Merge branch 'profile-feature'
|
@ -1,8 +1,8 @@
|
|||
# This file is machine-generated - editing it directly is not advised
|
||||
|
||||
julia_version = "1.9.0"
|
||||
julia_version = "1.9.1"
|
||||
manifest_format = "2.0"
|
||||
project_hash = "829f3e210629ef04542eb44fc4cb5acdb74d23eb"
|
||||
project_hash = "09d33216e2516631ede3cbab2af65d3f95eb0598"
|
||||
|
||||
[[deps.Adapt]]
|
||||
deps = ["LinearAlgebra", "Requires"]
|
||||
|
@ -62,9 +62,9 @@ version = "1.3.1"
|
|||
|
||||
[[deps.CodecZlib]]
|
||||
deps = ["TranscodingStreams", "Zlib_jll"]
|
||||
git-tree-sha1 = "9c209fb7536406834aa938fb149964b985de6c83"
|
||||
git-tree-sha1 = "02aa26a4cf76381be7f66e020a3eddeb27b0a092"
|
||||
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
|
||||
[[deps.CommonMark]]
|
||||
deps = ["Crayons", "JSON", "PrecompileTools", "URIs"]
|
||||
|
@ -74,9 +74,9 @@ version = "0.8.12"
|
|||
|
||||
[[deps.Compat]]
|
||||
deps = ["UUIDs"]
|
||||
git-tree-sha1 = "4e88377ae7ebeaf29a047aa1ee40826e0b708a5d"
|
||||
git-tree-sha1 = "5ce999a19f4ca23ea484e92a1774a61b8ca4cf8e"
|
||||
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
|
||||
version = "4.7.0"
|
||||
version = "4.8.0"
|
||||
weakdeps = ["Dates", "LinearAlgebra"]
|
||||
|
||||
[deps.Compat.extensions]
|
||||
|
@ -89,31 +89,36 @@ version = "1.0.2+0"
|
|||
|
||||
[[deps.ConcurrentUtilities]]
|
||||
deps = ["Serialization", "Sockets"]
|
||||
git-tree-sha1 = "96d823b94ba8d187a6d8f0826e731195a74b90e9"
|
||||
git-tree-sha1 = "5372dbbf8f0bdb8c700db5367132925c0771ef7e"
|
||||
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
|
||||
[[deps.Crayons]]
|
||||
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
|
||||
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
|
||||
version = "4.1.1"
|
||||
|
||||
[[deps.DBInterface]]
|
||||
git-tree-sha1 = "9b0dc525a052b9269ccc5f7f04d5b3639c65bca5"
|
||||
uuid = "a10d1c49-ce27-4219-8d33-6db1a4562965"
|
||||
version = "2.5.0"
|
||||
|
||||
[[deps.DataAPI]]
|
||||
git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c"
|
||||
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
|
||||
version = "1.15.0"
|
||||
|
||||
[[deps.DataFrames]]
|
||||
deps = ["Compat", "DataAPI", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SnoopPrecompile", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
|
||||
git-tree-sha1 = "aa51303df86f8626a962fccb878430cdb0a97eee"
|
||||
deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
|
||||
git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8"
|
||||
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
version = "1.5.0"
|
||||
version = "1.6.1"
|
||||
|
||||
[[deps.DataStructures]]
|
||||
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
|
||||
git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0"
|
||||
git-tree-sha1 = "cf25ccb972fec4e4817764d01c82386ae94f77b4"
|
||||
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||
version = "0.18.13"
|
||||
version = "0.18.14"
|
||||
|
||||
[[deps.DataValueInterfaces]]
|
||||
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
|
||||
|
@ -168,9 +173,9 @@ uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4"
|
|||
version = "0.1.9"
|
||||
|
||||
[[deps.ExprTools]]
|
||||
git-tree-sha1 = "c1d06d129da9f55715c6c212866f5b1bddc5fa00"
|
||||
git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec"
|
||||
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
|
||||
version = "0.1.9"
|
||||
version = "0.1.10"
|
||||
|
||||
[[deps.EzXML]]
|
||||
deps = ["Printf", "XML2_jll"]
|
||||
|
@ -193,12 +198,6 @@ version = "0.9.20"
|
|||
[[deps.FileWatching]]
|
||||
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
|
||||
|
||||
[[deps.Formatting]]
|
||||
deps = ["Printf"]
|
||||
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
|
||||
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
|
||||
version = "0.4.2"
|
||||
|
||||
[[deps.Future]]
|
||||
deps = ["Random"]
|
||||
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
|
||||
|
@ -257,9 +256,9 @@ version = "1.3.1"
|
|||
|
||||
[[deps.HTTP]]
|
||||
deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"]
|
||||
git-tree-sha1 = "2613d054b0e18a3dea99ca1594e9a3960e025da4"
|
||||
git-tree-sha1 = "cb56ccdd481c0dd7f975ad2b3b62d9eda088f7e2"
|
||||
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||
version = "1.9.7"
|
||||
version = "1.9.14"
|
||||
|
||||
[[deps.HttpCommon]]
|
||||
deps = ["Dates", "Nullables", "Test", "URIParser"]
|
||||
|
@ -339,6 +338,12 @@ git-tree-sha1 = "5b62d93f2582b09e469b3099d839c2d2ebf5066d"
|
|||
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
|
||||
version = "1.13.1"
|
||||
|
||||
[[deps.JWTs]]
|
||||
deps = ["Base64", "Downloads", "JSON", "MbedTLS", "Random"]
|
||||
git-tree-sha1 = "a1f3ded6307ef85cc18dec93d9b993814eb4c1a0"
|
||||
uuid = "d850fbd6-035d-5a70-a269-1ca2e636ac6c"
|
||||
version = "0.2.2"
|
||||
|
||||
[[deps.JuliaFormatter]]
|
||||
deps = ["CSTParser", "CommonMark", "DataStructures", "Glob", "Pkg", "PrecompileTools", "Tokenize"]
|
||||
git-tree-sha1 = "60567b51bd9e1e19ae2fd8a54dcd6bc5994727f0"
|
||||
|
@ -386,10 +391,10 @@ deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
|
|||
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
||||
|
||||
[[deps.LibPQ]]
|
||||
deps = ["CEnum", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Infinity", "Intervals", "IterTools", "LayerDicts", "LibPQ_jll", "Libdl", "Memento", "OffsetArrays", "SQLStrings", "Tables", "TimeZones", "UTCDateTimes"]
|
||||
git-tree-sha1 = "114d9d239ab8e1251354ad6bb97ed38622133114"
|
||||
deps = ["CEnum", "DBInterface", "Dates", "Decimals", "DocStringExtensions", "FileWatching", "Infinity", "Intervals", "IterTools", "LayerDicts", "LibPQ_jll", "Libdl", "Memento", "OffsetArrays", "SQLStrings", "Tables", "TimeZones", "UTCDateTimes"]
|
||||
git-tree-sha1 = "d8967f68674aa9ad4b9b3df114e3842f269ac147"
|
||||
uuid = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1"
|
||||
version = "1.15.1"
|
||||
version = "1.16.0"
|
||||
|
||||
[[deps.LibPQ_jll]]
|
||||
deps = ["Artifacts", "JLLWrappers", "Kerberos_krb5_jll", "Libdl", "OpenSSL_jll", "Pkg"]
|
||||
|
@ -519,9 +524,9 @@ version = "1.0.0"
|
|||
|
||||
[[deps.OffsetArrays]]
|
||||
deps = ["Adapt"]
|
||||
git-tree-sha1 = "82d7c9e310fe55aa54996e6f7f94674e2a38fcb4"
|
||||
git-tree-sha1 = "2ac17d29c523ce1cd38e27785a7d23024853a4bb"
|
||||
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
|
||||
version = "1.12.9"
|
||||
version = "1.12.10"
|
||||
|
||||
[[deps.OpenBLAS_jll]]
|
||||
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
|
||||
|
@ -552,9 +557,9 @@ uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
|
|||
version = "0.5.5+0"
|
||||
|
||||
[[deps.OrderedCollections]]
|
||||
git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282"
|
||||
git-tree-sha1 = "2e73fe17cac3c62ad1aebe70d44c963c3cfdc3e3"
|
||||
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
||||
version = "1.6.0"
|
||||
version = "1.6.2"
|
||||
|
||||
[[deps.Parameters]]
|
||||
deps = ["OrderedCollections", "UnPack"]
|
||||
|
@ -564,9 +569,9 @@ version = "0.12.3"
|
|||
|
||||
[[deps.Parsers]]
|
||||
deps = ["Dates", "PrecompileTools", "UUIDs"]
|
||||
git-tree-sha1 = "4b2e829ee66d4218e0cef22c0a64ee37cf258c29"
|
||||
git-tree-sha1 = "716e24b21538abc91f6205fd1d8363f39b442851"
|
||||
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
|
||||
[[deps.Pkg]]
|
||||
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
|
||||
|
@ -608,10 +613,10 @@ uuid = "21216c6a-2e73-6563-6e65-726566657250"
|
|||
version = "1.4.0"
|
||||
|
||||
[[deps.PrettyTables]]
|
||||
deps = ["Crayons", "Formatting", "LaTeXStrings", "Markdown", "Reexport", "StringManipulation", "Tables"]
|
||||
git-tree-sha1 = "213579618ec1f42dea7dd637a42785a608b1ea9c"
|
||||
deps = ["Crayons", "LaTeXStrings", "Markdown", "Printf", "Reexport", "StringManipulation", "Tables"]
|
||||
git-tree-sha1 = "ee094908d720185ddbdc58dbe0c1cbe35453ec7a"
|
||||
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
|
||||
version = "2.2.4"
|
||||
version = "2.2.7"
|
||||
|
||||
[[deps.Printf]]
|
||||
deps = ["Unicode"]
|
||||
|
@ -701,12 +706,6 @@ git-tree-sha1 = "874e8867b33a00e784c8a7e4b60afe9e037b74e1"
|
|||
uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7"
|
||||
version = "1.1.0"
|
||||
|
||||
[[deps.SnoopPrecompile]]
|
||||
deps = ["Preferences"]
|
||||
git-tree-sha1 = "e760a70afdcd461cf01a575947738d359234665c"
|
||||
uuid = "66db9d55-30c0-4569-8b51-7e840670fc0c"
|
||||
version = "1.0.3"
|
||||
|
||||
[[deps.Sockets]]
|
||||
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
||||
|
||||
|
@ -739,9 +738,9 @@ version = "1.9.0"
|
|||
|
||||
[[deps.StringEncodings]]
|
||||
deps = ["Libiconv_jll"]
|
||||
git-tree-sha1 = "33c0da881af3248dafefb939a21694b97cfece76"
|
||||
git-tree-sha1 = "b765e46ba27ecf6b44faf70df40c57aa3a547dcb"
|
||||
uuid = "69024149-9ee7-55f6-a4c4-859efe599b68"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
|
||||
[[deps.StringManipulation]]
|
||||
git-tree-sha1 = "46da2434b41f41ac3594ee9816ce5541c6096123"
|
||||
|
@ -765,10 +764,10 @@ uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
|
|||
version = "1.0.3"
|
||||
|
||||
[[deps.TableShowUtils]]
|
||||
deps = ["DataValues", "Dates", "JSON", "Markdown", "Test"]
|
||||
git-tree-sha1 = "14c54e1e96431fb87f0d2f5983f090f1b9d06457"
|
||||
deps = ["DataValues", "Dates", "JSON", "Markdown", "Unicode"]
|
||||
git-tree-sha1 = "2a41a3dedda21ed1184a47caab56ed9304e9a038"
|
||||
uuid = "5e66a065-1f0a-5976-b372-e0b8c017ca10"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
|
||||
[[deps.TableTraits]]
|
||||
deps = ["IteratorInterfaceExtensions"]
|
||||
|
@ -810,9 +809,9 @@ version = "1.0.1"
|
|||
|
||||
[[deps.TimeZones]]
|
||||
deps = ["Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "RecipesBase", "Scratch", "Unicode"]
|
||||
git-tree-sha1 = "cdaa0c2a4449724aded839550eca7d7240bb6938"
|
||||
git-tree-sha1 = "5b347464bdac31eccfdbe1504d9484c31645cafc"
|
||||
uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
|
||||
[[deps.Tokenize]]
|
||||
git-tree-sha1 = "90538bf898832b6ebd900fa40f223e695970e3a5"
|
||||
|
@ -880,7 +879,7 @@ version = "1.2.13+0"
|
|||
[[deps.libblastrampoline_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
|
||||
version = "5.7.0+0"
|
||||
version = "5.8.0+0"
|
||||
|
||||
[[deps.nghttp2_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
|
|
|
@ -4,6 +4,7 @@ authors = ["a-ill <a_ill@outlook.com>"]
|
|||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
CSVFiles = "5d742f6a-9f54-50ce-8119-2520741973ca"
|
||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
|
@ -15,6 +16,7 @@ GenieSession = "03cc5b98-4f21-4eb6-99f2-22eced81f962"
|
|||
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
||||
Inflector = "6d011eab-0732-4556-8808-e463c76bf3b6"
|
||||
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
|
||||
JWTs = "d850fbd6-035d-5a70-a269-1ca2e636ac6c"
|
||||
LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1"
|
||||
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
<!--<loadscreen-component></loadscreen-component>-->
|
||||
|
||||
<div id="content">
|
||||
<navbar-component></navbar-component>
|
||||
<% if authenticated() %>
|
||||
<navbar-logged></navbar-logged>
|
||||
<% else %>
|
||||
<navbar-not-logged></navbar-not-logged>
|
||||
<% end %>
|
||||
|
||||
<%@yield%>
|
||||
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
module AuthenticationController
|
||||
|
||||
using Genie, Genie.Requests, Genie.Renderer, Genie.Renderer.Json, Genie.Renderer.Html, GenieSession, SearchLight, GenieAuthentication, GenieAuthorisation
|
||||
using Logging
|
||||
using JSON3, Random, Base64, HTTP, Dates
|
||||
using Server.Users, Server.EmailSupport, Server.TemplateEditor, Server.Cookies, Server.DatabaseSupport
|
||||
import Server.TemplateEditor.generate_layout_html
|
||||
import Server.DatabaseSupport.select_from_table
|
||||
using JWTs
|
||||
|
||||
#---Helpers----------------------------------------------------------
|
||||
|
||||
const keyset = JWKSet("https://www.googleapis.com/oauth2/v3/certs")
|
||||
refresh!(keyset)
|
||||
|
||||
current_user() = findone(Users.User, id = get_authentication())
|
||||
|
||||
function send_signup_confirmation_email(receiver,confirmation_code)
|
||||
subject,message = ["Sign-up confirmation","Hello!\r\nYour confirmation code is "*confirmation_code*"\r\n"]
|
||||
message = "Content-Type: text/html\r\n"*message
|
||||
return send_email(receiver,subject,message)
|
||||
end
|
||||
|
||||
function register_google()
|
||||
jws = rawpayload()
|
||||
jws_split = split(jws,".")
|
||||
payload_encoded = jws_split[2]
|
||||
rem = length(payload_encoded)%4
|
||||
if rem!= 0
|
||||
payload_encoded = payload_encoded* "="^(4-rem)
|
||||
end
|
||||
payload = String(base64decode(payload_encoded))
|
||||
json = JSON3.read(payload)
|
||||
sub = json[:sub]
|
||||
email = json[:email]
|
||||
user = findone(User, email = email)
|
||||
if isnothing(user)
|
||||
# ENABLE WHEN IN PRODUCTION
|
||||
user = User(email = email,google_id = sub) |> save!
|
||||
authenticate(user.id, GenieSession.session(params()))
|
||||
assign_role(user, findone(Role, name = "free"))
|
||||
save(user)
|
||||
return true
|
||||
return 0
|
||||
else
|
||||
jwt = JWT(payload="")
|
||||
jwt.header = jws_split[1]
|
||||
jwt.payload = jws_split[2]
|
||||
jwt.signature = jws_split[3]
|
||||
if validate!(jwt, keyset)
|
||||
if user.google_id==""
|
||||
user.google_id = sub
|
||||
save(user)
|
||||
authenticate(user.id, GenieSession.session(params()))
|
||||
return 3
|
||||
elseif user.google_id==sub
|
||||
authenticate(user.id, GenieSession.session(params()))
|
||||
return 3
|
||||
else
|
||||
return 0
|
||||
end
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function get_locale()
|
||||
data = payload()
|
||||
if :locale in keys(data)
|
||||
return data[:locale]
|
||||
else
|
||||
return "en"
|
||||
end
|
||||
end
|
||||
|
||||
const auth_info = Dict(
|
||||
"en" => Dict(
|
||||
:title => "LibSoc - Login/Sign Up",
|
||||
:description => ""
|
||||
),
|
||||
"ru" => Dict(
|
||||
:title => "LibSoc - Логин/Регистрация",
|
||||
:description => ""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
#---Routing functions---------------------------------------------------
|
||||
|
||||
controller = "authentication"
|
||||
const dict_layouts = Dict(
|
||||
:auth => generate_layout_html("main",controller,"auth",libraries=["GoogleAuth"]),
|
||||
:profile => generate_layout_html("main",controller,"profile",libraries=["Leaflet"]),
|
||||
:email_confirmation => generate_layout_html("main",controller,"email_confirmation"),
|
||||
)
|
||||
|
||||
function auth()
|
||||
locale = get_locale()
|
||||
set_cookies(params())
|
||||
html(:authentication,:auth, layout = dict_layouts[:auth], context = @__MODULE__,
|
||||
title = auth_info[locale][:title],
|
||||
description = auth_info[locale][:description]
|
||||
)
|
||||
end
|
||||
|
||||
function profile()
|
||||
set_cookies(params())
|
||||
html(:authentication,:profile, layout = dict_layouts[:profile], context = @__MODULE__,
|
||||
title = "Chiron | Profile",
|
||||
description = ""
|
||||
)
|
||||
end
|
||||
|
||||
function email_confirmation()
|
||||
set_cookies(params())
|
||||
html(:authentication,:email_confirmation, layout = dict_layouts[:email_confirmation], context = @__MODULE__,
|
||||
title = "Chiron | Email Confirmation",
|
||||
description = ""
|
||||
)
|
||||
end
|
||||
|
||||
function confirm_email()
|
||||
code = rawpayload()
|
||||
user = current_user()
|
||||
if code==user.confirmation_code
|
||||
GenieAuthorisation.Relationship!(user, findone(Role, name = "unconfirmed")) |> delete
|
||||
assign_role(user, findone(Role, name = "free"))
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function register()
|
||||
data = jsonpayload()
|
||||
user = findone(User, email = data["email"])
|
||||
if isnothing(user)
|
||||
user = User(email = data["email"],
|
||||
password = data["password"] |> Users.hash_password,
|
||||
) |> save!
|
||||
authenticate(user.id, GenieSession.session(params()))
|
||||
assign_role(user, findone(Role, name = "free"))
|
||||
confirmation_code = randstring('0':'9', 5)
|
||||
user.confirmation_code = confirmation_code
|
||||
save(user)
|
||||
#send_signup_confirmation_email(data["email"],confirmation_code)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function login()
|
||||
data = jsonpayload()
|
||||
user = findone(User, email = data["email"])
|
||||
if isnothing(user)
|
||||
return 0
|
||||
else
|
||||
if (user.password==Users.hash_password(data["password"]))
|
||||
authenticate(user.id, GenieSession.session(params()))
|
||||
return 2
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function logout()
|
||||
deauthenticate(GenieSession.session(params()))
|
||||
return
|
||||
end
|
||||
|
||||
function change_user()
|
||||
data = jsonpayload()
|
||||
user = findone(Users.User, id = get_authentication())
|
||||
for (field,value) in data
|
||||
setfield!(user, Symbol(field), value)
|
||||
end
|
||||
save(user)
|
||||
return JSON3.write(true)
|
||||
end
|
||||
|
||||
function get_user()
|
||||
try
|
||||
user = findone(Users.User, id = get_authentication())
|
||||
return JSON3.write(user)
|
||||
catch ex
|
||||
return JSON3.write(false)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
<auth-component></auth-component>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<confirmation-component></confirmation-component>
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
<profile-component></profile-component>
|
|
@ -1,6 +1,6 @@
|
|||
module BasicController
|
||||
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests, GenieAuthentication
|
||||
using JSON3
|
||||
using SearchLight
|
||||
using Server.DatabaseSupport, Server.TemplateEditor
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module CommunesController
|
||||
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests, GenieAuthentication
|
||||
using JSON3
|
||||
using SearchLight
|
||||
using Server.DatabaseSupport, Server.TemplateEditor
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module CooperativesController
|
||||
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests, GenieAuthentication
|
||||
using JSON3
|
||||
using SearchLight
|
||||
using Server.DatabaseSupport, Server.TemplateEditor
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
module GroupsController
|
||||
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests, GenieAuthentication, DataFrames
|
||||
using JSON3
|
||||
using SearchLight
|
||||
using Server.DatabaseSupport, Server.TemplateEditor
|
||||
using SearchLight,SearchLightPostgreSQL, LibPQ, JSON3
|
||||
using Server.DatabaseSupport, Server.TemplateEditor, Server.Users
|
||||
import Server.DatabaseSupport: select_from_table, insert_into_table, delete_from_table, exist_in_table
|
||||
|
||||
controller = "groups"
|
||||
dict_layouts = Dict(
|
||||
|
@ -33,8 +34,61 @@ function get_locale()
|
|||
end
|
||||
end
|
||||
|
||||
#---Helpers-----------------------------------------------------------
|
||||
|
||||
|
||||
function table_to_json(name,df)
|
||||
ar = []
|
||||
for df_row in eachrow(df)
|
||||
dict = Dict()
|
||||
for id in names(df_row)
|
||||
dict[id] = df_row[id]
|
||||
end
|
||||
push!(ar,dict)
|
||||
end
|
||||
open("public/assets/"*name*".json", "w") do io
|
||||
JSON3.write(io, ar)
|
||||
end
|
||||
end
|
||||
|
||||
function compile(name)
|
||||
df = select_from_table([name => ["*"]])
|
||||
table_to_json(name,df)
|
||||
end
|
||||
|
||||
function move_requests(name)
|
||||
df_requests = select_from_table(["$(name)_requests" => ["*"]], where_data=["verified" => true, "added" => false])
|
||||
df = select_from_table([name => ["*"]])
|
||||
latitudes = df.latitude
|
||||
longitudes = df.longitude
|
||||
for df_row in eachrow(df_requests)
|
||||
ind_id_given = ismissing(df_row.id_given) ? nothing : findfirst(df_row.id_given.==df.id)
|
||||
if (!isnothing(ind_id_given))
|
||||
id = df[ind_id_given,:id]
|
||||
row_found = df[ind_id_given,Not(:id)]
|
||||
dict = Dict(zip(names(row_found),values(row_found)))
|
||||
dict["members"] += 1
|
||||
update_table(name,dict, where_data=["id" => id])
|
||||
else
|
||||
id = df_row.id
|
||||
dict_update = Dict("added" => true)
|
||||
update_table("$(name)_requests",dict_update, where_data=["id" => id])
|
||||
|
||||
df_row_to_add = df_row[Not(:id_given)]
|
||||
df_row_to_add = df_row_to_add[Not(:verified)]
|
||||
df_row_to_add = df_row_to_add[Not(:added)]
|
||||
df_row_to_add = df_row_to_add[Not(:id)]
|
||||
dict = Dict(zip(names(df_row_to_add),values(df_row_to_add)))
|
||||
dict["members"] = 1
|
||||
insert_into_table(name,dict)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#---Functions---------------------------------------------------------
|
||||
|
||||
current_user() = findone(Users.User, id = get_authentication())
|
||||
|
||||
function groups()
|
||||
locale = get_locale()
|
||||
html(:groups,:groups, layout = dict_layouts[:groups], context = @__MODULE__,
|
||||
|
@ -52,8 +106,156 @@ function groups_add()
|
|||
end
|
||||
|
||||
function groups_add_post()
|
||||
data = jsonpayload()
|
||||
data = copy(jsonpayload())
|
||||
mode = data["mode"]
|
||||
delete!(data,"mode")
|
||||
user = current_user()
|
||||
user_id = user.id
|
||||
if mode==0 # Create
|
||||
if user.verified
|
||||
existing_user_group_data = select_from_table(["users_groups" => ["*"]], where_data=["user_id" => user_id])
|
||||
has_group = !isempty(existing_user_group_data)
|
||||
delete!(data,"group_id")
|
||||
group_id = insert_into_table("groups",data, "RETURNING id")[1,1]
|
||||
if has_group
|
||||
user_groups_id = existing_user_group_data[1,"id"]
|
||||
prev_group_id = existing_user_group_data[1,"group_id"]
|
||||
update_table("users_groups",Dict("group_id" => group_id), where_data=["id" => user_groups_id])
|
||||
members = select_from_table(["groups" => ["members"]], where_data=["id" => prev_group_id])[1,1]
|
||||
if (members==1)
|
||||
delete_from_table("groups",["id" => prev_group_id])
|
||||
else
|
||||
update_table("groups",Dict("members" => members - 1), where_data=["id" => id])
|
||||
end
|
||||
else
|
||||
dict_users_groups = Dict("user_id" => user.id, "group_id" => group_id)
|
||||
insert_into_table("users_groups",dict_users_groups)
|
||||
end
|
||||
compile("groups")
|
||||
else
|
||||
data["status"] = 0
|
||||
data["user_id"] = user_id
|
||||
insert_into_table("groups_requests",data)
|
||||
end
|
||||
elseif mode==1 # Join
|
||||
data["user_id"] = user_id
|
||||
if exist_in_table("users_groups",["group_id" => data["group_id"]])
|
||||
if exist_in_table("groups_requests",["user_id" => user_id])
|
||||
delete_from_table("groups_requests",["user_id" => user_id])
|
||||
end
|
||||
data["status"] = 0
|
||||
insert_into_table("groups_requests",data)
|
||||
else
|
||||
group_id = data["group_id"]
|
||||
members = select_from_table("groups" => ["members"], where_data = ["id" => group_id])[1,1]
|
||||
dict = Dict("members" => members + 1)
|
||||
update_table("groups",dict, where_data=["id" => group_id])
|
||||
dict_users_groups = Dict("user_id" => user_id, "group_id" => group_id)
|
||||
insert_into_table("users_groups",dict_users_groups)
|
||||
end
|
||||
|
||||
elseif mode==2 # Move
|
||||
existing_user_group_data = select_from_table(["users_groups" => ["*"]], where_data=["user_id" => user_id])
|
||||
group_id = existing_user_group_data[1,"group_id"]
|
||||
delete!(data,"group_id")
|
||||
delete!(data,"members")
|
||||
delete!(data,"contact")
|
||||
update_table("groups",data, where_data=["id" => group_id])
|
||||
compile("groups")
|
||||
elseif mode==3 # Leave
|
||||
existing_user_group_data = select_from_table(["users_groups" => ["*"]], where_data=["user_id" => user_id])
|
||||
if size(existing_user_group_data,1)==0
|
||||
if exist_in_table("groups_requests",["user_id" => user_id])
|
||||
delete_from_table("groups_requests",["user_id" => user_id])
|
||||
end
|
||||
else
|
||||
delete_from_table("users_groups",["user_id" => user_id])
|
||||
end
|
||||
end
|
||||
return nothing
|
||||
end
|
||||
|
||||
function get_user_groups()
|
||||
local data_dicts
|
||||
user_id = get_authentication()
|
||||
groups_ids = select_from_table("users_groups" => ["group_id"], where_data = ["user_id" => user_id])[:,1]
|
||||
group_id = isempty(groups_ids) ? nothing : groups_ids[1]
|
||||
data_dicts = []
|
||||
if isnothing(group_id)
|
||||
local data
|
||||
data = select_from_table("groups_requests" => ["*"], where_data = ["user_id" => user_id,"status" => 0])
|
||||
if size(data,1)==0
|
||||
data = select_from_table("groups_requests" => ["*"], where_data = ["user_id" => user_id,"status" => 2])
|
||||
if size(data,1)!=0
|
||||
data = data[[end],:]
|
||||
end
|
||||
end
|
||||
for row in eachrow(data)
|
||||
dict = Dict(zip(names(row),values(row)))
|
||||
if (!ismissing(row["group_id"]))
|
||||
extra_data = select_from_table("groups" => ["*"], where_data = ["id" => row["group_id"]])
|
||||
merge!(dict, Dict(zip(names(extra_data[1,:]),values(extra_data[1,:]))))
|
||||
end
|
||||
push!(data_dicts, dict)
|
||||
end
|
||||
else
|
||||
group_data = select_from_table("groups" => ["*"], where_data = ["id" => group_id])
|
||||
ns = names(group_data)
|
||||
data_dicts = map(x -> Dict(zip(ns,values(x))),eachrow(group_data))
|
||||
end
|
||||
return JSON3.write(data_dicts)
|
||||
end
|
||||
|
||||
function get_group_requests()
|
||||
user_id = get_authentication()
|
||||
groups_ids = select_from_table("users_groups" => ["group_id"], where_data = ["user_id" => user_id])[:,1]
|
||||
group_id = isempty(groups_ids) ? nothing : groups_ids[1]
|
||||
data_dicts = []
|
||||
if !isnothing(group_id)
|
||||
user_ids = select_from_table("groups_requests" => ["user_id"], where_data = ["group_id" => group_id, "status" => 0])[:,1]
|
||||
for user2_id in user_ids
|
||||
email = select_from_table("users" => ["email"], where_data = ["id" => user2_id])[1,1]
|
||||
push!(data_dicts,Dict("email" => email, "user_id" => user2_id))
|
||||
end
|
||||
end
|
||||
return JSON3.write(data_dicts)
|
||||
end
|
||||
|
||||
function approve_request()
|
||||
data = copy(jsonpayload())
|
||||
user_id = get_authentication()
|
||||
groups_ids = select_from_table("users_groups" => ["group_id"], where_data = ["user_id" => user_id])[:,1]
|
||||
group_id = isempty(groups_ids) ? nothing : groups_ids[1]
|
||||
members = select_from_table("groups" => ["members"], where_data = ["id" => group_id])[1,1]
|
||||
dict = Dict("members" => members + 1)
|
||||
update_table("groups",dict, where_data=["id" => group_id])
|
||||
update_table("groups_requests",Dict("status" => 1), where_data=["group_id" => group_id, "user_id" => data["user_id"]])
|
||||
dict_users_groups = Dict("user_id" => data["user_id"], "group_id" => group_id)
|
||||
insert_into_table("users_groups",dict_users_groups)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function reject_request()
|
||||
data = copy(jsonpayload())
|
||||
user_id = get_authentication()
|
||||
groups_ids = select_from_table("users_groups" => ["group_id"], where_data = ["user_id" => user_id])[:,1]
|
||||
group_id = isempty(groups_ids) ? nothing : groups_ids[1]
|
||||
update_table("groups_requests",Dict("status" => 2), where_data=["group_id" => group_id, "user_id" => data["user_id"]])
|
||||
return nothing
|
||||
end
|
||||
|
||||
function add_verified_groups()
|
||||
groups_create_requests_verified = select_from_table("groups_requests" => ["*"], where_data = ["group_id" => nothing, "status" => 1])
|
||||
data = Dict(zip(names(groups_create_requests_verified),groups_create_requests_verified[end,:]))
|
||||
user_id = data["user_id"]
|
||||
delete!(data,"group_id")
|
||||
delete!(data,"user_id")
|
||||
delete!(data,"id")
|
||||
delete!(data,"status")
|
||||
group_id = insert_into_table("groups",data, "RETURNING id")[1,1]
|
||||
dict_users_groups = Dict("user_id" => user_id, "group_id" => group_id)
|
||||
insert_into_table("users_groups",dict_users_groups)
|
||||
delete_from_table("groups_requests",["user_id" => user_id])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module PartiesController
|
||||
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests, GenieAuthentication
|
||||
using JSON3
|
||||
using SearchLight
|
||||
using Server.DatabaseSupport, Server.TemplateEditor
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module PartnersController
|
||||
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests
|
||||
using Genie, Genie.Renderer, Genie.Renderer.Html, Genie.Requests, GenieAuthentication
|
||||
using JSON3
|
||||
using SearchLight
|
||||
using Server.DatabaseSupport, Server.TemplateEditor
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
module Users
|
||||
|
||||
using SearchLight, SearchLight.Validation, Server.UsersValidator
|
||||
using SHA
|
||||
using Random
|
||||
|
||||
export User
|
||||
|
||||
Base.@kwdef mutable struct User <: AbstractModel
|
||||
### FIELDS
|
||||
id::DbId = DbId()
|
||||
email::String = ""
|
||||
password::String = ""
|
||||
google_id::String = ""
|
||||
confirmation_code::String = ""
|
||||
verified::Bool = false
|
||||
end
|
||||
|
||||
Validation.validator(u::Type{User}) = ModelValidator([
|
||||
ValidationRule(:email, UsersValidator.not_empty),
|
||||
ValidationRule(:email, UsersValidator.unique),
|
||||
ValidationRule(:password, UsersValidator.not_empty)
|
||||
])
|
||||
|
||||
function hash_password(password::String)
|
||||
sha256(password) |> bytes2hex
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
module UsersValidator
|
||||
|
||||
using SearchLight, SearchLight.Validation, SearchLight.QueryBuilder
|
||||
|
||||
function not_empty(field::Symbol, m::T, args::Vararg{Any})::ValidationResult where {T<:AbstractModel}
|
||||
isempty(getfield(m, field)) && return ValidationResult(invalid, :not_empty, "should not be empty")
|
||||
|
||||
ValidationResult(valid)
|
||||
end
|
||||
|
||||
function unique(field::Symbol, m::T, args::Vararg{Any})::ValidationResult where {T<:AbstractModel}
|
||||
ispersisted(m) && return ValidationResult(valid) # don't validate updates
|
||||
|
||||
if SearchLight.count(typeof(m), where("$field = ?", getfield(m, field))) > 0
|
||||
return ValidationResult(invalid, :unique, "is already used")
|
||||
end
|
||||
|
||||
ValidationResult(valid)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,180 @@
|
|||
|
||||
label {
|
||||
font-size: 1.3rem;
|
||||
font-family: var(--sans-serif);
|
||||
}
|
||||
|
||||
.auth-pane {
|
||||
position: relative;
|
||||
padding: 3.4rem;
|
||||
padding-top: 3.4rem;
|
||||
padding-bottom: 3.4rem;
|
||||
width: 30rem;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.auth-title {
|
||||
position: relative;
|
||||
top: 0.2rem;
|
||||
margin-bottom: 2.7rem;
|
||||
}
|
||||
|
||||
.auth-label {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.authEmailInput, .authPasswordInput {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-radius: 0.34rem;
|
||||
color: #353535;
|
||||
height: 2.73rem;
|
||||
padding-left: 0.34rem;
|
||||
}
|
||||
|
||||
.authEmailInput {
|
||||
margin-bottom: 0.682rem;
|
||||
}
|
||||
|
||||
.auth-button {
|
||||
margin-top: 1.365rem;
|
||||
height: 3.412rem;
|
||||
width: 100%;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.3rem;
|
||||
color: white;
|
||||
background-color: var(--red);
|
||||
border-color: var(--red);
|
||||
border-radius: 0.512rem;
|
||||
filter: drop-shadow(0.068rem 0.136rem 0.068rem rgb(0 0 0 / 0.4));
|
||||
}
|
||||
|
||||
.auth-button:active {
|
||||
background-color: var(--darker-pink);
|
||||
}
|
||||
|
||||
#email-msg,#password-msg {
|
||||
display: inline;
|
||||
color:red;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
}
|
||||
|
||||
.auth-line {
|
||||
margin-top: 1.5rem;
|
||||
width: 100%;
|
||||
height: 0.07rem;
|
||||
border: 0;
|
||||
border-radius: 0.1rem;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.auth-methods-group {
|
||||
display: grid;
|
||||
grid-template-columns: auto ; /*auto auto*/
|
||||
justify-content: center;
|
||||
gap: 2.7rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.auth-methods-group img {
|
||||
height: auto;
|
||||
width: 3.4rem;
|
||||
}
|
||||
|
||||
.auth-methods-group> div {
|
||||
position: relative;
|
||||
border-radius: 6.8rem;
|
||||
width: 3.4rem;
|
||||
height: 3.4rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#google-btn {
|
||||
position: absolute;
|
||||
top: -0.8rem;
|
||||
left: -0.8rem;
|
||||
}
|
||||
|
||||
#google-logo {
|
||||
position: relative;
|
||||
background: white;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#google-btn-wrapper {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#google-btn div {
|
||||
position: absolute;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
#google-btn iframe {
|
||||
position: absolute;
|
||||
height: 10rem;
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.password-field {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.eye-icon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
opacity: 0.25;
|
||||
top: 2.6rem;
|
||||
right: 0.8rem;
|
||||
width: 1.7rem;
|
||||
}
|
||||
|
||||
.eye-icon * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#forgot-password {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
height: 2rem;
|
||||
color:#5f5f5f;
|
||||
margin-left: auto;
|
||||
width: max-content;
|
||||
font-family: var(--sans-serif);
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
|
||||
#remember-me {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 1rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#remember-me-checkbox {
|
||||
min-height: 1.5rem;
|
||||
min-width: 1.5rem;
|
||||
flex: 0;
|
||||
accent-color: var(--gray);
|
||||
}
|
||||
|
||||
#remember-me label {
|
||||
position: relative;
|
||||
margin-top: -0.2rem;
|
||||
color: #5f5f5f;
|
||||
}
|
||||
|
||||
#content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
|
@ -1,21 +1,7 @@
|
|||
|
||||
:root {
|
||||
--light-blue:hsl(195, 67%, 95%);
|
||||
--darker-pink:hsl(344, 60%, 47%);
|
||||
--pink:hsl(344, 73%, 57%);
|
||||
--dark-green:hsl(176, 63%, 25%);
|
||||
--green:hsl(147, 33%, 60%);
|
||||
--orange:hsl(30, 97%, 72%);
|
||||
--light-orange: hsl(19, 76%, 72%);
|
||||
--dark-brown:hsl(23, 47%, 20%);
|
||||
--brown:hsl(23, 47%, 30%);
|
||||
--light-brown: hsl(23, 47%, 50%);
|
||||
--dark-pink:hsl(343, 39%, 16%);
|
||||
--red:hsl(359, 72%, 61%);
|
||||
--dark-blue:hsl(217, 25%, 16%);
|
||||
--grey-blue:hsl(223, 13%, 22%);
|
||||
--cream:hsl(34, 43%, 90%);
|
||||
--dark-cream:hsl(33, 26%, 84%);
|
||||
--red:#c52a28;
|
||||
--gray: #5B6970;
|
||||
--sans-serif: "OpenSans";
|
||||
--serif: "Lora";
|
||||
}
|
||||
|
@ -48,12 +34,10 @@ body {
|
|||
|
||||
#content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
display: grid;
|
||||
grid-template-rows: max-content auto max-content;
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/*---Fonts---------------------------------------------------------*/
|
||||
|
@ -475,9 +459,8 @@ input[type=number]::-webkit-outer-spin-button {
|
|||
|
||||
.pane {
|
||||
background: white;
|
||||
border: 0;
|
||||
border: 0.1rem solid rgb(187, 187, 187);
|
||||
border-radius: 0.635rem;
|
||||
box-shadow: 0 0 0.314rem rgb(187, 187, 187);
|
||||
}
|
||||
|
||||
.pane-container {
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
/* Header */
|
||||
#navbar{
|
||||
position: relative;
|
||||
top: 0;
|
||||
width: min(100%,116rem);
|
||||
z-index: 1000000000;
|
||||
height: 5.26rem;
|
||||
padding-left: 0rem;
|
||||
padding-right: 0rem;
|
||||
}
|
||||
|
||||
#navbar * {
|
||||
font-family: var(--sans-serif, sans-serif);
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
#logo-container {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
margin-left: 1rem;
|
||||
height: 100%;
|
||||
max-height: 5.26rem;
|
||||
color: black;
|
||||
z-index: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#navbar-logo {
|
||||
height: 3.5rem;
|
||||
width: 3.5rem;
|
||||
object-fit: contain;
|
||||
border-radius: 10rem;
|
||||
}
|
||||
|
||||
#navbar-logo-text {
|
||||
position: relative;
|
||||
word-wrap: normal;
|
||||
height: 100%;
|
||||
line-height: 400%;
|
||||
font-size: 1.4rem;
|
||||
color: #292222;
|
||||
font-family: var(--sans-serif, sans-serif);
|
||||
font-weight: 400;
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
/* Nav menu */
|
||||
#nav {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
#menu > li > a, .options-button {
|
||||
display: block;
|
||||
padding: 1.2rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
color: black;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
#menu > li > a:active{
|
||||
|
||||
}
|
||||
|
||||
#menu li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#nav{
|
||||
max-height: 0;
|
||||
/*transition: max-height .5s ease-out;*/
|
||||
}
|
||||
|
||||
/* Menu Icon */
|
||||
#hamb{
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
right: 0rem;
|
||||
padding: 2.8rem 2rem;
|
||||
z-index: 9999;
|
||||
}/* Style label tag */
|
||||
|
||||
#hamb-line {
|
||||
background: black;
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: relative;
|
||||
width: 24px;
|
||||
|
||||
} /* Style span tag */
|
||||
|
||||
#hamb-line::before,
|
||||
#hamb-line::after{
|
||||
background: black;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
transition: all .2s ease-out;
|
||||
width: 100%;
|
||||
}
|
||||
#hamb-line::before{
|
||||
top: 5px;
|
||||
}
|
||||
#hamb-line::after{
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
#side-menu {
|
||||
display: none;
|
||||
} /* Hide checkbox */
|
||||
|
||||
/* Toggle menu icon */
|
||||
#side-menu:checked ~ nav {
|
||||
display: block;
|
||||
max-height: 100%;
|
||||
padding-top: 5.625rem;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #logo-container {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #logo-container {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line::before {
|
||||
transform: rotate(-45deg);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line::after {
|
||||
transform: rotate(45deg);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Options */
|
||||
|
||||
.options-dropdown {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 5.6rem;
|
||||
right: 1.8rem;
|
||||
border: #404040 solid 0.1rem;
|
||||
background-color: white;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.options-dropdown button, .options-dropdown a {
|
||||
display: block;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.2rem;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.options-dropdown button:hover, .options-dropdown a:hover {
|
||||
background-color: var(--red);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.options-button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Localization */
|
||||
|
||||
#locales {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#locales button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
#locales button:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#locales-img {
|
||||
position: relative;
|
||||
top: 0rem;
|
||||
height: 2rem;
|
||||
margin-left: 1.2rem;
|
||||
}
|
||||
|
||||
/*
|
||||
#options-dropdown>:first-child {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
#options-dropdown>:nth-child(2) {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Responsiveness */
|
||||
@media only screen and (min-width: 1200px) {
|
||||
|
||||
#navbar {
|
||||
position: relative;
|
||||
width: min(100%,116rem);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding-right: 4rem;
|
||||
padding-left: 4rem;
|
||||
}
|
||||
|
||||
#nav {
|
||||
max-height: none;
|
||||
top: 0;
|
||||
position: relative;
|
||||
float: right;
|
||||
width: fit-content;
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ nav {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#menu li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menu > li > a:hover, .options-button:hover, #navbar-logo-text:hover {
|
||||
color: rgb(127, 127, 127);
|
||||
}
|
||||
|
||||
#menu > li > a, .options-button {
|
||||
padding: 0.9rem;
|
||||
padding-top: 1.9rem;
|
||||
padding-bottom: 1.9rem;
|
||||
}
|
||||
|
||||
#hamb {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#locales {
|
||||
position: relative;
|
||||
margin-right: 1.8rem;
|
||||
}
|
||||
|
||||
#locales-img {
|
||||
top: 0.9rem;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#notifications-div>button {
|
||||
cursor: pointer;
|
||||
margin-left: 0.341rem;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(1) {
|
||||
width: 1.706rem;
|
||||
height: 1.706rem;
|
||||
background-color: #ccc;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(2) {
|
||||
width: 2.047rem;
|
||||
height: 2.047rem;
|
||||
background-color: #ccc;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(3) {
|
||||
width: 2.389rem;
|
||||
height: 2.389rem;
|
||||
background-color: #ccc;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>button>div {
|
||||
cursor: pointer;
|
||||
margin: auto;
|
||||
background-color: white;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(1)>div {
|
||||
width: 1.228rem;
|
||||
height: 1.228rem;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(2)>div {
|
||||
width: 1.57rem;
|
||||
height: 1.57rem;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(3)>div {
|
||||
width: 1.843rem;
|
||||
height: 1.843rem;
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1,163 @@
|
|||
|
||||
import {getData, sendData} from "/js/libraries/serverTools.js"
|
||||
|
||||
export function getUser(user,loaded,callbackOuter) {
|
||||
let callback = function(response) {
|
||||
Object.assign(user,JSON.parse(response))
|
||||
if(callbackOuter!=undefined) {
|
||||
callbackOuter()
|
||||
}
|
||||
loaded.update((val) => {
|
||||
return val + 1
|
||||
})
|
||||
}
|
||||
getData("/xx/get-user",callback)
|
||||
}
|
||||
|
||||
export function changeUser(name,value,user) {
|
||||
if (user[name]!=value && user[name]!=undefined) {
|
||||
user[name] = value
|
||||
let data = new Object();
|
||||
data[name] = value
|
||||
sendData("/xx/change-user",data)
|
||||
}
|
||||
}
|
||||
|
||||
export function changePasswordVisibility(button) {
|
||||
let input = button.previousElementSibling
|
||||
let type = input.type
|
||||
if (type=="text") {
|
||||
input.type = "password";
|
||||
button.style.opacity = 0.25
|
||||
}
|
||||
else {
|
||||
input.type = "text";
|
||||
button.style.opacity = 1
|
||||
}
|
||||
}
|
||||
|
||||
export function checkEmail(email,msg) {
|
||||
if (email.includes("@")) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
msg.innerHTML = "must contain '@'"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function checkPassword(password,msg) {
|
||||
let passwordLength = password.length
|
||||
if (passwordLength<8) {
|
||||
msg.innerHTML = "must be 8 characters"
|
||||
return false
|
||||
}
|
||||
let numNumbers = password.match(/\d/g)?.length || 0;
|
||||
if (numNumbers<1) {
|
||||
msg.innerHTML = "mush have digits"
|
||||
return false
|
||||
}
|
||||
let numLetters = password.match(/\D/g)?.length || 0;
|
||||
if (numLetters<2) {
|
||||
msg.innerHTML = "must have letters"
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export function redirectLogged() {
|
||||
let callback = function(responseText) {
|
||||
let response = JSON.parse(responseText)
|
||||
if (response) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
}
|
||||
getData("/xx/check-login",callback)
|
||||
}
|
||||
|
||||
export function redirectNotLogged() {
|
||||
let callback = function(responseText) {
|
||||
let response = JSON.parse(responseText)
|
||||
if (!response) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
}
|
||||
getData("/xx/check-login",callback)
|
||||
}
|
||||
|
||||
// Redirect to the landing page
|
||||
export function toLandingPage(response) {
|
||||
if (response!=0) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to the dashboard page
|
||||
export function toDashboard() {
|
||||
window.location.href = "/";
|
||||
}
|
||||
|
||||
// Process log in
|
||||
export function processLoginResponse(response,msgs,remember) {
|
||||
if (response==0) {
|
||||
msgs.email.innerHTML = "not found"
|
||||
}
|
||||
else if (response==1) {
|
||||
msgs.password.innerHTML = "is wrong"
|
||||
}
|
||||
else {
|
||||
if (remember) {
|
||||
let date = new Date()
|
||||
date.setMonth(date.getMonth()+1)
|
||||
date = date.toUTCString()
|
||||
document.cookie = "__genierememberme=; expires=" + date + "; path=/;SameSite=Lax";
|
||||
}
|
||||
toDashboard()
|
||||
}
|
||||
}
|
||||
|
||||
// Log in
|
||||
export function login(msgs,inputs) {
|
||||
msgs.email.innerHTML = ""
|
||||
msgs.password.innerHTML = ""
|
||||
let data = {email: inputs.email.value, password: inputs.password.value, remember: inputs.remember.checked}
|
||||
sendData('/xx/login-post', data, (response) => processLoginResponse(response,msgs,inputs.remember.checked))
|
||||
}
|
||||
|
||||
// Process sign in
|
||||
function processSignupResponse(response,msgs) {
|
||||
if (response) {
|
||||
toDashboard()
|
||||
}
|
||||
else {
|
||||
msgs.email.innerHTML = "already exists"
|
||||
}
|
||||
}
|
||||
|
||||
// Sign up
|
||||
export function signup(msgs,inputs) {
|
||||
msgs.email.innerHTML = ""
|
||||
let email = inputs.email.value
|
||||
let password = inputs.password.value
|
||||
if (checkEmail(email,msgs.email)==false) {
|
||||
return
|
||||
}
|
||||
if (checkPassword(password,msgs.password)==false) {
|
||||
return
|
||||
}
|
||||
let data = {email: email, password: password}
|
||||
sendData('/xx/signup-post', data, (response) => processSignupResponse(response,msgs))
|
||||
}
|
||||
|
||||
export function confirmEmail(msg,code,callback) {
|
||||
msg.innerHTML = ""
|
||||
sendData('xx/confirm-email',code,callback)
|
||||
}
|
||||
|
||||
// Log out
|
||||
export function logout() {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open( "GET", "/logout", false ); // false for synchronous request
|
||||
xmlHttp.send( null );
|
||||
window.location.href = "/";
|
||||
}
|
|
@ -10,7 +10,7 @@ export function translate(content, x) {
|
|||
}
|
||||
}
|
||||
|
||||
function addMarkersToLayer(g,layer,content,locale,addPinContent,markerColor) {
|
||||
function addMarkersToLayer(g,layer,content,locale,addPinContent,markerColor,options) {
|
||||
let {text,coordinates} = addPinContent(g,content,locale)
|
||||
var markerIcon = new L.Icon({
|
||||
iconUrl: 'https://www.libsoc.org/img/common/markers/marker-' + markerColor + '.png',
|
||||
|
@ -21,24 +21,32 @@ function addMarkersToLayer(g,layer,content,locale,addPinContent,markerColor) {
|
|||
shadowSize: [41, 41]
|
||||
})
|
||||
let marker = L.marker(coordinates, {icon: markerIcon})
|
||||
marker.id = g.id
|
||||
marker.members = g.members
|
||||
marker.contact = g.contact
|
||||
marker.addTo(layer).bindPopup(text)
|
||||
|
||||
if (options.pinCallback!=undefined) {
|
||||
marker.on('click', (event) => options.pinCallback(marker,event))
|
||||
}
|
||||
}
|
||||
|
||||
export function addMarkersEntries(entries,entriesByCountry,map,content,locale,addPinContent,markerColor) {
|
||||
export function addMarkersEntries(entries,entriesByCountry,map,content,locale,addPinContent,markerColor,options) {
|
||||
let entriesMarkersLayer = L.layerGroup()
|
||||
let entriesMarkersLayerOut = L.layerGroup()
|
||||
let entriesMarkersLayerIn = L.layerGroup()
|
||||
for (let g of entries) {
|
||||
if (g.country!="Online" && g.country!="Worldwide") {
|
||||
addMarkersToLayer(g,entriesMarkersLayerIn,content,locale,addPinContent,markerColor)
|
||||
addMarkersToLayer(g,entriesMarkersLayerIn,content,locale,addPinContent,markerColor,options)
|
||||
}
|
||||
}
|
||||
if (options.enableCountryGrouping) {
|
||||
for (let gs of Object.values(entriesByCountry)) {
|
||||
if (gs.length==1) {
|
||||
let g = {...gs[0]}
|
||||
g.country = [g.country]
|
||||
if (g.country!="Online" && g.country!="Worldwide") {
|
||||
addMarkersToLayer(g,entriesMarkersLayerOut,content,locale,addPinContent,markerColor)
|
||||
addMarkersToLayer(g,entriesMarkersLayerOut,content,locale,addPinContent,markerColor,options)
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -64,14 +72,18 @@ export function addMarkersEntries(entries,entriesByCountry,map,content,locale,ad
|
|||
members: members,
|
||||
contact: contact
|
||||
}
|
||||
addMarkersToLayer(gNew,entriesMarkersLayerOut,content,locale,addPinContent,markerColor)
|
||||
addMarkersToLayer(gNew,entriesMarkersLayerOut,content,locale,addPinContent,markerColor,options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entriesMarkersLayerOut.addTo(entriesMarkersLayer)
|
||||
entriesMarkersLayer.addTo(map)
|
||||
map.on("zoomend", () => onZoomEnd(map,entriesMarkersLayer,entriesMarkersLayerOut,entriesMarkersLayerIn))
|
||||
}
|
||||
else {
|
||||
entriesMarkersLayerIn.addTo(entriesMarkersLayer)
|
||||
}
|
||||
entriesMarkersLayer.addTo(map)
|
||||
|
||||
return entriesMarkersLayer
|
||||
}
|
||||
|
||||
|
|
|
@ -7,5 +7,7 @@
|
|||
"communes": "Communes",
|
||||
"cooperatives": "Cooperatives",
|
||||
"parties": "Parties",
|
||||
"partners": "Partners"
|
||||
"partners": "Partners",
|
||||
"login": "Login",
|
||||
"profile": "Profile"
|
||||
}
|
|
@ -10,6 +10,7 @@ import watch from "rollup-plugin-watch";
|
|||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
|
||||
function serve() {
|
||||
let server;
|
||||
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
<svelte:options tag="auth-component" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount, setContext,getContext } from 'svelte'
|
||||
import { sendText } from "/js/libraries/serverTools.js"
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
import "/js/components/login-component.js"
|
||||
import "/js/components/signup-component.js"
|
||||
|
||||
// Main code
|
||||
AuthTools.redirectLogged()
|
||||
|
||||
let loginComponent
|
||||
let signupComponent
|
||||
|
||||
let context = {
|
||||
googleInit: false
|
||||
}
|
||||
setContext("auth",context)
|
||||
|
||||
function switchFocus(component) {
|
||||
if (component==loginComponent) {
|
||||
loginComponent.focused = true
|
||||
signupComponent.focused = false
|
||||
}
|
||||
else {
|
||||
loginComponent.focused = false
|
||||
signupComponent.focused = true
|
||||
}
|
||||
}
|
||||
|
||||
function callbackGoogle(data) {
|
||||
console.log(data)
|
||||
sendText("/signup-google",data.credential,(response) => AuthTools.processLoginResponse(response,context.msgs,context.remember.checked))
|
||||
}
|
||||
|
||||
function initGoogle() {
|
||||
if (typeof google != 'undefined') {
|
||||
google.accounts.id.initialize({
|
||||
client_id: '93612176787-sr8qjqem4e3kok4msrnj8s1illt85a9g.apps.googleusercontent.com',
|
||||
callback: callbackGoogle,
|
||||
auto_select: true,
|
||||
context: "signin"
|
||||
})
|
||||
context.googleInit = true
|
||||
}
|
||||
else {
|
||||
setTimeout(initGoogle,100)
|
||||
}
|
||||
}
|
||||
|
||||
initGoogle()
|
||||
|
||||
</script>
|
||||
|
||||
<div id="auth-group">
|
||||
<div id="auth-grid-group">
|
||||
<login-component bind:this={loginComponent} on:click={() => switchFocus(loginComponent)} on:keydown={() => ""}></login-component>
|
||||
<signup-component bind:this={signupComponent} on:click={() => switchFocus(signupComponent)} on:keydown={() => ""}></signup-component>
|
||||
</div>
|
||||
<div id="auth-or" class="pane">
|
||||
<span>OR</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@import '/css/common.css';
|
||||
@import '/css/auth.css';
|
||||
|
||||
span {
|
||||
font-size: 1.4rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
}
|
||||
|
||||
#auth-group {
|
||||
margin: auto;
|
||||
width: auto;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
#auth-grid-group {
|
||||
display: grid;
|
||||
grid-template-columns: 30rem 30rem;
|
||||
justify-content: center;
|
||||
gap: 1.37rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#auth-or {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
top: 40%;/*40%;*/
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 5.4rem;
|
||||
height: 5.4rem;
|
||||
border-radius: 6.8rem;
|
||||
background-color: white;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#auth-grid-group {
|
||||
display: grid;
|
||||
grid-template-columns: 30rem;
|
||||
grid-template-rows: auto auto;
|
||||
justify-content: center;
|
||||
gap: 1.37rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#auth-or {
|
||||
top: 40rem;/*46.4rem;*/
|
||||
}
|
||||
|
||||
#auth-group {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -0,0 +1,131 @@
|
|||
<svelte:options tag="confirmation-component" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
// Export statements
|
||||
|
||||
// Main code
|
||||
let confirmationInputs = []
|
||||
let confirmationMsg
|
||||
let confirmationButton
|
||||
|
||||
function onlyNumberKey(ind,evt) {
|
||||
// Only ASCII character in that range allowed
|
||||
var value = evt.data
|
||||
if (value in ["0","1","2","3","4","5","6","7","8","9"]) {
|
||||
if (ind<4) {
|
||||
confirmationInputs[ind+1].focus()
|
||||
}
|
||||
else {
|
||||
AuthTools.confirmEmail(confirmationMsg,getCode(),callback)
|
||||
}
|
||||
}
|
||||
else {
|
||||
confirmationInputs[ind].value = ""
|
||||
}
|
||||
}
|
||||
|
||||
function getCode() {
|
||||
let code = ""
|
||||
for (let input of confirmationInputs) {
|
||||
code += input.value
|
||||
}
|
||||
return parseInt(code)
|
||||
}
|
||||
|
||||
function callback(response) {
|
||||
if (response=="true") {
|
||||
AuthTools.toDashboard()
|
||||
}
|
||||
else {
|
||||
confirmationMsg.innerHTML = "Wrong code"
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<div class="pane auth-pane">
|
||||
<h2 class="auth-title title-highlight">CONFIRMATION CODE</h2>
|
||||
<div id="confirmationInputs">
|
||||
<input bind:this={confirmationInputs[0]} class="authConfirmationInput" type="text" maxlength="1" on:input={(evt) => onlyNumberKey(0,evt)}><span class="dash">-</span>
|
||||
<input bind:this={confirmationInputs[1]} class="authConfirmationInput" type="text" maxlength="1" on:input={(evt) => onlyNumberKey(1,evt)}><span class="dash">-</span>
|
||||
<input bind:this={confirmationInputs[2]} class="authConfirmationInput" type="text" maxlength="1" on:input={(evt) => onlyNumberKey(2,evt)}><span class="dash">-</span>
|
||||
<input bind:this={confirmationInputs[3]} class="authConfirmationInput" type="text" maxlength="1" on:input={(evt) => onlyNumberKey(3,evt)}><span class="dash">-</span>
|
||||
<input bind:this={confirmationInputs[4]} class="authConfirmationInput" type="text" maxlength="1" on:input={(evt) => onlyNumberKey(4,evt)}>
|
||||
</div>
|
||||
<span bind:this={confirmationMsg} id="confirmation-msg"></span>
|
||||
<button bind:this={confirmationButton} class="auth-button" on:click="{() => AuthTools.confirmEmail(confirmationMsg,getCode(),callback)}">Confirm</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
|
||||
.auth-pane {
|
||||
position: relative;
|
||||
padding: 3.4rem;
|
||||
padding-top: 5.5rem;
|
||||
padding-bottom: 5.5rem;
|
||||
width: 33rem;
|
||||
height: auto;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.auth-title {
|
||||
position: relative;
|
||||
left: 0.7rem;
|
||||
top: 0.2rem;
|
||||
margin-bottom: 1.4rem;
|
||||
}
|
||||
|
||||
.authConfirmationInput {
|
||||
position: relative;
|
||||
width: 3.16rem;
|
||||
font-family: var(--serif,serif);
|
||||
font-size: 3rem;
|
||||
border-radius: 0.34rem;
|
||||
margin-bottom: 0.7rem;
|
||||
text-align: center;
|
||||
padding-left: 0;
|
||||
padding-bottom: 0.3 rem;
|
||||
}
|
||||
|
||||
.dash {
|
||||
display: block;
|
||||
font-size: 3rem;
|
||||
font-family: var(--serif,serif);
|
||||
}
|
||||
|
||||
#confirmationInputs {
|
||||
margin: auto;
|
||||
display: grid;
|
||||
justify-content: space-between;
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
|
||||
.auth-button {
|
||||
margin-top: 1.4rem;
|
||||
height: 3.4rem;
|
||||
width: 100%;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.6rem;
|
||||
color: white;
|
||||
background-color: var(--pink);
|
||||
border-color: var(--pink);
|
||||
border-radius: 0.5rem;
|
||||
filter: drop-shadow(0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
|
||||
}
|
||||
|
||||
#confirmation-msg {
|
||||
display: inline;
|
||||
color:red;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,110 @@
|
|||
<svelte:options tag="login-component" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount, getContext } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
// Export statements
|
||||
export let focused = false
|
||||
|
||||
// Main code
|
||||
|
||||
let emailInput
|
||||
let passwordInput
|
||||
let inputs
|
||||
|
||||
let passwordVisibilityButton
|
||||
|
||||
let emailMsg
|
||||
let passwordMsg
|
||||
let msgs
|
||||
let rememberMe
|
||||
|
||||
let googleButton
|
||||
|
||||
let parentProps = getContext("auth")
|
||||
|
||||
function renderGoogle() {
|
||||
if (parentProps.googleInit) {
|
||||
google.accounts.id.renderButton(googleButton,{
|
||||
theme: 'outline',
|
||||
size: 'large'
|
||||
})
|
||||
let iframe = googleButton.getElementsByTagName('iframe')[0]
|
||||
iframe.style.height = "5rem"
|
||||
iframe.style.width = "5rem"
|
||||
}
|
||||
else {
|
||||
setTimeout(renderGoogle,100)
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
||||
rememberMe.checked = true
|
||||
|
||||
inputs = {email: emailInput, password: passwordInput, remember: rememberMe}
|
||||
msgs = {email: emailMsg, password: passwordMsg}
|
||||
|
||||
parentProps.msgs = msgs
|
||||
parentProps.remember = rememberMe
|
||||
parentProps.loginGoogle = googleButton
|
||||
|
||||
document.addEventListener("keypress", function(event) {
|
||||
if (event.code == "Enter") {
|
||||
if (focused) {
|
||||
AuthTools.login(msgs,inputs)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
renderGoogle()
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<div id="login-group"class="pane auth-pane">
|
||||
<h2 class="auth-title">LOG IN</h2>
|
||||
<label class="auth-label" for="emailInput">Email </label><span bind:this={emailMsg} id="email-msg"></span>
|
||||
<input bind:this={emailInput} id="emailInput" class="authEmailInput" type="email">
|
||||
<div class="password-field">
|
||||
<label class="auth-label" for="passwordInput">Password </label><span bind:this={passwordMsg} id="password-msg"></span>
|
||||
<input bind:this={passwordInput} id="passwordInput" class="authPasswordInput" type="password">
|
||||
<button bind:this={passwordVisibilityButton} class="eye-icon" on:click="{() => AuthTools.changePasswordVisibility(passwordVisibilityButton)}">
|
||||
<object type="image/svg+xml" data="/img/auth/eye_icon.svg" title="eye icon"></object>
|
||||
</button>
|
||||
</div>
|
||||
<div id="remember-me">
|
||||
<input bind:this={rememberMe} type="checkbox" id="remember-me-checkbox"><label id="remember-me-label" for="passwordInput">remember me</label>
|
||||
</div>
|
||||
<button class="auth-button" on:click="{() => AuthTools.login(msgs,inputs)}">Log in</button>
|
||||
<a id="forgot-password" href="forgot-password">Forgot password?</a>
|
||||
<!--
|
||||
<hr class="auth-line">
|
||||
<div class="auth-methods-group">
|
||||
<div id="google-btn-wrapper">
|
||||
<div bind:this={googleButton} id="google-btn"></div>
|
||||
<img src="/img/auth/google_icon.svg" id="google-logo" alt="google icon">
|
||||
</div>
|
||||
|
||||
<button on:click={openGoogleWindow}>
|
||||
<img src="img/auth/google_icon.svg" id="navbar-logo" alt="google icon">
|
||||
</button>
|
||||
<button onclick="">
|
||||
<img src="img/auth/facebook_icon.svg" id="navbar-logo" alt="facebook icon">
|
||||
</button>
|
||||
<button onclick="">
|
||||
<img src="img/auth/linkedin_icon.svg" id="navbar-logo" alt="linkedin icon">
|
||||
</button>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
@import '/css/auth.css';
|
||||
|
||||
</style>
|
|
@ -0,0 +1,243 @@
|
|||
<svelte:options tag="signup-component" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount, getContext } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
// Export statements
|
||||
export let focused = false
|
||||
|
||||
// Main code
|
||||
|
||||
let signupGroup
|
||||
let emailInput
|
||||
let passwordInput
|
||||
let passwordVisibilityButton
|
||||
let inputs
|
||||
let googleButton
|
||||
|
||||
let emailMsg
|
||||
let passwordMsg
|
||||
let msgs
|
||||
let rememberMe
|
||||
|
||||
let dialog
|
||||
let signUp
|
||||
let signUpField
|
||||
|
||||
let parentProps = getContext("auth")
|
||||
|
||||
function removeMsg(msg) {
|
||||
if (msg.innerHTML!="") {
|
||||
msg.innerHTML = ""
|
||||
}
|
||||
}
|
||||
|
||||
function showDialog() {
|
||||
dialog.style.display = "block"
|
||||
}
|
||||
|
||||
function hide() {
|
||||
if (dialog!=null) {
|
||||
dialog.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function sendEmail() {
|
||||
let email = signUpField.value
|
||||
if (email.includes("@")) {
|
||||
sendText("/get-email",email)
|
||||
signUpField.value = ""
|
||||
signUpField.placeholder = "Subscribed!"
|
||||
signUpField.style.setProperty("--c", "hsl(147, 33%, 60%)")
|
||||
}
|
||||
else {
|
||||
signUpField.value = ""
|
||||
signUpField.placeholder = "must contain '@'"
|
||||
signUpField.style.setProperty("--c", "hsl(0, 100%, 60%)")
|
||||
}
|
||||
}
|
||||
|
||||
function clearField() {
|
||||
signUpField.placeholder = ""
|
||||
}
|
||||
|
||||
function renderGoogle() {
|
||||
if (parentProps.googleInit) {
|
||||
google.accounts.id.renderButton(googleButton,{
|
||||
theme: 'outline',
|
||||
size: 'large'
|
||||
})
|
||||
}
|
||||
else {
|
||||
setTimeout(renderGoogle,100)
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
||||
rememberMe.checked = true
|
||||
inputs = {email: emailInput, password: passwordInput}
|
||||
msgs = {email: emailMsg, password: passwordMsg}
|
||||
|
||||
document.addEventListener("keypress", function(event) {
|
||||
if (event.code == "Enter") {
|
||||
if (focused) {
|
||||
AuthTools.signup(msgs,inputs,toLandingPage)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
//renderGoogle()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<div id="signup-group" class="pane auth-pane" bind:this={signupGroup}>
|
||||
<h2 class="auth-title">SIGN UP</h2>
|
||||
<label class="auth-label" for="emailInput">Email </label><span bind:this={emailMsg} id="email-msg" on:change={() => removeMsg(emailMsg)}></span>
|
||||
<input bind:this={emailInput} id="emailInput" class="authEmailInput" type="email">
|
||||
<div class="password-field">
|
||||
<label class="auth-label" for="emailInput">Password </label><span bind:this={passwordMsg} id="password-msg"></span>
|
||||
<input bind:this={passwordInput} id="passwordInput" class="authPasswordInput" type="password" on:change={() => removeMsg(passwordMsg)}>
|
||||
<button bind:this={passwordVisibilityButton} class="eye-icon" on:click="{() => AuthTools.changePasswordVisibility(passwordVisibilityButton)}">
|
||||
<object type="image/svg+xml" data="/img/auth/eye_icon.svg" title="eye-icon"></object>
|
||||
</button>
|
||||
</div>
|
||||
<div id="remember-me">
|
||||
<input bind:this={rememberMe} type="checkbox" id="remember-me-checkbox"><label id="remember-me-label" for="passwordInput">remember me</label>
|
||||
</div>
|
||||
<button class="auth-button" on:click="{showDialog}">Sign up</button> <!--() => AuthTools.signup(msgs,inputs,AuthTools.toLandingPage)-->
|
||||
<p id="forgot-password"></p>
|
||||
<!--
|
||||
<hr class="auth-line">
|
||||
<div class="auth-methods-group">
|
||||
<button on:click="{showDialog}">
|
||||
<img src="/img/auth/google_icon.svg" id="navbar-logo" alt="google icon">
|
||||
</button>
|
||||
<button onclick="">
|
||||
<img src="img/auth/facebook_icon.svg" id="navbar-logo" alt="facebook icon">
|
||||
</button>
|
||||
<button onclick="">
|
||||
<img src="img/auth/linkedin_icon.svg" id="navbar-logo" alt="linkedin icon">
|
||||
</button>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<div bind:this={dialog} id="dialog">
|
||||
<button id="shadow" on:click={hide}></button>
|
||||
<div id="wrapper" class="pane">
|
||||
<h2>Registration is closed</h2>
|
||||
<p>We are still in the process of opening.</p>
|
||||
<p>Sign up for updates to know when it becomes available:</p>
|
||||
<div id="newsletter-container">
|
||||
<input bind:this={signUpField} on:click={clearField} id="newsletterEmailInput" type="text">
|
||||
<button bind:this={signUp} on:click={sendEmail} id="newsletterEmailButton">sign up</button>
|
||||
</div>
|
||||
<button id="no-button" on:click={hide}>No thanks</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
@import '/css/auth.css';
|
||||
|
||||
#dialog {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wrapper p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
#wrapper h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#shadow {
|
||||
position: fixed;
|
||||
cursor: default;
|
||||
top: 50%; right: 50%;
|
||||
transform: translate(50%,-50%);
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background:rgb(0, 0, 0, 0.2);
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
#newsletter-container {
|
||||
position: relative;
|
||||
height: 3rem;
|
||||
width: 100%;
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#newsletterEmailInput {
|
||||
height: 2.5rem;
|
||||
border-radius: 0.2rem 0 0 0.2rem;
|
||||
filter: drop-shadow( 0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#newsletterEmailInput::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||
color: var(--c,gray);
|
||||
opacity: 1; /* Firefox */
|
||||
}
|
||||
|
||||
#newsletterEmailButton {
|
||||
width: 6.8rem;
|
||||
height: 2.5rem;
|
||||
background: var(--pink);
|
||||
color: #ffffff;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.4rem;
|
||||
border-radius: 0 0.2rem 0.2rem 0;
|
||||
filter: drop-shadow( 0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
|
||||
}
|
||||
|
||||
#newsletterEmailButton:active {
|
||||
background: var(--darker-pink);
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
top: 50%; right: 50%;
|
||||
transform: translate(50%,-50%);
|
||||
position: fixed;
|
||||
max-width: 36rem;
|
||||
width: 90vw;
|
||||
padding: 2rem 4rem;
|
||||
z-index: 1999999;
|
||||
}
|
||||
|
||||
#wrapper * {
|
||||
font-family: var(--sans-serif);
|
||||
}
|
||||
|
||||
#no-button {
|
||||
position: relative;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 13rem;
|
||||
height: 3rem;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
background: #ffffff;
|
||||
border: 0.2rem solid var(--pink);
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.4rem;
|
||||
border-radius: 0.5rem;
|
||||
filter: drop-shadow( 0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4));
|
||||
}
|
||||
|
||||
#no-button:active {
|
||||
background: hsl(343, 23%, 82%);
|
||||
}
|
||||
|
||||
</style>
|
|
@ -43,7 +43,10 @@
|
|||
|
||||
function mapCallback(createMap,content,locale) {
|
||||
let map = createMap([22, 0],2)
|
||||
addMarkersEntries(entries,entriesByCountry,map,content,locale,addCommunePinContent,"red")
|
||||
let options = {
|
||||
enableCountryGrouping: true,
|
||||
}
|
||||
addMarkersEntries(entries,entriesByCountry,map,content,locale,addCommunePinContent,"red",options)
|
||||
}
|
||||
|
||||
function getCountry(x) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// Export statements
|
||||
export let callback = null
|
||||
export let colors = null
|
||||
export let map = null
|
||||
|
||||
// Main code
|
||||
let mapContainer
|
||||
|
|
|
@ -71,17 +71,17 @@
|
|||
<div bind:this={root} id="root" class="pane-centering">
|
||||
<div class="pane-container">
|
||||
<div id="sidebars-left" class="sidebar">
|
||||
<div bind:this={sidebarLeft} id="sidebar-left" class="pane">
|
||||
<div bind:this={sidebarLeft} id="sidebar-left">
|
||||
<slot name="sidebar-left"></slot>
|
||||
</div>
|
||||
<div bind:this={sidebarLeft2} id="sidebar-left2" class="pane">
|
||||
<div bind:this={sidebarLeft2} id="sidebar-left2">
|
||||
<slot name="sidebar-left2"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div bind:this={sidebarRight} id="sidebar-right" class="pane sidebar">
|
||||
<slot name="sidebar-right"></slot>
|
||||
</div>
|
||||
<div bind:this={mainPane} id="main-pane" class="pane">
|
||||
<div bind:this={mainPane} id="main-pane">
|
||||
<slot name="main" id="main-slot"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -95,7 +95,10 @@
|
|||
}
|
||||
|
||||
#root {
|
||||
position: relative;
|
||||
margin-top: auto;
|
||||
min-height: var(--min-height,auto);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#main-pane {
|
||||
|
@ -105,10 +108,8 @@
|
|||
padding-top: var(--padding-top,0rem);
|
||||
padding-bottom: var(--padding-bottom,0rem);
|
||||
text-align: justify;
|
||||
background: var(--background,white);
|
||||
box-shadow: var(--box-shadow,0 0 0.314rem rgb(187, 187, 187));
|
||||
margin: auto;
|
||||
height: min-content;
|
||||
height: 100%;
|
||||
max-width: var(--width-main,66rem);
|
||||
width: var(--width-main,66rem);
|
||||
z-index: 1;
|
||||
|
@ -124,13 +125,14 @@
|
|||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-left: calc(-1*var(--width-left,22.5rem) - 1rem - 4rem);
|
||||
width: calc(var(--width-left,22.5rem) + 4rem);
|
||||
width: max-content;
|
||||
max-width: 30rem;
|
||||
}
|
||||
|
||||
#sidebar-left,#sidebar-left2 {
|
||||
position: relative;
|
||||
background-color: white;
|
||||
padding: 2rem 2rem;
|
||||
padding: 0rem 0rem;
|
||||
}
|
||||
|
||||
#sidebar-left {
|
||||
|
@ -149,16 +151,16 @@
|
|||
padding: 2rem 2rem;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1880px) {
|
||||
@media only screen and (max-width: 1340px) {
|
||||
|
||||
#main-pane {
|
||||
max-width: initial;
|
||||
width: 100%;
|
||||
max-width: var(--width-main,66rem);
|
||||
padding-left: var(--padding-left-mobile,1.8rem);
|
||||
padding-right: var(--padding-right-mobile,1.8rem);
|
||||
padding-top: var(--padding-top-mobile,1.8rem);
|
||||
padding-bottom: var(--padding-bottom-mobile,1.8rem);
|
||||
padding-left: var(--padding-left-mobile,0rem);
|
||||
padding-right: var(--padding-right-mobile,0rem);
|
||||
padding-top: var(--padding-top-mobile,0rem);
|
||||
padding-bottom: var(--padding-bottom-mobile,0rem);
|
||||
}
|
||||
|
||||
#sidebars-left, #sidebar-right {
|
||||
|
|
|
@ -43,7 +43,10 @@
|
|||
|
||||
function mapCallback(createMap,content,locale) {
|
||||
let map = createMap([22, 0],2)
|
||||
addMarkersEntries(entries,entriesByCountry,map,content,locale,addCoopPinContent,"blue")
|
||||
let options = {
|
||||
enableCountryGrouping: true,
|
||||
}
|
||||
addMarkersEntries(entries,entriesByCountry,map,content,locale,addCoopPinContent,"blue",options)
|
||||
}
|
||||
|
||||
function getCountry(x) {
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
<button on:click={() => {location.href='#'}} id="footer-up" aria-label="go up">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="42.545" height="72.601" viewBox="0 0 42.545 72.601">
|
||||
<g id="Group_268" data-name="Group 268" transform="translate(-6.177 -2.399)">
|
||||
<rect id="Rectangle_146" data-name="Rectangle 146" width="11" height="51" rx="5.5" transform="translate(22 24)" fill="#cb1816"/>
|
||||
<path id="Path_1145" data-name="Path 1145" d="M23.814,4.021a5,5,0,0,1,7.372,0l16.134,17.6c2.94,3.207,1.046,10.4-3.686,8.379S28.02,14.081,28.391,13.524,16.544,27.976,11.366,30,4.741,24.828,7.68,21.621Z" fill="#DD1C1A"/>
|
||||
<rect id="Rectangle_146" data-name="Rectangle 146" width="11" height="51" rx="5.5" transform="translate(22 24)" fill="var(--red)"/>
|
||||
<path id="Path_1145" data-name="Path 1145" d="M23.814,4.021a5,5,0,0,1,7.372,0l16.134,17.6c2.94,3.207,1.046,10.4-3.686,8.379S28.02,14.081,28.391,13.524,16.544,27.976,11.366,30,4.741,24.828,7.68,21.621Z" fill="var(--red)"/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
|
@ -54,8 +54,8 @@ footer {
|
|||
bottom: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: #5B6970;/*var(--dark-green);*/
|
||||
border-top: #cb1816 solid 0.5rem;
|
||||
background: var(--gray);
|
||||
border-top: var(--red) solid 0.5rem;
|
||||
}
|
||||
|
||||
footer p, footer a {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<script>
|
||||
// Import statements
|
||||
import { onMount } from 'svelte'
|
||||
import { onMount, getContext } from 'svelte'
|
||||
import { writable } from 'svelte/store';
|
||||
import { loadLocaleContent, getData, sendData } from "/js/libraries/serverTools.js"
|
||||
import { addMarkersEntries, translate } from "/js/libraries/mapTools.js"
|
||||
|
@ -10,11 +10,18 @@
|
|||
// Import components
|
||||
import "/js/components/map-component.js"
|
||||
|
||||
// Export statements
|
||||
export let map = null
|
||||
|
||||
// Main code
|
||||
let loaded = writable(0)
|
||||
let content = writable({})
|
||||
let entries
|
||||
let entriesByCountry
|
||||
let userData
|
||||
|
||||
let buttonsGroupMember
|
||||
let buttonsNotGroupMember
|
||||
|
||||
let callback = (response) => {
|
||||
entries = JSON.parse(response)
|
||||
|
@ -41,11 +48,32 @@
|
|||
let confirmationMsg
|
||||
let addressInput
|
||||
let contactInput
|
||||
let addressVec
|
||||
let userPinLat = 0
|
||||
let membersInput
|
||||
let addressVec = ["","",""]
|
||||
let userPinData = {
|
||||
|
||||
}
|
||||
let userPinLng = 0
|
||||
let userPin = createPin(0,0)
|
||||
userPin.setOpacity(0)
|
||||
let modeButtons = []
|
||||
|
||||
let context = getContext("profile-component")
|
||||
let closeGroupsAdd = context.closeGroupsAdd
|
||||
let maps = context.maps
|
||||
let onLoadedGroups = context.onLoadedGroups
|
||||
let userGroups = context.userGroups
|
||||
let user = context.user
|
||||
|
||||
let has_group = userGroups.length!=0
|
||||
let mode = has_group ? 2 : 0
|
||||
let pendingGroup
|
||||
if (has_group) {
|
||||
pendingGroup= userGroups[0].status!=undefined
|
||||
if (pendingGroup) {
|
||||
mode = 3
|
||||
}
|
||||
}
|
||||
|
||||
let locale = loadLocaleContent(content,"groups-component",loaded)
|
||||
loadLocaleContent(content,"countries",loaded)
|
||||
|
@ -105,6 +133,7 @@
|
|||
response = JSON.parse(response)
|
||||
// Extract the address information from the response
|
||||
let address = response.address
|
||||
if (address!=undefined) {
|
||||
let city = address.city || address.town || address.village || address.hamlet
|
||||
let state = address.state
|
||||
let country = address.country
|
||||
|
@ -123,6 +152,7 @@
|
|||
}
|
||||
addressVec = [country,state,city]
|
||||
}
|
||||
}
|
||||
getData(url,callback)
|
||||
}
|
||||
|
||||
|
@ -153,59 +183,97 @@
|
|||
return {text,coordinates}
|
||||
}
|
||||
|
||||
|
||||
function mapCallback(createMap,content,locale) {
|
||||
let map = createMap([22, 0],2)
|
||||
addMarkersEntries(entries,entriesByCountry,map,content,locale,addGroupPinContent,"green")
|
||||
map = createMap([22, 0],2)
|
||||
maps["groupsAdd"] = map
|
||||
let options = {
|
||||
enableCountryGrouping: false,
|
||||
pinCallback: pinCallback
|
||||
}
|
||||
addMarkersEntries(entries,entriesByCountry,map,content,locale,addGroupPinContent,"green",options)
|
||||
|
||||
userPin.addTo(map)
|
||||
map.on('click', function(event) {
|
||||
if (mode==0) {
|
||||
let lat = event.latlng.lat;
|
||||
let lng = event.latlng.lng;
|
||||
userPinLat = lat
|
||||
userPinLng = lng
|
||||
userPinData["latitude"] = lat
|
||||
userPinData["longitude"] = lng
|
||||
userPinData["id"] = null
|
||||
updatePin(userPin,lat,lng)
|
||||
userPin.setOpacity(1)
|
||||
reverseGeocodeLocal(lat, lng)
|
||||
reverseGeocode(lat, lng)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function updateConfirmationMsg(response) {
|
||||
if (response!==false) {
|
||||
|
||||
if (mode==0 && !user.verified) {
|
||||
confirmationMsg.innerHTML = "You have been added to our database! Now go to our Discord to verify yourself."
|
||||
}
|
||||
else {
|
||||
confirmationMsg.innerHTML = "Success!"
|
||||
}
|
||||
confirmationMsg.style.color = "green"
|
||||
if (mode==0 || mode==1) {
|
||||
userGroups[0] = {}
|
||||
}
|
||||
userGroups[0].country = addressVec[0]=="" ? null : addressVec[0]
|
||||
userGroups[0].state = addressVec[1]=="" ? null : addressVec[1]
|
||||
userGroups[0].town = addressVec[2]=="" ? null : addressVec[2]
|
||||
userGroups[0].members = userPinData["members"]
|
||||
onLoadedGroups()
|
||||
}
|
||||
else {
|
||||
confirmationMsg.innerHTML = "Something went wrong."
|
||||
confirmationMsg.style.color = "red"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function submitLocation() {
|
||||
if (addressVec!=undefined) {
|
||||
let data = {
|
||||
if (addressVec[0]!="" || mode==3) {
|
||||
let membersVal, contactVal
|
||||
if (mode==0) { // Create
|
||||
membersVal = membersInput.value
|
||||
contactVal = contactInput.value
|
||||
}
|
||||
else if (mode==1) { // Join
|
||||
contactVal = contactInput.value
|
||||
}
|
||||
else if (mode==2 || mode==3) { // Move
|
||||
membersVal = ""
|
||||
contactVal = ""
|
||||
}
|
||||
else if (mode==3) { // Leave
|
||||
membersVal = ""
|
||||
contactVal = ""
|
||||
addressVec = [null,null,null]
|
||||
userPinData["latitude"] = null
|
||||
userPinData["longitude"] = null
|
||||
}
|
||||
|
||||
userData = {
|
||||
country: addressVec[0],
|
||||
state: addressVec[1],
|
||||
town: addressVec[2],
|
||||
latitude: userPinLat,
|
||||
longitude: userPinLng,
|
||||
contact: contactInput.value
|
||||
latitude: userPinData["latitude"],
|
||||
longitude: userPinData["longitude"],
|
||||
contact: contactVal=="" ? null : contactVal,
|
||||
members: membersVal=="" ? null : parseInt(membersVal),
|
||||
group_id: userPinData["id"],
|
||||
mode: mode
|
||||
}
|
||||
|
||||
if (data.state=="") {
|
||||
data.state = null
|
||||
if (userData.state=="") {
|
||||
userData.state = null
|
||||
}
|
||||
if (data.town=="") {
|
||||
data.town = null
|
||||
}
|
||||
if (data.contact=="") {
|
||||
data.contact = null
|
||||
if (userData.town=="") {
|
||||
userData.town = null
|
||||
}
|
||||
let url = "/" + locale + "/groups-add-post/"
|
||||
sendData(url,data,updateConfirmationMsg)
|
||||
sendData(url,userData,updateConfirmationMsg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,25 +281,82 @@
|
|||
el.nextElementSibling.innerHTML = el.value
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
function pinCallback(marker,event) {
|
||||
if (mode==1) {
|
||||
let lat = event.latlng.lat;
|
||||
let lng = event.latlng.lng;
|
||||
userPinData["latitude"] = lat
|
||||
userPinData["longitude"] = lng
|
||||
userPinData["id"] = marker.id
|
||||
userPinData["members"] = marker.members
|
||||
updatePin(userPin,lat,lng)
|
||||
userPin.setOpacity(1)
|
||||
reverseGeocodeLocal(lat, lng)
|
||||
reverseGeocode(lat, lng)
|
||||
}
|
||||
}
|
||||
|
||||
function chooseButton(index) {
|
||||
for (let b of modeButtons) {
|
||||
if (b!=undefined) {
|
||||
b.style.background = "rgba(197, 43, 40, 0.319)"
|
||||
b.style.color = "black"
|
||||
}
|
||||
}
|
||||
modeButtons[index].style.background = "rgb(197, 43, 40)"
|
||||
modeButtons[index].style.color = "white"
|
||||
mode = index
|
||||
}
|
||||
|
||||
function getAddress(g) {
|
||||
if (g!=undefined) {
|
||||
let location = [g.country,g.state,g.town].filter(x => x!=null)
|
||||
return location.map(x => locale=="en" ? x : translate($content,x)).join(", ")
|
||||
}
|
||||
else {
|
||||
return "Create or join group"
|
||||
}
|
||||
}
|
||||
|
||||
function onLoaded() {
|
||||
if ($loaded==3) {
|
||||
chooseButton(mode)
|
||||
if (mode==2 || mode==3) {
|
||||
addressInput.value = getAddress(userGroups[0])
|
||||
}
|
||||
}
|
||||
else {
|
||||
let f = () => onLoaded()
|
||||
setTimeout(f, 100)
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
onLoaded()
|
||||
})
|
||||
</script>
|
||||
|
||||
{#key $loaded}
|
||||
{#if $loaded==3}
|
||||
<div id="container">
|
||||
<button class="close-button" on:click={closeGroupsAdd}></button>
|
||||
<!--<img src="img/crowd.png" id="crowd" alt="crowd">-->
|
||||
<div id="text-container">
|
||||
<h1>Add a Group</h1>
|
||||
<img id="groups-img" src="/img/common/groups.svg" alt="groups">
|
||||
<p class="description">If there are no groups in your town with whom you can organize then do the following:</p>
|
||||
<ol>
|
||||
<li>Click on the map to show us where you are located;</li>
|
||||
<li>Add a way to contact you or leave blank for a pin to point to our discord;</li>
|
||||
<li>Press "Submit" to add yourself to our map;</li>
|
||||
<li>Verify yourself by having a chat with us at our Discord server to show on the map;</li>
|
||||
</ol>
|
||||
{#if !has_group}
|
||||
<div bind:this={buttonsNotGroupMember} id="button-line">
|
||||
<button bind:this={modeButtons[0]} on:click={() => chooseButton(0)}>Create</button>
|
||||
<button bind:this={modeButtons[1]} on:click={() => chooseButton(1)}>Join</button>
|
||||
</div>
|
||||
{:else if has_group && !pendingGroup}
|
||||
<div bind:this={buttonsGroupMember} id="button-line">
|
||||
<button bind:this={modeButtons[2]} on:click={() => chooseButton(2)} style={"display: " + (pendingGroup ? "none" : "initial")}>Move</button>
|
||||
<button bind:this={modeButtons[3]} on:click={() => chooseButton(3)}>Leave</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div bind:this={buttonsGroupMember} id="button-line">
|
||||
<button bind:this={modeButtons[3]} on:click={() => chooseButton(3)}>Leave</button>
|
||||
</div>
|
||||
{/if}
|
||||
<div id="address-input-wrapper" class="input-label-wrapper">
|
||||
<label for="address-input">Location: </label>
|
||||
<div class="input-wrapper">
|
||||
|
@ -239,6 +364,16 @@
|
|||
<div class="ghost-input"></div>
|
||||
</div>
|
||||
</div>
|
||||
{#key mode}
|
||||
{#if mode==0}
|
||||
<div id="members-input-wrapper" class="input-label-wrapper">
|
||||
<label for="members-input">Members: </label>
|
||||
<div class="input-wrapper">
|
||||
<input bind:this={membersInput} id="members-input" type="text" value={1}>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if mode==0 || mode==1}
|
||||
<div class="input-label-wrapper">
|
||||
<label for="contact-input">Contact: </label>
|
||||
<div class="input-wrapper">
|
||||
|
@ -246,9 +381,13 @@
|
|||
<div class="ghost-input"></div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/key}
|
||||
<button id="submit-button" on:click={submitLocation}>Submit</button>
|
||||
<p id="confirmation-msg" bind:this={confirmationMsg}></p>
|
||||
{#if !(has_group && pendingGroup)}
|
||||
<map-component id="map" callback={(createMap) => mapCallback(createMap,$content,locale)}></map-component>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -257,13 +396,75 @@
|
|||
<style>
|
||||
@import '/css/common.css';
|
||||
|
||||
#button-line {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
#button-line button{
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.15rem;
|
||||
padding: 1rem 0;
|
||||
width: 7rem;
|
||||
}
|
||||
|
||||
#button-line :first-child {
|
||||
border-top-left-radius: 1rem;
|
||||
border-bottom-left-radius: 1rem;
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
|
||||
#button-line :last-child {
|
||||
margin-left: 0.1rem;
|
||||
border-top-right-radius: 1rem;
|
||||
border-bottom-right-radius: 1rem;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
right: 0rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.close-button::before,
|
||||
.close-button::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 0.2rem;
|
||||
height: 2rem;
|
||||
background-color: #000;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.close-button::before {
|
||||
transform: translate(-50%, -50%) rotate(45deg);
|
||||
}
|
||||
|
||||
.close-button::after {
|
||||
transform: translate(-50%, -50%) rotate(-45deg);
|
||||
}
|
||||
|
||||
|
||||
#confirmation-msg {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
ol li {
|
||||
margin-left: 3rem;
|
||||
margin-left: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
|
@ -273,7 +474,7 @@
|
|||
font-size: 1.15rem;
|
||||
line-height: 160%;
|
||||
color: #222222;
|
||||
width: 5.5rem;
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
input, .ghost-input {
|
||||
|
@ -296,6 +497,14 @@
|
|||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#members-input-wrapper {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#members-input {
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
.ghost-input {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
|
@ -339,42 +548,6 @@
|
|||
color: white;
|
||||
}
|
||||
|
||||
#add-prompt {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
#groups-img {
|
||||
position: absolute;
|
||||
width: 14rem;
|
||||
left: 50%;
|
||||
transform: translate(-50%);
|
||||
z-index: 0;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
#text-container>:nth-child(3) {
|
||||
margin-top: 8rem;
|
||||
}
|
||||
|
||||
.country-name {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.country-block {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.location-info {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.location-info p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #DD1C1A;
|
||||
}
|
||||
|
||||
#map {
|
||||
--height: 30rem;
|
||||
|
@ -389,16 +562,6 @@
|
|||
margin: auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 2.2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin: auto;
|
||||
max-width: 800px;
|
||||
|
|
|
@ -62,10 +62,13 @@
|
|||
|
||||
function mapCallback(createMap,content,locale) {
|
||||
let map = createMap([22, 0],2)
|
||||
let groupsMarkersLayer = addMarkersEntries(entries["groups"],entriesByCountry["groups"],map,content,locale,addGroupPinContent,"green")
|
||||
let communesMarkersLayer = addMarkersEntries(entries["communes"],entriesByCountry["communes"],map,content,locale,addCommunePinContent,"red")
|
||||
let coopsMarkersLayer = addMarkersEntries(entries["cooperatives"],entriesByCountry["cooperatives"],map,content,locale,addCoopPinContent,"blue")
|
||||
let partiesMarkersLayer = addMarkersEntries(entries["parties"],entriesByCountry["parties"],map,content,locale,addPartyPinContent,"gold")
|
||||
let options = {
|
||||
enableCountryGrouping: true,
|
||||
}
|
||||
let groupsMarkersLayer = addMarkersEntries(entries["groups"],entriesByCountry["groups"],map,content,locale,addGroupPinContent,"green",options)
|
||||
let communesMarkersLayer = addMarkersEntries(entries["communes"],entriesByCountry["communes"],map,content,locale,addCommunePinContent,"red",options)
|
||||
let coopsMarkersLayer = addMarkersEntries(entries["cooperatives"],entriesByCountry["cooperatives"],map,content,locale,addCoopPinContent,"blue",options)
|
||||
let partiesMarkersLayer = addMarkersEntries(entries["parties"],entriesByCountry["parties"],map,content,locale,addPartyPinContent,"gold",options)
|
||||
|
||||
let overlayMaps = {}
|
||||
overlayMaps[content.groups] = groupsMarkersLayer
|
||||
|
@ -163,7 +166,7 @@
|
|||
font-family: var(--sans-serif,sans-serif);
|
||||
width: 14rem;
|
||||
line-height: 4rem;
|
||||
background: #cb1816;
|
||||
background: var(--red);
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<svelte:options tag="navbar-logged" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount, getContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import { loadLocaleContent, locales } from "/js/libraries/serverTools.js"
|
||||
|
||||
// Main code
|
||||
let hambInput
|
||||
let navbar
|
||||
let localesDropdown
|
||||
let initiativesDropdown
|
||||
let loaded = writable(0)
|
||||
let content = writable({})
|
||||
let logoText
|
||||
|
||||
let locale = loadLocaleContent(content,"navbar-component",loaded)
|
||||
|
||||
function changeNavbar() {
|
||||
if (hambInput.checked) {
|
||||
navbar.style.background = "white"
|
||||
//navbar.style.boxShadow = "0 0 0.314rem rgb(187, 187, 187)"
|
||||
}
|
||||
else {
|
||||
setTimeout(()=> {
|
||||
navbar.style.position = "relative"
|
||||
navbar.style.background = ""
|
||||
navbar.style.boxShadow = ""
|
||||
}
|
||||
,510)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function showDropdown(dropdown) {
|
||||
let state = dropdown.style.display
|
||||
initiativesDropdown.style.display = "none"
|
||||
localesDropdown.style.display = "none"
|
||||
if (state=="block") {
|
||||
dropdown.style.display = "none"
|
||||
}
|
||||
else {
|
||||
dropdown.style.display = "block"
|
||||
}
|
||||
}
|
||||
|
||||
function changeLocale(lang) {
|
||||
localStorage.setItem("locale",lang)
|
||||
let locSplit = location.href.split("/")
|
||||
let localesSymbols = Object.keys(locales)
|
||||
locSplit = locSplit.filter(x => !localesSymbols.includes(x))
|
||||
let loc = locSplit.slice(0,locSplit.length-1).join("/") + "/" + lang + "/" + locSplit[locSplit.length-1]
|
||||
location.href = loc
|
||||
}
|
||||
|
||||
function fixHeading() {
|
||||
if (locale=="ru") {
|
||||
let func = () => {
|
||||
if (logoText==undefined) {
|
||||
setTimeout(func,100)
|
||||
}
|
||||
else {
|
||||
if (((window.innerWidth < 1700 && window.innerWidth > 1400) || window.innerWidth < 400) && logoText.style.lineHeight!="100%") {
|
||||
logoText.style.lineHeight = "120%"
|
||||
logoText.style.top = "1rem"
|
||||
logoText.style.width = "16rem"
|
||||
}
|
||||
else if (((window.innerWidth > 1700) || (window.innerWidth > 400 && window.innerWidth < 1400)) && logoText.style.lineHeight!="400%") {
|
||||
logoText.style.lineHeight = "400%"
|
||||
logoText.style.top = "0rem"
|
||||
logoText.style.width = "auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
func()
|
||||
addEventListener("resize", func)
|
||||
}
|
||||
}
|
||||
|
||||
function hide(dropdown) {
|
||||
let callback = () => {
|
||||
dropdown.style.display = "none"
|
||||
}
|
||||
setTimeout(callback,100)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
fixHeading()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Navigation bar -->
|
||||
{#key loaded}
|
||||
{#if Object.keys($content).length!=0}
|
||||
<header bind:this={navbar} id="navbar">
|
||||
<!-- Hamburger icon -->
|
||||
<input bind:this={hambInput} type="checkbox" id="side-menu" on:click={changeNavbar}>
|
||||
<label id="hamb" for="side-menu"><span id="hamb-line"></span></label>
|
||||
<!-- Logo -->
|
||||
<a id=logo-container href={"/" + locale + "/"}>
|
||||
<img src="/img/common/flag.png" id="navbar-logo" alt="logo">
|
||||
<span bind:this={logoText} id="navbar-logo-text" >{@html $content.orgName}</span>
|
||||
</a>
|
||||
<!-- Menu -->
|
||||
<nav id="nav">
|
||||
<ul id="menu">
|
||||
<li><a href={"/"+locale+"/join-us"}>{$content.joinUs}</a></li>
|
||||
<li><a href={"/"+locale+"/manifesto"}>{$content.manifesto}</a></li>
|
||||
<!-- Options dropdown -->
|
||||
<!-- A list of links pointing to different pages of the website. Implemented as a div opened on :hover-->
|
||||
<li id="options-container">
|
||||
<button on:click={() => showDropdown(initiativesDropdown)} on:focusout={() => hide(initiativesDropdown)} class="options-button">{$content.initiatives}</button>
|
||||
<div bind:this={initiativesDropdown} class="options-dropdown">
|
||||
<a href={"/"+locale+"/groups"}>{$content.groups}</a>
|
||||
<a href={"/"+locale+"/communes"}>{$content.communes}</a>
|
||||
<a href={"/"+locale+"/cooperatives"}>{$content.cooperatives}</a>
|
||||
<a href={"/"+locale+"/parties"}>{$content.parties}</a>
|
||||
<a href={"/"+locale+"/partners"}>{$content.partners}</a>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href={"/"+locale+"/profile"}>{$content.profile}</a></li>
|
||||
<li id="locales">
|
||||
<button on:click={() => showDropdown(localesDropdown)} on:focusout={() => hide(localesDropdown)}>
|
||||
<picture>
|
||||
<source srcset="/img/common/globe.webp">
|
||||
<source srcset="/img/common/globe.png">
|
||||
<img id="locales-img" alt="globe">
|
||||
</picture>
|
||||
</button>
|
||||
</li>
|
||||
<div bind:this={localesDropdown} class="options-dropdown">
|
||||
{#each Object.entries(locales) as [loc,name]}
|
||||
<button on:click={() => changeLocale(loc)}>{name}</button>
|
||||
{/each}
|
||||
</div>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
{/if}
|
||||
{/key}
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
@import '/css/navbar.css';
|
||||
|
||||
</style>
|
|
@ -1,4 +1,4 @@
|
|||
<svelte:options tag="navbar-component" />
|
||||
<svelte:options tag="navbar-not-logged" />
|
||||
|
||||
<script>
|
||||
|
||||
|
@ -121,6 +121,7 @@
|
|||
<a href={"/"+locale+"/partners"}>{$content.partners}</a>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href={"/"+locale+"/auth"}>{$content.login}</a></li>
|
||||
<li id="locales">
|
||||
<button on:click={() => showDropdown(localesDropdown)} on:focusout={() => hide(localesDropdown)}>
|
||||
<picture>
|
||||
|
@ -146,274 +147,5 @@
|
|||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
|
||||
/* Header */
|
||||
#navbar{
|
||||
position: relative;
|
||||
top: 0;
|
||||
width: min(100%,116rem);
|
||||
z-index: 1000000000;
|
||||
height: 5.26rem;
|
||||
padding-left: 0rem;
|
||||
padding-right: 0rem;
|
||||
}
|
||||
|
||||
#navbar * {
|
||||
font-family: var(--sans-serif, sans-serif);
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
#logo-container {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
margin-left: 1rem;
|
||||
height: 100%;
|
||||
max-height: 5.26rem;
|
||||
color: black;
|
||||
z-index: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#navbar-logo {
|
||||
height: 3.5rem;
|
||||
width: 3.5rem;
|
||||
object-fit: contain;
|
||||
border-radius: 10rem;
|
||||
}
|
||||
|
||||
#navbar-logo-text {
|
||||
position: relative;
|
||||
word-wrap: normal;
|
||||
height: 100%;
|
||||
line-height: 400%;
|
||||
font-size: 1.4rem;
|
||||
color: #292222;
|
||||
font-family: var(--sans-serif, sans-serif);
|
||||
font-weight: 400;
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
/* Nav menu */
|
||||
#nav {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
#menu > li > a, .options-button {
|
||||
display: block;
|
||||
padding: 1.2rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
color: black;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
#menu > li > a:active{
|
||||
background-color: #f7aec0;
|
||||
}
|
||||
|
||||
#menu li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#nav{
|
||||
max-height: 0;
|
||||
/*transition: max-height .5s ease-out;*/
|
||||
}
|
||||
|
||||
/* Menu Icon */
|
||||
#hamb{
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
right: 0rem;
|
||||
padding: 2.8rem 2rem;
|
||||
z-index: 9999;
|
||||
}/* Style label tag */
|
||||
|
||||
#hamb-line {
|
||||
background: black;
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: relative;
|
||||
width: 24px;
|
||||
|
||||
} /* Style span tag */
|
||||
|
||||
#hamb-line::before,
|
||||
#hamb-line::after{
|
||||
background: black;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
transition: all .2s ease-out;
|
||||
width: 100%;
|
||||
}
|
||||
#hamb-line::before{
|
||||
top: 5px;
|
||||
}
|
||||
#hamb-line::after{
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
#side-menu {
|
||||
display: none;
|
||||
} /* Hide checkbox */
|
||||
|
||||
/* Toggle menu icon */
|
||||
#side-menu:checked ~ nav {
|
||||
display: block;
|
||||
max-height: 100%;
|
||||
padding-top: 5.625rem;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #logo-container {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #logo-container {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line::before {
|
||||
transform: rotate(-45deg);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line::after {
|
||||
transform: rotate(45deg);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Options */
|
||||
|
||||
.options-dropdown {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 5.6rem;
|
||||
right: 1.8rem;
|
||||
border: #404040 solid 0.1rem;
|
||||
background-color: white;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.options-dropdown button, .options-dropdown a {
|
||||
display: block;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.2rem;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.options-dropdown button:hover, .options-dropdown a:hover {
|
||||
background-color: rgb(187 53 52 / 96%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.options-button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Localization */
|
||||
|
||||
#locales {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#locales button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
#locales button:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#locales-img {
|
||||
position: relative;
|
||||
top: 0rem;
|
||||
height: 2rem;
|
||||
margin-left: 1.2rem;
|
||||
}
|
||||
|
||||
/*
|
||||
#options-dropdown>:first-child {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
#options-dropdown>:nth-child(2) {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Responsiveness */
|
||||
@media only screen and (min-width: 1200px) {
|
||||
|
||||
#navbar {
|
||||
position: relative;
|
||||
width: min(100%,116rem);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding-right: 4rem;
|
||||
padding-left: 4rem;
|
||||
}
|
||||
|
||||
#nav {
|
||||
max-height: none;
|
||||
top: 0;
|
||||
position: relative;
|
||||
float: right;
|
||||
width: fit-content;
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ nav {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#menu li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menu > li > a:hover, .options-button:hover, #navbar-logo-text:hover {
|
||||
color: rgb(127, 127, 127);
|
||||
}
|
||||
|
||||
#menu > li > a, .options-button {
|
||||
padding: 0.9rem;
|
||||
padding-top: 1.9rem;
|
||||
padding-bottom: 1.9rem;
|
||||
}
|
||||
|
||||
#hamb {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#locales {
|
||||
position: relative;
|
||||
margin-right: 1.8rem;
|
||||
}
|
||||
|
||||
#locales-img {
|
||||
top: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
@import '/css/navbar.css';
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<svelte:options tag="profile-communes" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
// Main code
|
||||
|
||||
onMount(() => {
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<h3>Under development</h3>
|
||||
|
||||
<p style=" position: relative; margin-top: 2rem;">Visit <a href="https://discord.gg/Qk8KUk787z" style="color: #c52a28;">https://discord.gg/Qk8KUk787z</a> and ask for your commune to be added.</p>
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,284 @@
|
|||
<svelte:options tag="profile-component" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import libraries
|
||||
import { onMount, afterUpdate, setContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
import {svgFromObject} from "/js/libraries/miscTools.js"
|
||||
|
||||
//Import components
|
||||
import "/js/components/pane-aligner.js"
|
||||
import "/js/components/profile-general.js"
|
||||
import "/js/components/profile-groups.js"
|
||||
import "/js/components/profile-communes.js"
|
||||
import "/js/components/profile-coops.js"
|
||||
import "/js/components/profile-parties.js"
|
||||
import "/js/components/groups-add-component.js"
|
||||
|
||||
// Main code
|
||||
AuthTools.redirectNotLogged()
|
||||
|
||||
let root
|
||||
let general
|
||||
let groups
|
||||
let communes
|
||||
let coops
|
||||
let parties
|
||||
let panes
|
||||
let groupsAdd
|
||||
|
||||
let generalButton
|
||||
let groupsButton
|
||||
let communesButton
|
||||
let coopsButton
|
||||
let partiesButton
|
||||
let buttons
|
||||
|
||||
let currentPaneIndex = 0
|
||||
|
||||
let locationPopup
|
||||
|
||||
let maps = {}
|
||||
|
||||
let user = {}
|
||||
let loaded = writable(0)
|
||||
let reloadTriggerVal = writable(0)
|
||||
AuthTools.getUser(user,loaded)
|
||||
|
||||
function changePane(pane,button) {
|
||||
for (let p of panes) {
|
||||
p.style.display = "none"
|
||||
}
|
||||
for (let b of buttons) {
|
||||
styleField(b,400,"#636363")
|
||||
}
|
||||
pane.style.display = "initial"
|
||||
|
||||
styleField(button,500,"#c52a28")
|
||||
}
|
||||
|
||||
function styleField(div,weight,color) {
|
||||
let svgObject = div.querySelector("object")
|
||||
if (svgObject==null) {
|
||||
let f = () => styleField(div,weight,color)
|
||||
setTimeout(f,100)
|
||||
}
|
||||
else {
|
||||
let svgItem = svgFromObject(svgObject)
|
||||
if (svgItem==null) {
|
||||
let f = () => styleField(div,weight,color)
|
||||
setTimeout(f,100)
|
||||
}
|
||||
else {
|
||||
div.style.fontWeight = weight
|
||||
svgItem.setAttribute("fill", color)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function fillFields() {
|
||||
if (Object.keys(user).length!=0 && root!=undefined) {
|
||||
for (let b of buttons) {
|
||||
styleField(b,400,"#636363")
|
||||
}
|
||||
styleField(buttons[currentPaneIndex],500,"#c52a28")
|
||||
}
|
||||
else {
|
||||
setTimeout(fillFields, 100)
|
||||
}
|
||||
}
|
||||
|
||||
function valid(el) {
|
||||
return (el!=undefined) && (el!=null)
|
||||
}
|
||||
|
||||
function init() {
|
||||
panes = [general,groups,communes,coops,parties]
|
||||
buttons = [generalButton,groupsButton,communesButton,coopsButton,partiesButton]
|
||||
if ($loaded==1 && panes.every(x => valid(x)) && buttons.every(x => valid(x))) {
|
||||
panes = [general,groups,communes,coops,parties]
|
||||
buttons = [generalButton,groupsButton,communesButton,coopsButton,partiesButton]
|
||||
|
||||
fillFields()
|
||||
general.style.display = "initial"
|
||||
}
|
||||
else {
|
||||
let f = () => init()
|
||||
setTimeout(f,100)
|
||||
}
|
||||
}
|
||||
|
||||
function reloadTrigger() {
|
||||
reloadTriggerVal.update((val) => {
|
||||
return val + 1
|
||||
})
|
||||
}
|
||||
|
||||
setContext("profile-component",{user,maps,reloadTrigger})
|
||||
|
||||
onMount(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--
|
||||
<div bind:this={locationPopup} class="overlay" style="display: none">
|
||||
<div id="location-overlay-content">
|
||||
|
||||
</div>
|
||||
<button class="overlay-button" on:click={() => locationPopup.style.display = "none"}></button>
|
||||
</div>
|
||||
-->
|
||||
<pane-aligner>
|
||||
<div id="left-column" class="pane" slot="sidebar-left" bind:this={root}>
|
||||
<button bind:this={generalButton} on:click={() => changePane(general,generalButton)}>
|
||||
<object id="general-img" class="icons" type="image/svg+xml" data="/img/profile/icons/general.svg" title="general"></object>
|
||||
<span>general</span>
|
||||
</button>
|
||||
<button bind:this={groupsButton} on:click={() => changePane(groups,groupsButton)}>
|
||||
<object id="groups-img" class="icons" type="image/svg+xml" data="/img/common/groups.svg" title="groups"></object>
|
||||
<span>groups</span>
|
||||
</button>
|
||||
<button bind:this={communesButton} on:click={() => changePane(communes,communesButton)}>
|
||||
<object id="communes-img" class="icons" type="image/svg+xml" data="/img/common/communes.svg" title="communes"></object>
|
||||
<span>communes</span>
|
||||
</button>
|
||||
<button bind:this={coopsButton} on:click={() => changePane(coops,coopsButton)}>
|
||||
<object id="coops-img" class="icons" type="image/svg+xml" data="/img/common/coops.svg" title="coops"></object>
|
||||
<span>cooperatives</span>
|
||||
</button>
|
||||
<button bind:this={partiesButton} on:click={() => changePane(parties,partiesButton)}>
|
||||
<object id="parties-img" class="icons" type="image/svg+xml" data="/img/common/parties.svg" title="parties"></object>
|
||||
<span>parties</span>
|
||||
</button>
|
||||
<button on:click={AuthTools.logout} id="logout-button">
|
||||
<object id="logout-img" class="icons" type="image/svg+xml" data="/img/profile/icons/logout.svg" title=""></object>
|
||||
<span>logout</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="main-column" slot="main">
|
||||
{#key $loaded}
|
||||
{#if $loaded==1}
|
||||
<profile-general bind:this={general} style="display: none;"></profile-general>
|
||||
<profile-groups bind:this={groups} style="display: none;"></profile-groups>
|
||||
<profile-communes bind:this={communes} style="display: none;"></profile-communes>
|
||||
<profile-coops bind:this={coops} style="display: none;"></profile-coops>
|
||||
<profile-parties bind:this={parties} style="display: none;"></profile-parties>
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
</pane-aligner>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
|
||||
#general-img {
|
||||
top: 0rem;
|
||||
}
|
||||
|
||||
#groups-img {
|
||||
top: 0.3rem;
|
||||
}
|
||||
|
||||
#coops-img {
|
||||
top: 0rem;
|
||||
}
|
||||
|
||||
#parties-img {
|
||||
top: 0rem;
|
||||
}
|
||||
|
||||
#logout-img {
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
#logout-button {
|
||||
padding-top: 1rem;
|
||||
padding-left: 0.1rem;
|
||||
}
|
||||
|
||||
#left-column {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 15.2rem;
|
||||
padding: 2rem;
|
||||
border-radius: 0.64rem 0.64rem 0.64rem 0.64rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
|
||||
.icons {
|
||||
position: relative;
|
||||
width: 1.8rem;
|
||||
}
|
||||
|
||||
#left-column button span {
|
||||
position: absolute;
|
||||
padding-left: 3.4rem;
|
||||
margin-top: 0rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
}
|
||||
|
||||
#left-column button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#main-column {
|
||||
padding: 1rem 2rem 1rem 2rem;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 0 0.64rem 0.64rem 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: 20rem;
|
||||
}
|
||||
|
||||
pane-aligner {
|
||||
--width-main: 800px;
|
||||
--width-left: 10.5rem;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1340px) {
|
||||
|
||||
|
||||
#left-column {
|
||||
position: relative;
|
||||
margin-left: 0rem;
|
||||
width: 100%;
|
||||
border-radius: 0.64rem 0.64rem 0rem 0;
|
||||
}
|
||||
|
||||
#main-column {
|
||||
border-radius: 0.64rem;
|
||||
padding: 3rem 0.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
border-radius: 0rem 0rem 0.64rem 0.64rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#logout-button {
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#left-column button {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
#logout-button {
|
||||
padding-top: 1rem;
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<svelte:options tag="profile-coops" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
// Main code
|
||||
|
||||
onMount(() => {
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<h3>Under development</h3>
|
||||
|
||||
<p style=" position: relative; margin-top: 2rem;">Visit <a href="https://discord.gg/Qk8KUk787z" style="color: #c52a28;">https://discord.gg/Qk8KUk787z</a> and ask for your cooperative to be added.</p>
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,433 @@
|
|||
<svelte:options tag="profile-general" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount, getContext } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
//Import components
|
||||
import "/js/components/select-component.js"
|
||||
import "/js/components/switch-component.js"
|
||||
|
||||
//Export statements
|
||||
|
||||
// Main code
|
||||
let emailInput
|
||||
|
||||
let section
|
||||
let saveEmailButton
|
||||
let changePasswordInputDiv
|
||||
let changePasswordMsg
|
||||
let savePasswordButton
|
||||
let passwordInput
|
||||
let changePasswordDiv
|
||||
let passwordVisibilityButton
|
||||
let emailMsg
|
||||
let passwordDiv
|
||||
let emailDiv
|
||||
let emailInputDiv
|
||||
let prevEmail
|
||||
|
||||
let context = getContext("profile-component")
|
||||
let user = context.user
|
||||
|
||||
function showSaveButton(button) {
|
||||
prevEmail = emailInput.value
|
||||
button.style.display = "initial"
|
||||
emailMsg.style.display = "inline"
|
||||
let windowWidth = window.innerWidth
|
||||
if (windowWidth<1100) {
|
||||
emailInputDiv.style.marginTop = "1rem"
|
||||
emailDiv.style.flexDirection = "column"
|
||||
}
|
||||
else {
|
||||
//emailInput.style.width = "19rem"
|
||||
}
|
||||
}
|
||||
|
||||
function saveEmail() {
|
||||
let email = emailInput.value
|
||||
if (AuthTools.checkEmail(email,emailMsg)) {
|
||||
if (email!=user.email) {
|
||||
AuthTools.changeUser("email",email,user)
|
||||
}
|
||||
resetEmailField()
|
||||
}
|
||||
}
|
||||
|
||||
function resetEmailField() {
|
||||
if (prevEmail!=undefined) {
|
||||
emailInput.value = prevEmail
|
||||
}
|
||||
emailInput.style.width = "100%"
|
||||
emailMsg.style.display = "none"
|
||||
emailDiv.style.flexDirection = "row"
|
||||
emailInputDiv.style.marginTop = "0rem"
|
||||
saveEmailButton.style.display = "none"
|
||||
emailMsg.innerHTML = ""
|
||||
}
|
||||
|
||||
function launchChangePassword() {
|
||||
let windowWidth = window.innerWidth
|
||||
if (windowWidth<1100) {
|
||||
changePasswordInputDiv.style.display = "flex";
|
||||
}
|
||||
else {
|
||||
changePasswordInputDiv.style.display = "initial";
|
||||
}
|
||||
changePasswordDiv.style.display = "none";
|
||||
passwordInput.focus()
|
||||
}
|
||||
|
||||
function savePassword() {
|
||||
let password = passwordInput.value
|
||||
if (AuthTools.checkPassword(password,changePasswordMsg)) {
|
||||
if (password!=user.password) {
|
||||
AuthTools.changeUser("password",password,user)
|
||||
}
|
||||
changePasswordMsg.innerHTML = ""
|
||||
resetPasswordField()
|
||||
}
|
||||
}
|
||||
|
||||
function resetPasswordField() {
|
||||
changePasswordInputDiv.style.display = "none";
|
||||
changePasswordDiv.style.display = "initial";
|
||||
changePasswordMsg.innerHTML = ""
|
||||
}
|
||||
|
||||
function fillFields() {
|
||||
if (user!=null && Object.keys(user).length!=0 && section!=undefined) {
|
||||
emailInput.value = user.email
|
||||
}
|
||||
else {
|
||||
setTimeout(fillFields, 10)
|
||||
}
|
||||
}
|
||||
|
||||
function resizeInput(el) {
|
||||
el.nextElementSibling.innerHTML = el.value
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
||||
fillFields()
|
||||
|
||||
document.addEventListener("click", function(event) {
|
||||
if (passwordDiv.focused) {
|
||||
resetEmailField()
|
||||
}
|
||||
else if (emailDiv.focused) {
|
||||
resetPasswordField()
|
||||
}
|
||||
else {
|
||||
resetEmailField()
|
||||
resetPasswordField()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<section bind:this={section} id="general-section">
|
||||
<h2 class="title-highlight">General</h2>
|
||||
<div bind:this={emailDiv} on:mouseenter={emailDiv.focused=true} on:mouseleave={emailDiv.focused=false}>
|
||||
<div class="title-msg">
|
||||
<span>Email:</span>
|
||||
<span bind:this={emailMsg} id="signup-email-msg"></span>
|
||||
</div>
|
||||
<div bind:this={emailInputDiv} id="emailInputDiv">
|
||||
<button bind:this={saveEmailButton} id="save-email" class="save-button" on:click={saveEmail}>save</button>
|
||||
<div class="input-wrapper">
|
||||
<input bind:this={emailInput} id="emailInput" class="text-input" type="text" on:click={() => showSaveButton(saveEmailButton)} on:input={() => resizeInput(emailInput)}>
|
||||
<div class="ghost-input"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div bind:this={passwordDiv} on:mouseenter={passwordDiv.focused=true} on:mouseleave={passwordDiv.focused=false} id="change-password-line-wrapper">
|
||||
<div id="change-password-line">
|
||||
<div class="title-msg">
|
||||
<span>Password:</span>
|
||||
<span bind:this={changePasswordMsg} id="signup-password-msg"></span>
|
||||
</div>
|
||||
|
||||
<div bind:this={changePasswordDiv} id="change-password-div">
|
||||
<button id="change-password" on:click={launchChangePassword}>change
|
||||
<object type="image/svg+xml" data="/img/profile/icons/pencil.svg" title="pencil-icon"></object>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div bind:this={changePasswordInputDiv} id="change-password-input-div">
|
||||
<button bind:this={savePasswordButton} id="save-password" class="save-button" on:click={savePassword}>save</button>
|
||||
<input bind:this={passwordInput} id="passwordInput" class="text-input" type="password">
|
||||
<button bind:this={passwordVisibilityButton} class="eye-icon" on:click="{() => AuthTools.changePasswordVisibility(passwordVisibilityButton)}">
|
||||
<object type="image/svg+xml" data="/img/auth/eye_icon.svg" title="eye icon"></object>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="verifiedDiv">
|
||||
<span>Verified:</span>
|
||||
<span style="color: {user.verified ? "green" : "red"}">{user.verified}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
@import '/css/common.css';
|
||||
|
||||
#verifiedDiv {
|
||||
display: inline;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*---General section-----------------------------------------------------------*/
|
||||
|
||||
.ghost-input {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
display: inline-block;
|
||||
max-width: calc(100% - 10rem);
|
||||
min-width: 0rem;
|
||||
height: 2.5rem;
|
||||
position: relative;
|
||||
right: 0
|
||||
}
|
||||
|
||||
span {
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
#general-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#general-section h2 {
|
||||
margin: auto;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#general-section >div {
|
||||
height: 3.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-bottom: 0.14rem solid;
|
||||
border-color: #cdcdcd;
|
||||
}
|
||||
|
||||
#general-section >div >:first-child {
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
}
|
||||
|
||||
/* add padding to every line to center the diving line*/
|
||||
#general-section >div:last-child {
|
||||
padding-bottom: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#general-section >div div,
|
||||
#general-section >div input,
|
||||
#general-section >div :not(:first-child) input {
|
||||
font-weight: 500;
|
||||
font-size: 1.15rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
color: #292222;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#general-section >div>:last-child {
|
||||
padding-right: 1.35rem;
|
||||
}
|
||||
|
||||
.text-input {
|
||||
position: relative;
|
||||
width: 20.475rem;
|
||||
direction: rtl;
|
||||
border: 0;
|
||||
outline: none;
|
||||
bottom: 0.341rem;
|
||||
}
|
||||
|
||||
|
||||
/*---Email-------------------------------------------------------------------*/
|
||||
|
||||
#emailInput {
|
||||
position: relative;
|
||||
right: 0;
|
||||
top: 0.1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#save-email {
|
||||
display: none;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
#signup-email-msg,
|
||||
#signup-password-msg {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
color:red;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#signup-email-msg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#general-section >div:nth-child(2) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#emailInputDiv {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
align-items: center;
|
||||
height: 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title-msg {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.title-msg * {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/*---Change password-------------------------------------------------------------------*/
|
||||
|
||||
#change-password-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#change-password-div {
|
||||
width: 9.3rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#change-password {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
width: 8rem;
|
||||
height: 2.73rem;
|
||||
font-size: 1.15rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
padding-right: 2rem;
|
||||
margin-top: -0.55rem;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#change-password > object {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
width: 1.5rem;
|
||||
right: 0.0rem;
|
||||
}
|
||||
|
||||
#change-password-input-div {
|
||||
display: none;
|
||||
float: right;
|
||||
position: relative;
|
||||
margin-top: -1.7rem;
|
||||
}
|
||||
|
||||
#passwordInput {
|
||||
width: 15rem;
|
||||
right: 0.65rem;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
position: relative;
|
||||
bottom: 0.34rem;
|
||||
margin-right: 0.6rem;
|
||||
height: 2.73rem;
|
||||
width: 4.778rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.15rem;
|
||||
color: white;
|
||||
background-color: var(--red);
|
||||
border-color: var(--red);
|
||||
border-radius: 0.512rem;
|
||||
}
|
||||
|
||||
#save-password {
|
||||
bottom: 0.6rem
|
||||
}
|
||||
|
||||
.eye-icon {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
opacity: 0.25;
|
||||
height: 2.2rem;
|
||||
width: 1.7rem;
|
||||
}
|
||||
|
||||
.eye-icon * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 1100px) {
|
||||
|
||||
#change-password-line-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
min-height: 4rem;
|
||||
}
|
||||
|
||||
#change-password-input-div {
|
||||
margin-top: 1rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
#general-section >div:nth-child(2) {
|
||||
height: auto;
|
||||
min-height: 4rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#passwordInput {
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#emailInput {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#save-password {
|
||||
bottom: 0rem
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,455 @@
|
|||
<svelte:options tag="profile-groups" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount, getContext } from 'svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import { getData, sendData } from "/js/libraries/serverTools.js"
|
||||
|
||||
//Import components
|
||||
import "/js/components/select-component.js"
|
||||
import "/js/components/switch-component.js"
|
||||
|
||||
//Export statements
|
||||
|
||||
// Main code
|
||||
let section
|
||||
let userGroups = []
|
||||
let groupsRequests = []
|
||||
let content = writable({})
|
||||
let loaded = writable(0)
|
||||
let keyRequests = 0
|
||||
let numLoaded = 2
|
||||
let mainPane
|
||||
let groupsAdd
|
||||
|
||||
let membersInput
|
||||
let saveMembersButton
|
||||
let membersInputDiv
|
||||
|
||||
let contactInput
|
||||
let saveContactButton
|
||||
let contactInputDiv
|
||||
|
||||
let locale = "en"
|
||||
|
||||
let inputLocation
|
||||
let inputContact
|
||||
let inputMembers
|
||||
let pencilMembers
|
||||
let pencilContact
|
||||
let pencilButtonMembers
|
||||
let pencilButtonContact
|
||||
|
||||
let myGroupLocation
|
||||
let myGroupStatus
|
||||
|
||||
let context = getContext("profile-component")
|
||||
let maps = context.maps
|
||||
|
||||
function groups_callback(response) {
|
||||
userGroups = JSON.parse(response)
|
||||
context["userGroups"] = userGroups
|
||||
loaded.update((val) => {
|
||||
return val + 1
|
||||
})
|
||||
}
|
||||
getData("/xx/get-user-groups",groups_callback)
|
||||
|
||||
function requests_callback(response) {
|
||||
let parsed = JSON.parse(response)
|
||||
groupsRequests.push(...parsed)
|
||||
loaded.update((val) => {
|
||||
return val + 1
|
||||
})
|
||||
}
|
||||
getData("/xx/get-group-requests",requests_callback)
|
||||
|
||||
function getAddress(g) {
|
||||
if (g!=undefined) {
|
||||
let location = [g.country,g.state,g.town].filter(x => x!=null)
|
||||
return location.map(x => locale=="en" ? x : translate($content,x)).join(", ")
|
||||
}
|
||||
else {
|
||||
return "Create or join group"
|
||||
}
|
||||
}
|
||||
|
||||
function getContact(c) {
|
||||
if (c==null) {
|
||||
return "https://discord.gg/Qk8KUk787z"
|
||||
}
|
||||
else {
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
function launchChangeLocation() {
|
||||
showLocationOverlay()
|
||||
}
|
||||
|
||||
function launchChangeMembers() {
|
||||
|
||||
}
|
||||
|
||||
function showSaveButton(button,input) {
|
||||
if (!input.readOnly) {
|
||||
button.style.display = "initial"
|
||||
}
|
||||
}
|
||||
|
||||
function resetMembersField() {
|
||||
saveMembersButton.style.display = "none"
|
||||
}
|
||||
|
||||
function resetContactField() {
|
||||
saveContactButton.style.display = "none"
|
||||
}
|
||||
|
||||
function saveMembers() {
|
||||
let email = emailInput.value
|
||||
if (AuthTools.checkEmail(email,emailMsg)) {
|
||||
if (email!=user.email) {
|
||||
AuthTools.changeUser("email",email,user)
|
||||
}
|
||||
resetMembersField()
|
||||
}
|
||||
}
|
||||
|
||||
function saveContact() {}
|
||||
|
||||
function updateUserGroup(newInfo) {
|
||||
if (newInfo!=undefined) {
|
||||
myGroupLocation.innerHTML = getAddress(newInfo)
|
||||
}
|
||||
}
|
||||
|
||||
function onLoadedGroups() {
|
||||
let els = [saveMembersButton,saveContactButton,membersInputDiv,contactInputDiv]
|
||||
if ($loaded==numLoaded && els.every(x => x!=undefined && x!=null)) {
|
||||
document.addEventListener("click", function(event) {
|
||||
let activeEl
|
||||
let shadowRoot = this.activeElement.shadowRoot
|
||||
if (shadowRoot!=null) {
|
||||
activeEl = shadowRoot.activeElement
|
||||
shadowRoot = activeEl.shadowRoot
|
||||
if (shadowRoot!=null) {
|
||||
activeEl = shadowRoot.activeElement
|
||||
}
|
||||
}
|
||||
if (activeEl == membersInput || activeEl == saveMembersButton) {
|
||||
resetContactField()
|
||||
}
|
||||
else if (activeEl == contactInput || activeEl == saveContactButton) {
|
||||
resetMembersField()
|
||||
}
|
||||
else {
|
||||
resetMembersField()
|
||||
resetContactField()
|
||||
}
|
||||
})
|
||||
context["updateUserGroup"] = updateUserGroup
|
||||
inputLocation = getAddress(userGroups[0])
|
||||
if (userGroups.length==0) {
|
||||
inputContact = ""
|
||||
inputMembers = ""
|
||||
}
|
||||
else {
|
||||
let group = userGroups[0]
|
||||
|
||||
inputContact = getContact(group.contact)
|
||||
inputMembers = group.members
|
||||
let status = group.status
|
||||
if (status!=undefined) {
|
||||
if (status==0) {
|
||||
myGroupStatus.innerHTML = "(pending)"
|
||||
myGroupStatus.style.color = "#FFC90E"
|
||||
}
|
||||
else if (status==2) {
|
||||
myGroupStatus.innerHTML = "(rejected)"
|
||||
myGroupStatus.style.color = "#c52a28"
|
||||
}
|
||||
pencilMembers.style.display = "none"
|
||||
pencilContact.style.display = "none"
|
||||
pencilButtonContact.style.cursor = "default"
|
||||
pencilButtonMembers.style.cursor = "default"
|
||||
membersInput.readOnly = true
|
||||
contactInput.readOnly = true
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let f = () => onLoadedGroups()
|
||||
setTimeout(f, 100)
|
||||
}
|
||||
}
|
||||
|
||||
function focus(el) {
|
||||
el.focus()
|
||||
el.click()
|
||||
}
|
||||
|
||||
function approveRequest(ind,user_id) {
|
||||
sendData("/xx/group-approve-request",{user_id: user_id})
|
||||
groupsRequests.splice(ind,1)
|
||||
keyRequests = keyRequests + 1
|
||||
}
|
||||
|
||||
function rejectRequest(ind,user_id) {
|
||||
sendData("/xx/group-reject-request",{user_id: user_id})
|
||||
groupsRequests.splice(ind,1)
|
||||
keyRequests = keyRequests + 1
|
||||
}
|
||||
|
||||
function launchGroupsAdd() {
|
||||
groupsAdd.style.display = "block"
|
||||
mainPane.style.display = "none"
|
||||
if (maps["groupsAdd"]!=undefined) {
|
||||
maps["groupsAdd"].invalidateSize()
|
||||
}
|
||||
}
|
||||
|
||||
function closeGroupsAdd() {
|
||||
groupsAdd.style.display = "none"
|
||||
mainPane.style.display = "block"
|
||||
}
|
||||
|
||||
context["onLoadedGroups"] = onLoadedGroups
|
||||
context["launchGroupsAdd"] = launchGroupsAdd
|
||||
context["closeGroupsAdd"] = closeGroupsAdd
|
||||
|
||||
onMount(() => {
|
||||
onLoadedGroups()
|
||||
})
|
||||
</script>
|
||||
|
||||
{#key $loaded}
|
||||
{#if $loaded==numLoaded}
|
||||
<div bind:this={mainPane}>
|
||||
<h2>Groups</h2>
|
||||
<div>
|
||||
<h3 class="group-heading">My group</h3>
|
||||
<span bind:this={myGroupStatus} class="status"></span>
|
||||
</div>
|
||||
<section bind:this={section} class="entries-section">
|
||||
<div>
|
||||
<div class="change-field-line">
|
||||
<span>Location:</span>
|
||||
<div class="change-field-div">
|
||||
<button class="change-field-button" bind:this={myGroupLocation} on:click={launchGroupsAdd}>{inputLocation}
|
||||
<object type="image/svg+xml" data="/img/profile/icons/pencil.svg" title="pencil-icon" class="pencil"></object>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="change-field-line">
|
||||
<span>Members:</span>
|
||||
<div bind:this={membersInputDiv} class="change-field-div input-pencil">
|
||||
<div class="save-button-wrapper">
|
||||
<button bind:this={saveMembersButton} on:click={saveMembers} class="save-button" style="display: none">save</button>
|
||||
</div>
|
||||
<input bind:this={membersInput} id="membersInput" class="text-input" type="text" bind:value={inputMembers} on:click={() => showSaveButton(saveMembersButton,membersInput)}>
|
||||
<button bind:this={pencilButtonMembers} class="text-input-pencil-button" on:click={() => {focus(membersInput)}}>
|
||||
<object bind:this={pencilMembers} type="image/svg+xml" data="/img/profile/icons/pencil.svg" title="pencil-icon" class="pencil"></object>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="change-field-line">
|
||||
<span>Contact:</span>
|
||||
<div bind:this={contactInputDiv} class="change-field-div input-pencil">
|
||||
<div class="save-button-wrapper">
|
||||
<button bind:this={saveContactButton} on:click={saveContact} class="save-button" style="display: none">save</button>
|
||||
</div>
|
||||
<input bind:this={contactInput} id="contactInput" class="text-input" type="text" bind:value={inputContact} on:click={() => showSaveButton(saveContactButton,contactInput)}>
|
||||
<button bind:this={pencilButtonContact} class="text-input-pencil-button" on:click={focus(contactInput)}>
|
||||
<object bind:this={pencilContact} type="image/svg+xml" data="/img/profile/icons/pencil.svg" title="pencil-icon" class="pencil"></object>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<h3>Requests</h3>
|
||||
<section bind:this={section} class="entries-section">
|
||||
{#key keyRequests}
|
||||
{#each groupsRequests as req,ind}
|
||||
<div>
|
||||
<div class="change-field-line">
|
||||
<span>{req.email}</span>
|
||||
<div class="request-button-wrapper">
|
||||
<button on:click={() => approveRequest(ind,req.user_id)} class="approve-button">approve</button>
|
||||
<button on:click={() => rejectRequest(ind,req.user_id)} class="approve-button" style="display:visible">reject</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/key}
|
||||
</section>
|
||||
</div>
|
||||
<!--Helper panes-->
|
||||
<groups-add-component bind:this={groupsAdd} style="display: none;"></groups-add-component>
|
||||
{/if}
|
||||
{/key}
|
||||
|
||||
|
||||
<style>
|
||||
@import '/css/common.css';
|
||||
|
||||
.request-button-wrapper {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.approve-button {
|
||||
height: 2.7rem;
|
||||
padding: 0rem 1rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.15rem;
|
||||
color: white;
|
||||
background-color: var(--red);
|
||||
border-color: var(--red);
|
||||
border-radius: 0.5rem;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
.group-heading {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: inline-block;
|
||||
font-size: 1.15rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
input {
|
||||
font-family: var(--sans-serif,sans-serif)
|
||||
}
|
||||
|
||||
.text-input-pencil-button {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
height: 2.7rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.text-input-pencil-button object {
|
||||
top: 0rem;
|
||||
}
|
||||
|
||||
.pencil {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
width: 1.5rem;
|
||||
right: 0.0rem;
|
||||
}
|
||||
|
||||
.change-field-div input.text-input {
|
||||
position: relative;
|
||||
width: 20.475rem;
|
||||
direction: rtl;
|
||||
border: 0;
|
||||
outline: none;
|
||||
height: 2.7rem;
|
||||
font-style: var(--sans-serif,sans-serif);
|
||||
background: transparent;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
#membersInput {
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
#contactInput {
|
||||
max-width: 18rem;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: -0.4rem;
|
||||
margin-right: 0.6rem;
|
||||
height: 2.7rem;
|
||||
width: 5rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.15rem;
|
||||
color: white;
|
||||
background-color: var(--red);
|
||||
border-color: var(--red);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.save-button-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.entries-section {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.entries-section >div {
|
||||
height: 3.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-bottom: 0.14rem solid;
|
||||
border-color: #cdcdcd;
|
||||
}
|
||||
|
||||
/* add padding to every line to center the diving line*/
|
||||
.entries-section >div:last-child {
|
||||
padding-bottom: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
/*---Change field-------------------------------------------------------------------*/
|
||||
|
||||
.change-field-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.change-field-div {
|
||||
width: max-content;
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.change-field-button {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 2.7rem;
|
||||
font-size: 1.15rem;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
padding-right: 1.9rem;
|
||||
margin-top: -0.55rem;
|
||||
background-color: transparent;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
/*---General section-----------------------------------------------------------*/
|
||||
|
||||
h3 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
span {
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<svelte:options tag="profile-parties" />
|
||||
|
||||
<script>
|
||||
|
||||
// Import statements
|
||||
import { onMount } from 'svelte'
|
||||
import * as AuthTools from "/js/libraries/authTools.js"
|
||||
|
||||
// Main code
|
||||
|
||||
onMount(() => {
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<h3>Under development</h3>
|
||||
|
||||
<p style=" position: relative; margin-top: 2rem;">Visit <a href="https://discord.gg/Qk8KUk787z" style="color: #c52a28;">https://discord.gg/Qk8KUk787z</a> and ask for your party to be added.</p>
|
||||
|
||||
<style>
|
||||
|
||||
@import '/css/common.css';
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -12,8 +12,8 @@ server {
|
|||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
location ~* \.(?:css|js|json)$ {
|
||||
expires 1d;
|
||||
location ~* \.(?:css|js|json|txt)$ {
|
||||
expires 1h;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ server {
|
|||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
location /js/ {}
|
||||
location /css {}
|
||||
location /img/ {}
|
||||
|
@ -29,18 +30,29 @@ server {
|
|||
location /fonts/ {}
|
||||
location /favicon.ico {}
|
||||
location /robots.txt {}
|
||||
location /sitemap.txt {}
|
||||
location ~ /loaderio-58f125137ee61345d68285d88016ce2a {}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8001/;
|
||||
map $request_uri $language_redirect {
|
||||
~^/(check-login|login-post|logout|signup-post|signup-google|change-user|get-user|confirm-email) ""; # Excluded URIs, no redirection
|
||||
~^/([a-zA-Z]{2})/ ""; # Matches URIs that start with a two-letter language code and sets it to an empty string
|
||||
default /en; # Redirects all other URIs to the /en prefix
|
||||
}
|
||||
|
||||
rewrite https://www.libsoc.org/communities https://www.libsoc.org/en/communes permanent;
|
||||
location / {
|
||||
rewrite ^ $language_redirect$request_uri? permanent;
|
||||
proxy_pass http://127.0.0.1:8001;
|
||||
}
|
||||
|
||||
rewrite /en/communities /en/communes permanent;
|
||||
rewrite /en/coops /en/cooperatives permanent;
|
||||
rewrite /en/affiliates /en/partners permanent;
|
||||
|
||||
|
||||
listen 443 http3;
|
||||
listen 443 ssl http2;
|
||||
ssl_certificate /etc/letsencrypt/live/libsoc.org/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/libsoc.org/privkey.pem; # managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/libsoc.org-0001/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/libsoc.org-0001/privkey.pem; # managed by Certbot
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
||||
|
||||
|
@ -51,6 +63,7 @@ server {
|
|||
|
||||
resolver 1.1.1.1 1.0.0.1 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
|
@ -59,17 +72,20 @@ server {
|
|||
server_name libsoc.org;
|
||||
|
||||
listen 443 ssl http2; # managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/libsoc.org/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/libsoc.org/privkey.pem; # managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/libsoc.org-0001/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/libsoc.org-0001/privkey.pem; # managed by Certbot
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
|
||||
return 301 https://www.libsoc.org$request_uri;
|
||||
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
server_name www.libsoc.org libsoc.org;
|
||||
|
||||
}
|
||||
|
|
|
@ -8,12 +8,9 @@ function up()
|
|||
primary_key()
|
||||
column(:email, :string)
|
||||
column(:password, :string, limit = 100)
|
||||
column(:name, :string)
|
||||
column(:profile_picture, :int)
|
||||
column(:country, :int)
|
||||
column(:newsletter, :bool)
|
||||
column(:notifications, :int)
|
||||
column(:confirmation_code, :string)
|
||||
column(:google_id, :string)
|
||||
column(:verified, :bool)
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ module CreateTableGroups
|
|||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
include("../../lib/DatabaseSupport.jl")
|
||||
import .DatabaseSupport: add_foreign_key, add_index
|
||||
|
||||
function up()
|
||||
create_table(:groups) do
|
||||
[
|
||||
|
@ -13,8 +16,12 @@ function up()
|
|||
column(:latitude, :float)
|
||||
column(:longitude, :float)
|
||||
column(:members, :int)
|
||||
column(:user_id, :int)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:groups,:user_id,:users,:id)
|
||||
add_index(:groups, :user_id)
|
||||
end
|
||||
|
||||
function down()
|
||||
|
|
|
@ -18,7 +18,6 @@ function up()
|
|||
column(:name, :string)
|
||||
column(:market, :string)
|
||||
column(:website, :string)
|
||||
column(:description, :string)
|
||||
]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
module CreateTableGroupsRequests
|
||||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
include("../../lib/DatabaseSupport.jl")
|
||||
using .DatabaseSupport
|
||||
import .DatabaseSupport: add_foreign_key, add_index, set_default
|
||||
|
||||
function up()
|
||||
create_table(:groups_requests) do
|
||||
[
|
||||
primary_key()
|
||||
column(:group_id, :integer)
|
||||
column(:user_id, :integer)
|
||||
column(:country, :string)
|
||||
column(:state, :string)
|
||||
column(:town, :string)
|
||||
column(:contact, :string)
|
||||
column(:latitude, :float)
|
||||
column(:longitude, :float)
|
||||
column(:longitude, :float)
|
||||
column(:members,:integer)
|
||||
column(:added, :bool)
|
||||
column(:status,:Integer)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:groups_requests,:user_id,:users,:id)
|
||||
add_foreign_key(:groups_requests,:group_id,:groups,:id)
|
||||
|
||||
add_index(:groups_requests, :user_id)
|
||||
|
||||
set_default("groups_requests","added",false)
|
||||
|
||||
end
|
||||
|
||||
function down()
|
||||
drop_table(:groups_requests)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module CreateTableGroupsUsers
|
||||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
function up()
|
||||
create_table(:groups_users) do
|
||||
[
|
||||
primary_key()
|
||||
column(:user_id, :int)
|
||||
column(:group_id, :int)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:groups_users,:user_id,:users,:id)
|
||||
add_foreign_key(:groups_users,:group_id,:groups,:id)
|
||||
add_index(:groups_users, :user_id)
|
||||
add_index(:groups_users, :group_id)
|
||||
end
|
||||
|
||||
function down()
|
||||
drop_table(:groups_users)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module CreateTableCommunesUsers
|
||||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
function up()
|
||||
create_table(:communes_users) do
|
||||
[
|
||||
primary_key()
|
||||
column(:user_id, :int)
|
||||
column(:commune_id, :int)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:communes_users,:user_id,:users,:id)
|
||||
add_foreign_key(:communes_users,:commune_id,:communes,:id)
|
||||
add_index(:communes_users, :user_id)
|
||||
add_index(:communes_users, :commune_id)
|
||||
end
|
||||
|
||||
function down()
|
||||
drop_table(:communes_users)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module CreateTableCooperativesUsers
|
||||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
function up()
|
||||
create_table(:cooperatives_users) do
|
||||
[
|
||||
primary_key()
|
||||
column(:user_id, :int)
|
||||
column(:cooperative_id, :int)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:cooperatives_users,:user_id,:users,:id)
|
||||
add_foreign_key(:cooperatives_users,:cooperative_id,:cooperatives,:id)
|
||||
add_index(:cooperatives_users, :user_id)
|
||||
add_index(:cooperatives_users, :cooperative_id)
|
||||
end
|
||||
|
||||
function down()
|
||||
drop_table(:cooperatives_users)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module CreateTablePartiesUsers
|
||||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
function up()
|
||||
create_table(:parties_users) do
|
||||
[
|
||||
primary_key()
|
||||
column(:user_id, :int)
|
||||
column(:party_id, :int)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:parties_users,:user_id,:users,:id)
|
||||
add_foreign_key(:parties_users,:party_id,:parties,:id)
|
||||
add_index(:parties_users, :user_id)
|
||||
add_index(:parties_users, :party_id)
|
||||
end
|
||||
|
||||
function down()
|
||||
drop_table(:parties_users)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module CreateTableUsersGroups
|
||||
|
||||
import SearchLight.Migrations: create_table, column, primary_key, add_index, drop_table
|
||||
|
||||
include("../../lib/DatabaseSupport.jl")
|
||||
import .DatabaseSupport: add_foreign_key, add_index
|
||||
|
||||
function up()
|
||||
create_table(:users_groups) do
|
||||
[
|
||||
primary_key()
|
||||
column(:user_id, :int)
|
||||
column(:group_id, :int)
|
||||
]
|
||||
end
|
||||
|
||||
add_foreign_key(:users_groups,:user_id,:users,:id)
|
||||
add_foreign_key(:users_groups,:group_id,:groups,:id)
|
||||
add_index(:users_groups, :user_id)
|
||||
add_index(:users_groups, :group_id)
|
||||
end
|
||||
|
||||
function down()
|
||||
drop_table(:users_groups)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module Cookies
|
||||
|
||||
using HTTP, Dates, Genie
|
||||
|
||||
export set_cookies, set_remember, remove_remember
|
||||
|
||||
function set_cookies(params)
|
||||
request = params[:REQUEST]
|
||||
response = params[:RESPONSE]
|
||||
if !occursin("__genierememberme",string(request))
|
||||
headers = Genie.Responses.getheaders(response)
|
||||
headers["Set-Cookie"] = replace(headers["Set-Cookie"],"Max-Age=2592000;" => "")
|
||||
Genie.Responses.setheaders!(response,headers)
|
||||
end
|
||||
end
|
||||
#=
|
||||
function set_remember(params)
|
||||
#cookie_remember = HTTP.Cookies.Cookie("__genieremember", params[:SESSION].id, path="/", expires=now() + Dates.Month(1), httponly=true,samesite=HTTP.Cookies.SameSiteLaxMode)
|
||||
#HTTP.Cookies.addcookie!(params[:RESPONSE],cookie_remember)
|
||||
end
|
||||
|
||||
function remove_remember(params)
|
||||
#cookie_remember = HTTP.Cookies.Cookie("__genieremember", params[:SESSION].#id, path="/", httponly=true,samesite=HTTP.Cookies.SameSiteLaxMode)
|
||||
#HTTP.Cookies.addcookie!(params[:RESPONSE],cookie_remember)
|
||||
end
|
||||
=#
|
||||
end
|
|
@ -4,7 +4,7 @@ module DatabaseSupport
|
|||
using SearchLight, SearchLightPostgreSQL, LibPQ
|
||||
using DataFrames
|
||||
|
||||
export exist_in_table, insert_into_table, update_table, select_from_table, add_foreign_key, set_default
|
||||
export exist_in_table, insert_into_table, update_table, select_from_table, delete_from_table, add_foreign_key, set_default
|
||||
|
||||
options = SearchLight.Configuration.read_db_connection_data("db/connection.yml")
|
||||
conn = SearchLight.connect(options)
|
||||
|
@ -19,15 +19,22 @@ function format(x)
|
|||
end
|
||||
end
|
||||
|
||||
function insert_into_table(table_name,dict_values)
|
||||
function insert_into_table(table_name,dict_values,other="")
|
||||
names_string = join(keys(dict_values),", ")
|
||||
vals_raw = values(dict_values)
|
||||
|
||||
vals = map(x -> format(x),vals_raw)
|
||||
vals_string = join(values(vals),", ")
|
||||
query = "INSERT INTO $table_name ($names_string) VALUES ($vals_string)"
|
||||
query = "INSERT INTO $table_name ($names_string) VALUES ($vals_string) " * other
|
||||
return SearchLight.query(query)
|
||||
end
|
||||
|
||||
function delete_from_table(table_name,where_data)
|
||||
query = "DELETE FROM $table_name"
|
||||
if !isnothing(where_data)
|
||||
query *= where_query(where_data)
|
||||
end
|
||||
SearchLight.query(query)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function update_table(table_name,dict_values; where_data=nothing)
|
||||
|
@ -46,14 +53,22 @@ function update_table(table_name,dict_values; where_data=nothing)
|
|||
end
|
||||
|
||||
function where_query(pair::Pair)
|
||||
if isnothing(pair[2])
|
||||
return " WHERE $(pair[1]) is null"
|
||||
else
|
||||
return " WHERE $(pair[1]) = $(pair[2])"
|
||||
end
|
||||
end
|
||||
|
||||
function where_query(data::Vector{<:Pair})
|
||||
conds = String[]
|
||||
for pair in data
|
||||
if isnothing(pair[2])
|
||||
push!(conds, "$(pair[1]) is null")
|
||||
else
|
||||
push!(conds,"$(pair[1]) = $(pair[2])")
|
||||
end
|
||||
end
|
||||
query = " WHERE "*join(conds," AND ")
|
||||
return query
|
||||
end
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
module EmailSupport
|
||||
|
||||
using Genie, Genie.Requests, Genie.Renderer.Json
|
||||
using SMTPClient, JSON3, Random
|
||||
|
||||
export send_email
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
function send_email(receiver,subject,message)
|
||||
url = "smtps://mail.privateemail.com:465"
|
||||
rcpt = ["<"*receiver*">","<info@chrn.health>"]
|
||||
from = "<no-reply@chrn.health>"
|
||||
|
||||
# Message body as RFC5322 within an IO
|
||||
to = [receiver]
|
||||
from = "no-reply@chrn.health"
|
||||
replyto = "Chiron <info@chrn.health>"
|
||||
body = get_body(to, from, subject, message; replyto)
|
||||
|
||||
resp = send(url, rcpt, from, body, opt)
|
||||
return resp
|
||||
end
|
||||
|
||||
# Load credentails
|
||||
function load_credentials_inner(path)
|
||||
credentials_text = open(joinpath(path,"credentials.json")) do f
|
||||
read(f, String)
|
||||
end
|
||||
credentials_json = JSON3.read(credentials_text)
|
||||
opt.username = credentials_json[:username]
|
||||
opt.passwd = credentials_json[:password]
|
||||
return
|
||||
end
|
||||
function load_credentials(path)
|
||||
load_credentials_inner(path)
|
||||
end
|
||||
function load_credentials()
|
||||
path = @__DIR__
|
||||
load_credentials_inner(path)
|
||||
end
|
||||
|
||||
opt = SendOptions(
|
||||
isSSL = true,
|
||||
username = "",
|
||||
passwd = ""
|
||||
)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
load_credentials()
|
||||
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"username": "info@chrn.health",
|
||||
"password": "Ur4tdgishg"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
using Genie
|
||||
|
||||
import Server.AuthenticationController
|
||||
import Server.Users
|
||||
import SearchLight: findone
|
||||
|
||||
export current_user
|
||||
current_user() = findone(Users.User, id = get_authentication())
|
|
@ -1 +1 @@
|
|||
[{"town":"Atlanta","contact":null,"latitude":33.7243396617476,"longitude":-84.39697265625,"id":9,"members":1,"country":"United States","state":"Georgia"},{"town":null,"contact":null,"latitude":39.98855476000615,"longitude":-105.2105712890625,"id":10,"members":1,"country":"United States","state":"Colorado"},{"town":null,"contact":null,"latitude":28.27955105276024,"longitude":-81.47460937500001,"id":11,"members":1,"country":"United States","state":"Florida"},{"town":"Dublin","contact":null,"latitude":40.13360099478965,"longitude":-83.10607910156251,"id":12,"members":1,"country":"United States","state":"Ohio"},{"town":"Toronto","contact":null,"latitude":43.68959002213805,"longitude":-79.36523437500001,"id":13,"members":1,"country":"Canada","state":"Ontario"},{"town":"Halifax","contact":null,"latitude":44.64996307546047,"longitude":-63.60809326171876,"id":14,"members":1,"country":"Canada","state":"Nova Scotia"},{"town":null,"contact":null,"latitude":53.353612430518126,"longitude":-8.085937500000002,"id":15,"members":1,"country":"Ireland","state":null},{"town":"Cham","contact":null,"latitude":47.18444711300418,"longitude":8.461189270019533,"id":16,"members":1,"country":"Switzerland","state":"Zug"},{"town":"Wiesbaden","contact":null,"latitude":50.085975903187155,"longitude":8.240432739257814,"id":17,"members":1,"country":"Germany","state":"Hesse"},{"town":"Copenhagen","contact":null,"latitude":55.68832070332783,"longitude":12.568359375000002,"id":18,"members":1,"country":"Denmark","state":"Capital Region of Denmark"},{"town":"Kolding","contact":null,"latitude":55.5095568556412,"longitude":9.486694335937502,"id":19,"members":1,"country":"Denmark","state":null},{"town":"Municipal Unit of Moschato","contact":null,"latitude":37.950275539773436,"longitude":23.673992156982425,"id":20,"members":1,"country":"Greece","state":"Attica"},{"town":"Varna","contact":null,"latitude":43.18381722560103,"longitude":27.905273437500004,"id":21,"members":1,"country":"Bulgaria","state":null},{"town":"Riga","contact":null,"latitude":56.966939887376796,"longitude":24.142456054687504,"id":22,"members":1,"country":"Latvia","state":"Vidzeme"},{"town":"Kohtla-Järve linn","contact":null,"latitude":59.40196127188141,"longitude":27.28042602539063,"id":23,"members":1,"country":"Estonia","state":null},{"town":"Tallinn","contact":null,"latitude":59.39656672058008,"longitude":24.72610473655427,"id":24,"members":1,"country":"Estonia","state":null},{"town":"Chiang Mai","contact":null,"latitude":18.796128352413316,"longitude":98.98753015423392,"id":25,"members":1,"country":"Thailand","state":null}]
|
||||
[{"town":null,"contact":null,"latitude":52.16045455774706,"longitude":36.21093750000001,"id":39,"members":1,"country":"Russia","state":"Kursk Oblast"}]
|
|
@ -0,0 +1,180 @@
|
|||
|
||||
label {
|
||||
font-size: 1.3rem;
|
||||
font-family: var(--sans-serif);
|
||||
}
|
||||
|
||||
.auth-pane {
|
||||
position: relative;
|
||||
padding: 3.4rem;
|
||||
padding-top: 3.4rem;
|
||||
padding-bottom: 3.4rem;
|
||||
width: 30rem;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.auth-title {
|
||||
position: relative;
|
||||
top: 0.2rem;
|
||||
margin-bottom: 2.7rem;
|
||||
}
|
||||
|
||||
.auth-label {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.authEmailInput, .authPasswordInput {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-radius: 0.34rem;
|
||||
color: #353535;
|
||||
height: 2.73rem;
|
||||
padding-left: 0.34rem;
|
||||
}
|
||||
|
||||
.authEmailInput {
|
||||
margin-bottom: 0.682rem;
|
||||
}
|
||||
|
||||
.auth-button {
|
||||
margin-top: 1.365rem;
|
||||
height: 3.412rem;
|
||||
width: 100%;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.3rem;
|
||||
color: white;
|
||||
background-color: var(--red);
|
||||
border-color: var(--red);
|
||||
border-radius: 0.512rem;
|
||||
filter: drop-shadow(0.068rem 0.136rem 0.068rem rgb(0 0 0 / 0.4));
|
||||
}
|
||||
|
||||
.auth-button:active {
|
||||
background-color: var(--darker-pink);
|
||||
}
|
||||
|
||||
#email-msg,#password-msg {
|
||||
display: inline;
|
||||
color:red;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
}
|
||||
|
||||
.auth-line {
|
||||
margin-top: 1.5rem;
|
||||
width: 100%;
|
||||
height: 0.07rem;
|
||||
border: 0;
|
||||
border-radius: 0.1rem;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.auth-methods-group {
|
||||
display: grid;
|
||||
grid-template-columns: auto ; /*auto auto*/
|
||||
justify-content: center;
|
||||
gap: 2.7rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.auth-methods-group img {
|
||||
height: auto;
|
||||
width: 3.4rem;
|
||||
}
|
||||
|
||||
.auth-methods-group> div {
|
||||
position: relative;
|
||||
border-radius: 6.8rem;
|
||||
width: 3.4rem;
|
||||
height: 3.4rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#google-btn {
|
||||
position: absolute;
|
||||
top: -0.8rem;
|
||||
left: -0.8rem;
|
||||
}
|
||||
|
||||
#google-logo {
|
||||
position: relative;
|
||||
background: white;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#google-btn-wrapper {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#google-btn div {
|
||||
position: absolute;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
#google-btn iframe {
|
||||
position: absolute;
|
||||
height: 10rem;
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.password-field {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.eye-icon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
opacity: 0.25;
|
||||
top: 2.6rem;
|
||||
right: 0.8rem;
|
||||
width: 1.7rem;
|
||||
}
|
||||
|
||||
.eye-icon * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#forgot-password {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
height: 2rem;
|
||||
color:#5f5f5f;
|
||||
margin-left: auto;
|
||||
width: max-content;
|
||||
font-family: var(--sans-serif);
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
|
||||
#remember-me {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 1rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#remember-me-checkbox {
|
||||
min-height: 1.5rem;
|
||||
min-width: 1.5rem;
|
||||
flex: 0;
|
||||
accent-color: var(--gray);
|
||||
}
|
||||
|
||||
#remember-me label {
|
||||
position: relative;
|
||||
margin-top: -0.2rem;
|
||||
color: #5f5f5f;
|
||||
}
|
||||
|
||||
#content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
|
@ -1,21 +1,7 @@
|
|||
|
||||
:root {
|
||||
--light-blue:hsl(195, 67%, 95%);
|
||||
--darker-pink:hsl(344, 60%, 47%);
|
||||
--pink:hsl(344, 73%, 57%);
|
||||
--dark-green:hsl(176, 63%, 25%);
|
||||
--green:hsl(147, 33%, 60%);
|
||||
--orange:hsl(30, 97%, 72%);
|
||||
--light-orange: hsl(19, 76%, 72%);
|
||||
--dark-brown:hsl(23, 47%, 20%);
|
||||
--brown:hsl(23, 47%, 30%);
|
||||
--light-brown: hsl(23, 47%, 50%);
|
||||
--dark-pink:hsl(343, 39%, 16%);
|
||||
--red:hsl(359, 72%, 61%);
|
||||
--dark-blue:hsl(217, 25%, 16%);
|
||||
--grey-blue:hsl(223, 13%, 22%);
|
||||
--cream:hsl(34, 43%, 90%);
|
||||
--dark-cream:hsl(33, 26%, 84%);
|
||||
--red:#c52a28;
|
||||
--gray: #5B6970;
|
||||
--sans-serif: "OpenSans";
|
||||
--serif: "Lora";
|
||||
}
|
||||
|
@ -48,12 +34,10 @@ body {
|
|||
|
||||
#content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
display: grid;
|
||||
grid-template-rows: max-content auto max-content;
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/*---Fonts---------------------------------------------------------*/
|
||||
|
@ -475,9 +459,8 @@ input[type=number]::-webkit-outer-spin-button {
|
|||
|
||||
.pane {
|
||||
background: white;
|
||||
border: 0;
|
||||
border: 0.1rem solid rgb(187, 187, 187);
|
||||
border-radius: 0.635rem;
|
||||
box-shadow: 0 0 0.314rem rgb(187, 187, 187);
|
||||
}
|
||||
|
||||
.pane-container {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
/* Header */
|
||||
#navbar{
|
||||
/* Header */
|
||||
#navbar{
|
||||
position: relative;
|
||||
top: 0;
|
||||
width: min(100%,116rem);
|
||||
z-index: 1000;
|
||||
z-index: 1000000000;
|
||||
height: 5.26rem;
|
||||
padding-left: 0rem;
|
||||
padding-right: 0rem;
|
||||
}
|
||||
|
||||
#navbar * {
|
||||
|
@ -35,11 +36,9 @@
|
|||
|
||||
#navbar-logo-text {
|
||||
position: relative;
|
||||
width: auto;
|
||||
word-wrap: normal;
|
||||
height: 100%;
|
||||
line-height: 400%;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
font-size: 1.4rem;
|
||||
color: #292222;
|
||||
font-family: var(--sans-serif, sans-serif);
|
||||
|
@ -56,20 +55,17 @@
|
|||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
#menu a {
|
||||
#menu > li > a, .options-button {
|
||||
display: block;
|
||||
padding: 1.9rem;
|
||||
padding: 1.2rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
color: black;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
#menu a:hover {
|
||||
background-color: rgb(220, 220, 220);
|
||||
}
|
||||
|
||||
#menu a:active{
|
||||
background-color: #f7aec0;
|
||||
#menu > li > a:active{
|
||||
|
||||
}
|
||||
|
||||
#menu li {
|
||||
|
@ -145,49 +141,88 @@
|
|||
|
||||
#side-menu:checked ~ #hamb #hamb-line::before {
|
||||
transform: rotate(-45deg);
|
||||
top:0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ #hamb #hamb-line::after {
|
||||
transform: rotate(45deg);
|
||||
top:0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#cart-icon {
|
||||
height: 1.8rem;
|
||||
pointer-events: none;
|
||||
/* Options */
|
||||
|
||||
.options-dropdown {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 5.6rem;
|
||||
right: 1.8rem;
|
||||
border: #404040 solid 0.1rem;
|
||||
background-color: white;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#menu a:hover div {
|
||||
filter: saturate(50%) brightness(140%);
|
||||
.options-dropdown button, .options-dropdown a {
|
||||
display: block;
|
||||
font-family: var(--sans-serif,sans-serif);
|
||||
font-size: 1.2rem;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#menu a:hover svg {
|
||||
stroke: rgb(127, 127, 127);;
|
||||
}
|
||||
|
||||
#cart-counter {
|
||||
position: relative;
|
||||
top: -2.8rem;
|
||||
left: 1.6rem;
|
||||
width: 1.3rem;
|
||||
height: 1.3rem;
|
||||
border-radius: 3.4rem;
|
||||
font-family: var(--sans-serif, sans-serif);
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
.options-dropdown button:hover, .options-dropdown a:hover {
|
||||
background-color: var(--red);
|
||||
color: white;
|
||||
background: var(--pink);
|
||||
}
|
||||
|
||||
.options-button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Localization */
|
||||
|
||||
#locales {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#locales button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
#locales button:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#locales-img {
|
||||
position: relative;
|
||||
top: 0rem;
|
||||
height: 2rem;
|
||||
margin-left: 1.2rem;
|
||||
}
|
||||
|
||||
/*
|
||||
#options-dropdown>:first-child {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
#options-dropdown>:nth-child(2) {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Responsiveness */
|
||||
@media only screen and (min-width: 1500px) {
|
||||
@media only screen and (min-width: 1200px) {
|
||||
|
||||
#navbar {
|
||||
position: relative;
|
||||
width: min(100%,116rem);
|
||||
left: 50%;
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
padding-right: 4rem;
|
||||
padding-left: 4rem;
|
||||
}
|
||||
|
||||
#nav {
|
||||
|
@ -197,23 +232,37 @@
|
|||
float: right;
|
||||
width: fit-content;
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#side-menu:checked ~ nav {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#menu li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#menu a:hover {
|
||||
background-color: transparent;
|
||||
#menu > li > a:hover, .options-button:hover, #navbar-logo-text:hover {
|
||||
color: rgb(127, 127, 127);
|
||||
}
|
||||
|
||||
#menu a {
|
||||
padding: 1.9rem;
|
||||
#menu > li > a, .options-button {
|
||||
padding: 0.9rem;
|
||||
padding-top: 1.9rem;
|
||||
padding-bottom: 1.9rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#hamb {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#locales {
|
||||
position: relative;
|
||||
margin-right: 1.8rem;
|
||||
}
|
||||
|
||||
#locales-img {
|
||||
top: 0.9rem;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#notifications-div>button {
|
||||
cursor: pointer;
|
||||
margin-left: 0.341rem;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(1) {
|
||||
width: 1.706rem;
|
||||
height: 1.706rem;
|
||||
background-color: #ccc;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(2) {
|
||||
width: 2.047rem;
|
||||
height: 2.047rem;
|
||||
background-color: #ccc;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(3) {
|
||||
width: 2.389rem;
|
||||
height: 2.389rem;
|
||||
background-color: #ccc;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>button>div {
|
||||
cursor: pointer;
|
||||
margin: auto;
|
||||
background-color: white;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(1)>div {
|
||||
width: 1.228rem;
|
||||
height: 1.228rem;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(2)>div {
|
||||
width: 1.57rem;
|
||||
height: 1.57rem;
|
||||
}
|
||||
|
||||
#notifications-div>:nth-child(3)>div {
|
||||
width: 1.843rem;
|
||||
height: 1.843rem;
|
||||
}
|
||||
|
||||
*/
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#636363" d="M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9M12,4.5C17,4.5 21.27,7.61 23,12C21.27,16.39 17,19.5 12,19.5C7,19.5 2.73,16.39 1,12C2.73,7.61 7,4.5 12,4.5M3.18,12C4.83,15.36 8.24,17.5 12,17.5C15.76,17.5 19.17,15.36 20.82,12C19.17,8.64 15.76,6.5 12,6.5C8.24,6.5 4.83,8.64 3.18,12Z" /></svg>
|
After Width: | Height: | Size: 391 B |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="100%" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" version="1.1" viewBox="0 0 512 512" width="100%" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:serif="http://www.serif.com/" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M512,256c0,-141.385 -114.615,-256 -256,-256c-141.385,0 -256,114.615 -256,256c0,127.777 93.616,233.685 216,252.89l0,-178.89l-65,0l0,-74l65,0l0,-56.4c0,-64.16 38.219,-99.6 96.695,-99.6c28.009,0 57.305,5 57.305,5l0,63l-32.281,0c-31.801,0 -41.719,19.733 -41.719,39.978l0,48.022l71,0l-11.35,74l-59.65,0l0,178.89c122.385,-19.205 216,-125.113 216,-252.89Z" style="fill:#1877f2;fill-rule:nonzero;"/><path d="M355.65,330l11.35,-74l-71,0l0,-48.022c0,-20.245 9.917,-39.978 41.719,-39.978l32.281,0l0,-63c0,0 -29.297,-5 -57.305,-5c-58.476,0 -96.695,35.44 -96.695,99.6l0,56.4l-65,0l0,74l65,0l0,178.89c13.033,2.045 26.392,3.11 40,3.11c13.608,0 26.966,-1.065 40,-3.11l0,-178.89l59.65,0Z" style="fill:#fff;fill-rule:nonzero;"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 128 128" id="Social_Icons" version="1.1" viewBox="0 0 128 128" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="_x31__stroke"><g id="Google"><rect clip-rule="evenodd" fill="none" fill-rule="evenodd" height="128" width="128"/><path clip-rule="evenodd" d="M27.585,64c0-4.157,0.69-8.143,1.923-11.881L7.938,35.648 C3.734,44.183,1.366,53.801,1.366,64c0,10.191,2.366,19.802,6.563,28.332l21.558-16.503C28.266,72.108,27.585,68.137,27.585,64" fill="#FBBC05" fill-rule="evenodd"/><path clip-rule="evenodd" d="M65.457,26.182c9.031,0,17.188,3.2,23.597,8.436L107.698,16 C96.337,6.109,81.771,0,65.457,0C40.129,0,18.361,14.484,7.938,35.648l21.569,16.471C34.477,37.033,48.644,26.182,65.457,26.182" fill="#EA4335" fill-rule="evenodd"/><path clip-rule="evenodd" d="M65.457,101.818c-16.812,0-30.979-10.851-35.949-25.937 L7.938,92.349C18.361,113.516,40.129,128,65.457,128c15.632,0,30.557-5.551,41.758-15.951L86.741,96.221 C80.964,99.86,73.689,101.818,65.457,101.818" fill="#34A853" fill-rule="evenodd"/><path clip-rule="evenodd" d="M126.634,64c0-3.782-0.583-7.855-1.457-11.636H65.457v24.727 h34.376c-1.719,8.431-6.397,14.912-13.092,19.13l20.474,15.828C118.981,101.129,126.634,84.861,126.634,64" fill="#4285F4" fill-rule="evenodd"/></g></g></svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN' 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'><svg enable-background="new 0 0 32 32" height="32px" id="Layer_1" version="1.0" viewBox="0 0 32 32" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><circle clip-rule="evenodd" cx="16" cy="16" fill="#007BB5" fill-rule="evenodd" r="16"/><g><rect fill="#FFFFFF" height="14" width="4" x="7" y="11"/><path d="M20.499,11c-2.791,0-3.271,1.018-3.499,2v-2h-4v14h4v-8c0-1.297,0.703-2,2-2c1.266,0,2,0.688,2,2v8h4v-7 C25,14,24.479,11,20.499,11z" fill="#FFFFFF"/><circle cx="9" cy="8" fill="#FFFFFF" r="2"/></g></g><g/><g/><g/><g/><g/><g/></svg>
|
After Width: | Height: | Size: 732 B |
|
@ -1 +1 @@
|
|||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" fill="#5B6970"><path d="m0 0h16v16h-16z" fill="none"/><path d="m0 8v7h3v-4h3v4h6v-7l-6-5zm10-7-2.4 2 5.4 4.5v5.5h3v-7z"/></svg>
|
||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" fill="none"><path d="m0 8v7h3v-4h3v4h6v-7l-6-5zm10-7-2.4 2 5.4 4.5v5.5h3v-7z" fill="#5B6970"/><path d="m0 0h16v16h-16z"/></svg>
|
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B |
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m12 2a10 10 0 1 0 10 10 10 10 0 0 0 -10-10zm1 14a1 1 0 0 1 -2 0v-5a1 1 0 0 1 2 0zm-1-7a1 1 0 1 1 1-1 1 1 0 0 1 -1 1z" fill="#5B6970"/><path d="m0 0h24v24h-24z" fill="#fff" opacity="0" transform="matrix(-1 0 0 -1 24 24)"/></svg>
|
After Width: | Height: | Size: 296 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36">
|
||||
<path id="logout_FILL0_wght400_GRAD0_opsz48" d="M9,42a2.878,2.878,0,0,1-2.1-.9A2.878,2.878,0,0,1,6,39V9a2.878,2.878,0,0,1,.9-2.1A2.878,2.878,0,0,1,9,6H23.55V9H9V39H23.55v3Zm24.3-9.25L31.15,30.6l5.1-5.1H18.75v-3h17.4l-5.1-5.1,2.15-2.15,8.8,8.8Z" transform="translate(-6 -6)" fill="#5d6162"/>
|
||||
</svg>
|
After Width: | Height: | Size: 384 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="41" height="41" viewBox="0 0 41 41">
|
||||
<image id="edit_FILL0_wght400_GRAD0_opsz48" width="41" height="41" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABjUlEQVRoQ+2Y4W0CMQxGYYNuwAilG5QN2g3KBJRNygSwQbtB2YAyQjfoBtSWOBRFiZ3cnZ0P6ZDyK7njvXyOpdx8due/+Z3zzyaB1glOCRgksKF3Lmn80Nhp70dK4IFgv6/wHTdLrGj85URQBFLwRRIoAi9E+ymUCyfxlJpHEWC2Nxp7QWJLcx/xfEsBLptnGl8BlCTBB/odRSCs+TVBHQokYBJIHVhN4hx1p5uvdwlJ3SYnwfBcaslW6imQgv8lsEVQPrEEd6djDp6f8xLIlQ0fYAZ8FCSExuQjoNU8z3OfD5N4jbpTVsI6AQ2eweLWKda8Zxs1h7c8Ay7wVgJu8BYCrvBjC7jDjynQBH4sgWbwYwg0hR8q0Bx+iAAEfF8BGPg+AlDwtQJw8DUCkPClArDwJQLQ8JoAPLwmcKIFS+GuOugmJV50KyalK+UFHV5LIBQIRSF2vtvc0gS6dVDwNQmkqrLq60FFWVctLU0gfikEfN8EYOA1gaooWy22/jJn7jUJmG+x8gdTAq0T+AcZc54xVe/5CAAAAABJRU5ErkJggg=="/>
|
||||
</svg>
|
After Width: | Height: | Size: 849 B |
|
@ -0,0 +1,686 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" id="account-pic" viewBox="0 0 513 513" enable-background="new 0 0 513 513" xml:space="preserve">
|
||||
<path fill="#EA7B7D" opacity="1.000000" stroke="none" d="M514.000000,236.000000
|
||||
C514.000000,251.020889 514.000000,266.041779 513.649536,281.201965
|
||||
C512.888672,281.849335 512.190796,282.316132 512.111084,282.871674
|
||||
C511.019714,290.475494 510.695221,298.261810 508.845551,305.669434
|
||||
C504.923767,321.375336 501.127411,337.220123 495.550781,352.371674
|
||||
C490.953735,364.861694 484.648285,376.914246 477.675354,388.287201
|
||||
C469.958191,400.874146 461.249268,412.991150 451.799774,424.336212
|
||||
C443.546783,434.244781 433.838074,442.979706 424.431122,451.871979
|
||||
C419.719513,456.325775 414.246552,459.974152 408.756470,463.912781
|
||||
C406.608948,459.028748 404.249908,454.344727 403.158661,449.381897
|
||||
C401.025513,439.680664 400.117157,429.698151 397.773376,420.057770
|
||||
C393.074188,400.728973 384.557465,382.831238 375.020050,365.521027
|
||||
C370.586609,357.474365 364.448792,350.366730 359.100708,342.458130
|
||||
C359.567963,339.037079 360.018005,335.991302 360.566040,332.584503
|
||||
C360.707428,331.478424 360.750854,330.733398 360.890717,329.536377
|
||||
C360.411621,324.276947 359.836090,319.469543 359.273193,314.487061
|
||||
C359.285858,314.312012 359.183441,313.976257 359.182800,313.601257
|
||||
C358.505737,311.450165 357.829315,309.674072 357.096497,307.959045
|
||||
C357.040070,308.020111 357.166382,307.909119 357.151794,307.616943
|
||||
C356.839508,306.841309 356.541809,306.357819 356.198853,305.873474
|
||||
C356.153595,305.872589 356.227966,305.820984 356.195923,305.534912
|
||||
C355.841400,304.789337 355.518951,304.329834 355.107544,303.936646
|
||||
C355.018646,304.003021 355.206238,303.883575 355.201660,303.558167
|
||||
C354.802307,302.493439 354.407501,301.754120 354.014099,301.003906
|
||||
C354.015472,300.993073 353.996704,300.981689 353.974152,300.709167
|
||||
C353.612366,300.027954 353.273102,299.619293 352.827759,298.924225
|
||||
C352.619659,298.461639 352.517670,298.285431 352.363861,297.868530
|
||||
C351.916229,297.361511 351.520416,297.095215 351.106384,296.868866
|
||||
C351.088196,296.908844 351.173798,296.889099 351.129639,296.601501
|
||||
C350.711761,295.891174 350.338104,295.468414 349.980988,295.022186
|
||||
C349.997528,294.998688 349.950073,295.031586 349.907898,294.706573
|
||||
C348.991486,293.459564 348.117218,292.537537 347.137085,291.316650
|
||||
C346.814484,290.655609 346.597687,290.293457 346.404358,289.813019
|
||||
C346.427826,289.694702 346.026001,289.538177 345.831299,289.364624
|
||||
C345.493134,289.092743 345.349701,288.994446 345.110474,288.603455
|
||||
C344.399200,287.814423 343.783722,287.318054 343.097412,286.873566
|
||||
C343.026550,286.925415 343.187195,286.854584 343.139221,286.574432
|
||||
C342.705017,285.895844 342.318726,285.497437 341.947144,285.071167
|
||||
C341.961853,285.043304 341.898895,285.041687 341.825653,284.817505
|
||||
C341.570374,284.314148 341.316101,284.141113 340.860748,283.863190
|
||||
C340.534851,283.381866 340.293518,283.159637 339.918762,282.747803
|
||||
C339.566040,282.306152 339.302551,282.102081 338.925476,281.706421
|
||||
C338.628143,281.275024 338.403107,281.083923 338.024841,280.701233
|
||||
C337.633545,280.251709 337.354034,280.042511 336.967102,279.644562
|
||||
C336.686890,279.215118 336.467560,279.029480 336.081360,278.657837
|
||||
C335.684631,278.193085 335.408264,277.969360 335.026672,277.563873
|
||||
C334.747864,277.155334 334.533020,276.978760 334.153137,276.605957
|
||||
C333.751953,276.122772 333.474518,275.885986 333.151886,275.480957
|
||||
C333.106720,275.312744 332.931213,275.011841 332.844269,274.735840
|
||||
C332.190033,273.954315 331.622772,273.448761 331.033813,272.973236
|
||||
C331.012177,273.003265 331.064667,272.946136 330.995422,272.653015
|
||||
C330.347473,271.846222 329.768768,271.332581 329.121246,270.828735
|
||||
C329.052429,270.838593 329.189789,270.859924 329.123840,270.555267
|
||||
C328.399048,269.473419 327.740234,268.696228 327.045868,267.946045
|
||||
C327.010345,267.973022 327.097870,267.955719 327.064514,267.665863
|
||||
C326.693390,266.921082 326.355591,266.466156 326.017242,266.000183
|
||||
C326.016663,265.989105 325.997223,265.978363 325.930542,265.739441
|
||||
C325.715973,265.179169 325.473114,264.966003 325.148438,264.902954
|
||||
C325.161621,264.944885 325.198792,264.865234 325.160889,264.486053
|
||||
C323.690247,259.741913 322.257446,255.376953 320.813232,250.683548
|
||||
C320.713593,249.926819 320.625397,249.498550 320.616821,248.673187
|
||||
C318.847839,239.206482 316.999298,230.136887 315.425018,220.882874
|
||||
C325.048187,209.279083 335.349365,198.496567 343.515594,186.286224
|
||||
C354.837616,169.357254 364.731812,151.456390 374.865417,133.758698
|
||||
C378.457886,127.484657 380.960876,120.586807 383.978271,113.988556
|
||||
C383.995361,114.003372 383.972076,113.966606 384.223877,113.807907
|
||||
C384.651276,113.098106 384.826904,112.546997 385.080566,111.819031
|
||||
C385.158661,111.642181 385.225739,111.261406 385.438354,111.033051
|
||||
C385.774200,110.208626 385.897369,109.612564 386.076050,108.631439
|
||||
C386.765503,105.528435 387.815369,102.831184 387.951752,100.088501
|
||||
C388.295837,93.171082 385.811890,90.546196 378.774231,90.999680
|
||||
C374.370697,91.283432 369.826141,92.191185 365.721436,93.787331
|
||||
C351.728424,99.228638 339.691040,107.922951 328.617279,117.867462
|
||||
C306.773834,137.483337 292.288147,162.370239 278.644653,188.104599
|
||||
C272.459381,187.474991 266.699493,186.854324 260.486023,186.126190
|
||||
C250.358963,186.672348 240.685547,187.325974 230.909729,187.645721
|
||||
C229.120026,184.063156 227.497009,180.779190 225.735123,177.571503
|
||||
C213.024612,154.430664 199.118484,132.157196 178.481827,115.038651
|
||||
C166.522659,105.118279 153.893494,96.158127 138.698120,91.789146
|
||||
C133.921600,90.415802 128.469727,89.127167 124.438560,92.944710
|
||||
C120.207924,96.951149 122.360313,102.267998 123.497704,107.109436
|
||||
C123.649200,107.754311 123.920364,108.371086 124.157280,109.243233
|
||||
C124.285248,109.822701 124.506912,110.045639 124.816811,110.130013
|
||||
C124.790176,110.105629 124.768829,110.174622 124.780151,110.393814
|
||||
C124.791473,110.613014 124.988998,111.005028 125.016037,111.293442
|
||||
C125.319313,112.075935 125.595558,112.570015 125.893593,113.436935
|
||||
C126.583313,115.505013 127.155907,117.245331 127.933197,118.888847
|
||||
C144.348648,153.597961 163.473175,186.584579 189.715347,214.954758
|
||||
C193.574753,219.127121 196.253342,223.201889 193.785187,229.250885
|
||||
C193.701797,229.835007 193.707275,230.176071 193.464661,230.832916
|
||||
C192.601898,235.115036 191.987228,239.081406 191.297699,243.371857
|
||||
C191.214508,244.138901 191.206192,244.581833 191.083099,245.406372
|
||||
C190.934235,246.846115 190.900131,247.904266 190.906418,248.975723
|
||||
C190.946808,248.989044 190.902969,248.916153 190.664886,249.212097
|
||||
C189.924973,252.341217 189.423157,255.174377 188.859940,258.166199
|
||||
C188.798553,258.324829 188.814636,258.664642 188.595612,258.903992
|
||||
C188.231720,259.761871 188.086868,260.380402 187.878387,261.142761
|
||||
C187.814743,261.286621 187.833328,261.600647 187.626129,261.783325
|
||||
C187.308975,262.309631 187.199005,262.653198 186.905792,263.292511
|
||||
C180.095764,271.633270 173.740311,279.922699 166.771301,287.659485
|
||||
C158.658325,296.666260 152.450134,306.611176 151.203049,318.753967
|
||||
C150.380264,326.765442 151.042725,334.929443 150.742172,343.179291
|
||||
C131.598190,366.845032 119.361450,393.641113 112.062065,422.656494
|
||||
C108.743324,435.848633 106.941971,449.422546 104.142502,462.869812
|
||||
C102.728333,462.276062 101.453682,461.817688 100.545471,460.967773
|
||||
C89.038895,450.200043 77.500648,439.463287 66.169266,428.512939
|
||||
C62.778244,425.235962 59.635670,421.568146 57.011787,417.655273
|
||||
C47.914017,404.088165 38.088184,390.868927 30.456888,376.498993
|
||||
C23.072790,362.594574 16.979519,347.767090 12.310448,332.726868
|
||||
C7.856178,318.378571 5.988375,303.229218 2.887524,288.452118
|
||||
C2.763702,287.862030 1.651623,287.479340 1.000001,287.000000
|
||||
C1.000000,273.979095 1.000000,260.958221 1.300240,247.244965
|
||||
C1.400320,244.701752 1.200160,242.850876 1.000000,241.000000
|
||||
C1.000000,237.307098 1.000000,233.614182 1.359694,229.772308
|
||||
C2.134809,228.777603 2.800037,227.967499 2.926459,227.080582
|
||||
C4.019210,219.414719 4.331128,211.567627 6.161662,204.089325
|
||||
C12.963929,176.299896 22.437262,149.626877 37.761063,125.080322
|
||||
C46.061306,111.784515 54.983459,99.032440 65.320732,87.433167
|
||||
C79.799126,71.187210 95.901649,56.426167 114.537239,45.041058
|
||||
C128.742203,36.362766 143.368484,28.091438 158.589172,21.423813
|
||||
C182.200195,11.080681 206.977005,4.323318 232.962723,2.935838
|
||||
C234.006638,2.880100 234.988983,1.671474 236.000000,1.000003
|
||||
C236.750000,1.000000 237.500000,1.000000 238.300781,1.336543
|
||||
C240.756851,3.317096 243.110275,4.448632 245.000000,1.000000
|
||||
C254.687561,1.000000 264.375122,1.000000 274.245056,1.372616
|
||||
C275.272766,2.162385 276.082520,2.833764 276.968842,2.957769
|
||||
C286.931580,4.351604 296.925415,5.532055 306.873566,7.019388
|
||||
C330.479279,10.548635 352.717285,18.978046 373.655762,29.652117
|
||||
C394.968109,40.516788 415.260193,53.665508 431.960632,71.418442
|
||||
C439.880066,79.836937 448.534271,87.619072 455.928741,96.464340
|
||||
C468.436066,111.425522 478.673035,127.927826 487.275574,145.506210
|
||||
C501.093628,173.741943 509.968414,203.254761 512.140442,234.698105
|
||||
C512.173157,235.172623 513.354614,235.567795 514.000000,236.000000
|
||||
z"/>
|
||||
<path fill="#CCC2C8" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M104.452324,462.823273
|
||||
C106.941971,449.422546 108.743324,435.848633 112.062065,422.656494
|
||||
C119.361450,393.641113 131.598190,366.845032 150.967651,343.447449
|
||||
C154.454727,348.673889 156.743530,354.358185 160.503967,358.795258
|
||||
C173.642975,374.298462 190.905792,380.693787 211.090744,380.318542
|
||||
C217.213715,386.160065 224.525116,389.438049 232.365631,390.669281
|
||||
C241.485840,392.101410 250.799500,392.301697 260.026062,393.502930
|
||||
C260.349823,433.642670 260.676758,473.316071 260.802063,513.122742
|
||||
C260.328339,513.445984 260.128204,513.693970 260.000000,514.000000
|
||||
C257.299988,514.000000 254.599976,514.000000 251.196747,513.737671
|
||||
C248.662369,513.650146 246.831177,513.825073 245.000000,514.000000
|
||||
C240.975449,514.000000 236.950912,514.000000 232.802765,513.657043
|
||||
C231.673462,512.878235 230.688232,512.120300 229.658966,512.054810
|
||||
C214.090561,511.064941 199.069077,507.365173 184.156845,503.069458
|
||||
C164.687897,497.461121 146.085800,489.765076 128.753891,479.274200
|
||||
C120.396240,474.215393 112.537163,468.332855 104.452324,462.823273
|
||||
z"/>
|
||||
<path fill="#BEB4BA" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M261.003723,512.989441
|
||||
C260.676758,473.316071 260.349823,433.642670 260.027679,393.498047
|
||||
C260.032471,393.026764 260.046661,393.029877 260.479736,393.022827
|
||||
C268.225647,391.842438 275.731262,391.334930 282.792023,389.290771
|
||||
C288.733490,387.570587 295.382141,386.137482 299.457214,379.965576
|
||||
C326.667816,381.643250 350.343445,363.588776 358.265259,342.943604
|
||||
C358.720856,342.890320 358.902191,342.861877 359.083557,342.833435
|
||||
C364.448792,350.366730 370.586609,357.474365 375.020050,365.521027
|
||||
C384.557465,382.831238 393.074188,400.728973 397.773376,420.057770
|
||||
C400.117157,429.698151 401.025513,439.680664 403.158661,449.381897
|
||||
C404.249908,454.344727 406.608948,459.028748 408.607849,464.239624
|
||||
C408.249542,464.933716 407.628784,465.158295 407.114380,465.530029
|
||||
C387.010834,480.059845 365.242401,491.453125 341.821869,499.552490
|
||||
C323.366272,505.934784 304.468719,510.559082 284.909668,512.097473
|
||||
C284.227417,512.151184 283.634521,513.340149 283.000000,514.000000
|
||||
C278.975464,514.000000 274.950897,514.000000 270.176331,513.711792
|
||||
C266.618774,513.278931 263.811249,513.134216 261.003723,512.989441
|
||||
z"/>
|
||||
<path fill="#EBE7E9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M260.802063,513.122742
|
||||
C263.811249,513.134216 266.618774,513.278931 269.713135,513.711792
|
||||
C266.969391,514.000000 263.938812,514.000000 260.454102,514.000000
|
||||
C260.128204,513.693970 260.328339,513.445984 260.802063,513.122742
|
||||
z"/>
|
||||
<path fill="#EBE7E9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M245.428467,514.000000
|
||||
C246.831177,513.825073 248.662369,513.650146 250.746765,513.737671
|
||||
C249.285645,514.000000 247.571289,514.000000 245.428467,514.000000
|
||||
z"/>
|
||||
<path fill="#FFD2D7" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M1.000000,241.428467
|
||||
C1.200160,242.850876 1.400320,244.701752 1.300240,246.776306
|
||||
C1.000000,245.285645 1.000000,243.571289 1.000000,241.428467
|
||||
z"/>
|
||||
<path fill="#E0DCDD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M211.001480,379.990509
|
||||
C190.905792,380.693787 173.642975,374.298462 160.503967,358.795258
|
||||
C156.743530,354.358185 154.454727,348.673889 151.265640,343.293335
|
||||
C151.042725,334.929443 150.380264,326.765442 151.203049,318.753967
|
||||
C152.450134,306.611176 158.658325,296.666260 166.771301,287.659485
|
||||
C173.740311,279.922699 180.095764,271.633270 187.103149,263.105896
|
||||
C187.600281,262.282562 187.716797,261.941620 187.833328,261.600647
|
||||
C187.833328,261.600647 187.814743,261.286621 188.116455,260.917572
|
||||
C188.550308,259.920563 188.682480,259.292603 188.814636,258.664642
|
||||
C188.814636,258.664642 188.798553,258.324829 189.144714,257.913574
|
||||
C189.961578,254.640259 190.432266,251.778214 190.902969,248.916153
|
||||
C190.902969,248.916153 190.946808,248.989044 191.154480,248.769028
|
||||
C191.307404,247.374268 191.252640,246.199524 191.197876,245.024780
|
||||
C191.206192,244.581833 191.214508,244.138901 191.613251,243.201141
|
||||
C192.573395,238.643280 193.143082,234.580215 193.712769,230.517151
|
||||
C193.707275,230.176071 193.701797,229.835007 194.077423,229.011169
|
||||
C195.974625,223.018661 197.490738,217.508926 199.345795,211.940918
|
||||
C201.817001,209.876862 203.919922,207.838776 206.087585,205.872009
|
||||
C210.563675,201.810776 214.826965,197.455246 219.655197,193.862289
|
||||
C223.030762,191.350327 227.198303,189.902634 231.012131,187.979614
|
||||
C240.685547,187.325974 250.358963,186.672348 260.342468,186.444824
|
||||
C260.761017,227.451370 260.869507,268.031799 260.740112,308.725891
|
||||
C260.337189,308.897888 260.172150,308.956177 259.539825,308.970581
|
||||
C253.740875,308.942719 248.406372,308.871613 243.079636,309.042511
|
||||
C241.901611,309.080292 240.121613,309.705597 239.762634,310.547913
|
||||
C239.394333,311.411987 240.189651,313.050537 240.913452,314.025024
|
||||
C241.671799,315.045959 242.933426,315.703979 244.004745,316.479614
|
||||
C248.055679,319.412415 252.118683,322.328552 256.157166,325.236542
|
||||
C257.067139,324.407806 258.512390,323.091522 259.972778,322.216309
|
||||
C260.165009,323.798157 260.511475,324.941833 260.492035,326.079285
|
||||
C260.355835,334.053802 260.144104,342.027039 259.706207,349.770752
|
||||
C258.157684,346.950043 256.859558,344.359283 255.144684,340.936829
|
||||
C252.956131,345.465698 251.631958,349.636414 249.175873,352.974274
|
||||
C244.801987,358.918427 239.743393,364.358734 234.675751,370.178711
|
||||
C226.587387,373.561920 218.794434,376.776215 211.001480,379.990509
|
||||
M226.835876,263.789429
|
||||
C225.998428,258.384125 223.202942,254.496170 217.832474,252.988266
|
||||
C212.991531,251.629059 208.577087,252.691727 205.026184,256.397003
|
||||
C201.140274,260.451782 200.496170,266.823517 203.371155,271.646027
|
||||
C206.080322,276.190369 211.542465,278.603760 216.621262,277.500458
|
||||
C222.893372,276.137970 226.318207,271.820679 226.835876,263.789429
|
||||
z"/>
|
||||
<path fill="#D9D3D5" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M259.956543,350.000671
|
||||
C260.144104,342.027039 260.355835,334.053802 260.492035,326.079285
|
||||
C260.511475,324.941833 260.165009,323.798157 260.096252,321.998993
|
||||
C260.477997,320.914337 260.751404,320.488037 261.376526,319.995789
|
||||
C264.343079,318.488281 267.129303,317.276123 269.499115,315.506348
|
||||
C270.649780,314.647034 271.746368,312.613403 271.519806,311.353821
|
||||
C271.332062,310.310150 269.260468,309.164429 267.858429,308.881287
|
||||
C265.637390,308.432770 263.278534,308.666931 260.977966,308.612244
|
||||
C260.869507,268.031799 260.761017,227.451370 260.796082,186.552277
|
||||
C266.699493,186.854324 272.459381,187.474991 278.914307,188.319595
|
||||
C291.576019,192.217087 300.389923,199.895523 307.288422,210.109360
|
||||
C308.122162,211.343781 309.729248,212.055908 310.997894,213.387329
|
||||
C312.022064,216.177170 313.026245,218.589783 314.020935,221.414658
|
||||
C315.108368,226.666641 316.162292,231.516632 317.315125,236.343002
|
||||
C318.331757,240.599136 319.458862,244.828888 320.537231,249.070282
|
||||
C320.625397,249.498550 320.713593,249.926819 320.623291,250.968689
|
||||
C322.029449,256.009918 323.614105,260.437592 325.198792,264.865234
|
||||
C325.198792,264.865234 325.161621,264.944885 325.223755,265.136627
|
||||
C325.450226,265.624634 325.687347,265.841309 325.997223,265.978363
|
||||
C325.997223,265.978363 326.016663,265.989105 326.042725,266.292328
|
||||
C326.411804,267.048950 326.754852,267.502319 327.097870,267.955719
|
||||
C327.097870,267.955719 327.010345,267.973022 327.056396,268.275726
|
||||
C327.798218,269.338928 328.493988,270.099426 329.189789,270.859924
|
||||
C329.189789,270.859924 329.052429,270.838593 329.129364,271.154846
|
||||
C329.825745,271.962769 330.445221,272.454437 331.064667,272.946136
|
||||
C331.064667,272.946136 331.012177,273.003265 331.072632,273.281616
|
||||
C331.732452,274.043915 332.331848,274.527893 332.931213,275.011841
|
||||
C332.931213,275.011841 333.106720,275.312744 333.240234,275.754425
|
||||
C333.674774,276.414856 333.975830,276.633636 334.276886,276.852386
|
||||
C334.533020,276.978760 334.747864,277.155334 335.123718,277.823120
|
||||
C335.617859,278.475677 335.909760,278.687286 336.201660,278.898865
|
||||
C336.467560,279.029480 336.686890,279.215118 337.074341,279.889191
|
||||
C337.571594,280.528931 337.854126,280.735229 338.136658,280.941559
|
||||
C338.403107,281.083923 338.628143,281.275024 339.024841,281.937866
|
||||
C339.494598,282.569092 339.751312,282.777252 340.008026,282.985413
|
||||
C340.293518,283.159637 340.534851,283.381866 340.966736,284.063202
|
||||
C341.383728,284.725189 341.616180,284.914307 341.898895,285.041687
|
||||
C341.898895,285.041687 341.961853,285.043304 341.999207,285.352783
|
||||
C342.420074,286.059692 342.803650,286.457123 343.187195,286.854584
|
||||
C343.187195,286.854584 343.026550,286.925415 343.178345,287.173981
|
||||
C343.955536,287.913757 344.580902,288.404968 345.206268,288.896179
|
||||
C345.349701,288.994446 345.493134,289.092743 345.876648,289.438477
|
||||
C346.116699,289.685883 346.380920,289.931335 346.380920,289.931335
|
||||
C346.597687,290.293457 346.814484,290.655609 347.184052,291.658813
|
||||
C348.207916,293.210449 349.079010,294.121002 349.950073,295.031586
|
||||
C349.950073,295.031586 349.997528,294.998688 350.022308,295.312134
|
||||
C350.422668,296.046722 350.798248,296.467896 351.173798,296.889099
|
||||
C351.173798,296.889099 351.088196,296.908844 351.187195,297.098938
|
||||
C351.662689,297.562439 352.039185,297.835846 352.415680,298.109222
|
||||
C352.517670,298.285431 352.619659,298.461639 352.871033,299.188538
|
||||
C353.345856,300.153381 353.671265,300.567535 353.996704,300.981689
|
||||
C353.996704,300.981689 354.015472,300.993073 354.007812,301.335846
|
||||
C354.402161,302.413605 354.804199,303.148590 355.206238,303.883575
|
||||
C355.206238,303.883575 355.018646,304.003021 355.090637,304.240479
|
||||
C355.517731,304.925629 355.872864,305.373291 356.227966,305.820984
|
||||
C356.227966,305.820984 356.153595,305.872589 356.172882,306.176147
|
||||
C356.516907,306.956207 356.841644,307.432648 357.166382,307.909119
|
||||
C357.166382,307.909119 357.040070,308.020111 357.049561,308.341949
|
||||
C357.767151,310.434601 358.475311,312.205444 359.183441,313.976257
|
||||
C359.183441,313.976257 359.285858,314.312012 359.201691,314.954956
|
||||
C359.676453,320.394745 360.235382,325.191528 360.794250,329.988342
|
||||
C360.750854,330.733398 360.707428,331.478424 360.285736,332.761963
|
||||
C359.268677,336.523132 358.629852,339.745819 357.991058,342.968475
|
||||
C350.343445,363.588776 326.667816,381.643250 299.167816,379.732178
|
||||
C290.352600,376.355316 282.288818,373.212067 274.104248,369.733521
|
||||
C272.627472,367.771759 271.155029,366.227570 269.937866,364.503143
|
||||
C266.554016,359.709045 263.276215,354.840057 259.956543,350.000671
|
||||
M292.954834,252.577637
|
||||
C284.554016,254.437103 280.101990,261.094727 282.225677,268.622253
|
||||
C284.200958,275.623901 292.044647,279.524200 298.966736,276.946747
|
||||
C304.560913,274.863800 307.829224,269.117188 306.961121,262.890320
|
||||
C306.101593,256.724701 301.323578,252.973465 292.954834,252.577637
|
||||
z"/>
|
||||
<path fill="#E8E1E3" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M230.909729,187.645721
|
||||
C227.198303,189.902634 223.030762,191.350327 219.655197,193.862289
|
||||
C214.826965,197.455246 210.563675,201.810776 206.087585,205.872009
|
||||
C203.919922,207.838776 201.817001,209.876862 199.271240,211.543579
|
||||
C198.672882,210.565842 198.382446,209.937576 198.318497,209.287033
|
||||
C196.320541,188.961105 186.114044,172.083221 175.258102,155.637466
|
||||
C166.415649,142.241974 154.793076,131.261627 141.908539,121.791832
|
||||
C137.049515,118.220581 131.245193,115.935486 125.871803,113.064095
|
||||
C125.595558,112.570015 125.319313,112.075935 125.138161,111.187073
|
||||
C125.233253,110.792297 125.195129,110.356216 125.195129,110.356216
|
||||
C125.195129,110.356216 124.768829,110.174622 124.768829,110.174622
|
||||
C124.768829,110.174622 124.790176,110.105629 124.767502,109.900299
|
||||
C124.613037,109.401230 124.410126,109.169861 124.136108,109.000877
|
||||
C123.920364,108.371086 123.649200,107.754311 123.497704,107.109436
|
||||
C122.360313,102.267998 120.207924,96.951149 124.438560,92.944710
|
||||
C128.469727,89.127167 133.921600,90.415802 138.698120,91.789146
|
||||
C153.893494,96.158127 166.522659,105.118279 178.481827,115.038651
|
||||
C199.118484,132.157196 213.024612,154.430664 225.735123,177.571503
|
||||
C227.497009,180.779190 229.120026,184.063156 230.909729,187.645721
|
||||
z"/>
|
||||
<path fill="#E2DBDC" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M310.977905,213.010101
|
||||
C309.729248,212.055908 308.122162,211.343781 307.288422,210.109360
|
||||
C300.389923,199.895523 291.576019,192.217087 279.339722,188.328522
|
||||
C292.288147,162.370239 306.773834,137.483337 328.617279,117.867462
|
||||
C339.691040,107.922951 351.728424,99.228638 365.721436,93.787331
|
||||
C369.826141,92.191185 374.370697,91.283432 378.774231,90.999680
|
||||
C385.811890,90.546196 388.295837,93.171082 387.951752,100.088501
|
||||
C387.815369,102.831184 386.765503,105.528435 385.853577,108.852493
|
||||
C385.459015,110.059547 385.342377,110.660477 385.225739,111.261406
|
||||
C385.225739,111.261406 385.158661,111.642181 384.852539,112.001289
|
||||
C384.354950,112.895798 384.163513,113.431198 383.972076,113.966599
|
||||
C383.972076,113.966606 383.995361,114.003372 383.606873,113.994675
|
||||
C373.302124,118.110992 364.961212,124.463203 356.839417,131.438354
|
||||
C339.437592,146.383347 327.000336,164.799469 318.375488,185.727234
|
||||
C314.813660,194.369843 313.379669,203.889404 310.977905,213.010101
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M125.893593,113.436935
|
||||
C131.245193,115.935486 137.049515,118.220581 141.908539,121.791832
|
||||
C154.793076,131.261627 166.415649,142.241974 175.258102,155.637466
|
||||
C186.114044,172.083221 196.320541,188.961105 198.318497,209.287033
|
||||
C198.382446,209.937576 198.672882,210.565842 198.932297,211.601837
|
||||
C197.490738,217.508926 195.974625,223.018661 194.166290,228.768127
|
||||
C196.253342,223.201889 193.574753,219.127121 189.715347,214.954758
|
||||
C163.473175,186.584579 144.348648,153.597961 127.933197,118.888847
|
||||
C127.155907,117.245331 126.583313,115.505013 125.893593,113.436935
|
||||
z"/>
|
||||
<path fill="#F1BBBC" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M310.997925,213.387329
|
||||
C313.379669,203.889404 314.813660,194.369843 318.375488,185.727234
|
||||
C327.000336,164.799469 339.437592,146.383347 356.839417,131.438354
|
||||
C364.961212,124.463203 373.302124,118.110992 383.589783,113.979858
|
||||
C380.960876,120.586807 378.457886,127.484657 374.865417,133.758698
|
||||
C364.731812,151.456390 354.837616,169.357254 343.515594,186.286224
|
||||
C335.349365,198.496567 325.048187,209.279083 315.144836,220.863037
|
||||
C314.403778,221.019226 314.217133,221.010818 314.030457,221.002396
|
||||
C313.026245,218.589783 312.022064,216.177170 310.997925,213.387329
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M314.020935,221.414658
|
||||
C314.217133,221.010818 314.403778,221.019226 314.870605,221.047455
|
||||
C316.999298,230.136887 318.847839,239.206482 320.616791,248.673187
|
||||
C319.458862,244.828888 318.331757,240.599136 317.315125,236.343002
|
||||
C316.162292,231.516632 315.108368,226.666641 314.020935,221.414658
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M325.160889,264.486053
|
||||
C323.614105,260.437592 322.029449,256.009918 320.634705,251.297119
|
||||
C322.257446,255.376953 323.690247,259.741913 325.160889,264.486053
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M360.890747,329.536377
|
||||
C360.235382,325.191528 359.676453,320.394745 359.189026,315.130005
|
||||
C359.836090,319.469543 360.411621,324.276947 360.890747,329.536377
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M193.464661,230.832916
|
||||
C193.143082,234.580215 192.573395,238.643280 191.688126,242.877060
|
||||
C191.987228,239.081406 192.601898,235.115036 193.464661,230.832916
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M358.265259,342.943604
|
||||
C358.629852,339.745819 359.268677,336.523132 360.187744,333.122986
|
||||
C360.018005,335.991302 359.567963,339.037079 359.100708,342.458130
|
||||
C358.902191,342.861877 358.720856,342.890320 358.265259,342.943604
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M190.664886,249.212097
|
||||
C190.432266,251.778214 189.961578,254.640259 189.206100,257.754944
|
||||
C189.423157,255.174377 189.924973,252.341217 190.664886,249.212097
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M359.182800,313.601257
|
||||
C358.475311,312.205444 357.767151,310.434601 357.105957,308.280884
|
||||
C357.829315,309.674072 358.505737,311.450165 359.182800,313.601257
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M349.907898,294.706573
|
||||
C349.079010,294.121002 348.207916,293.210449 347.289917,291.957703
|
||||
C348.117218,292.537537 348.991486,293.459564 349.907898,294.706573
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M191.083099,245.406372
|
||||
C191.252640,246.199524 191.307404,247.374268 191.114105,248.755707
|
||||
C190.900131,247.904266 190.934235,246.846115 191.083099,245.406372
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M330.995422,272.653015
|
||||
C330.445221,272.454437 329.825745,271.962769 329.198181,271.144989
|
||||
C329.768768,271.332581 330.347473,271.846222 330.995422,272.653015
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M329.123840,270.555267
|
||||
C328.493988,270.099426 327.798218,269.338928 327.091919,268.248749
|
||||
C327.740234,268.696228 328.399048,269.473419 329.123840,270.555267
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M332.844269,274.735840
|
||||
C332.331848,274.527893 331.732452,274.043915 331.094299,273.251587
|
||||
C331.622772,273.448761 332.190033,273.954315 332.844269,274.735840
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M345.110474,288.603455
|
||||
C344.580902,288.404968 343.955536,287.913757 343.249207,287.122131
|
||||
C343.783722,287.318054 344.399200,287.814423 345.110474,288.603455
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M355.201660,303.558167
|
||||
C354.804199,303.148590 354.402161,302.413605 354.006409,301.346680
|
||||
C354.407501,301.754120 354.802307,302.493439 355.201660,303.558167
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M351.129639,296.601501
|
||||
C350.798248,296.467896 350.422668,296.046722 350.005768,295.335632
|
||||
C350.338104,295.468414 350.711761,295.891174 351.129639,296.601501
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M188.595612,258.903992
|
||||
C188.682480,259.292603 188.550308,259.920563 188.180084,260.773743
|
||||
C188.086868,260.380402 188.231720,259.761871 188.595612,258.903992
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M327.064514,267.665863
|
||||
C326.754852,267.502319 326.411804,267.048950 326.043304,266.303406
|
||||
C326.355591,266.466156 326.693390,266.921082 327.064514,267.665863
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M357.151794,307.616943
|
||||
C356.841644,307.432648 356.516907,306.956207 356.218140,306.177032
|
||||
C356.541809,306.357819 356.839508,306.841309 357.151794,307.616943
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M356.195923,305.534912
|
||||
C355.872864,305.373291 355.517731,304.925629 355.179565,304.174133
|
||||
C355.518951,304.329834 355.841400,304.789337 356.195923,305.534912
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M353.974121,300.709167
|
||||
C353.671265,300.567535 353.345856,300.153381 352.977142,299.474915
|
||||
C353.273102,299.619293 353.612366,300.027954 353.974121,300.709167
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M352.363861,297.868530
|
||||
C352.039185,297.835846 351.662689,297.562439 351.205383,297.058960
|
||||
C351.520416,297.095215 351.916229,297.361511 352.363861,297.868530
|
||||
z"/>
|
||||
<path fill="#F1BBBC" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M384.223877,113.807907
|
||||
C384.163513,113.431198 384.354950,112.895798 384.774475,112.178146
|
||||
C384.826904,112.546997 384.651276,113.098106 384.223877,113.807907
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M343.139221,286.574432
|
||||
C342.803650,286.457123 342.420074,286.059692 341.984497,285.380615
|
||||
C342.318726,285.497437 342.705017,285.895844 343.139221,286.574432
|
||||
z"/>
|
||||
<path fill="#F1BBBC" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M385.438354,111.033051
|
||||
C385.342377,110.660477 385.459015,110.059547 385.798126,109.237564
|
||||
C385.897369,109.612564 385.774200,110.208626 385.438354,111.033051
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M124.157272,109.243233
|
||||
C124.410126,109.169861 124.613037,109.401230 124.794144,109.924683
|
||||
C124.506912,110.045639 124.285248,109.822701 124.157272,109.243233
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M124.780151,110.393814
|
||||
C124.768829,110.174622 125.195129,110.356216 125.195129,110.356216
|
||||
C125.195129,110.356216 125.233253,110.792297 125.111130,110.898666
|
||||
C124.988998,111.005028 124.791473,110.613014 124.780151,110.393814
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M334.153137,276.605957
|
||||
C333.975830,276.633636 333.674774,276.414856 333.285400,275.922668
|
||||
C333.474518,275.885986 333.751953,276.122772 334.153137,276.605957
|
||||
z"/>
|
||||
<path fill="#F4C9C9" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M187.626129,261.783325
|
||||
C187.716797,261.941620 187.600281,262.282562 187.286407,262.810181
|
||||
C187.199005,262.653198 187.308975,262.309631 187.626129,261.783325
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M325.930542,265.739441
|
||||
C325.687347,265.841309 325.450226,265.624634 325.210571,265.094696
|
||||
C325.473114,264.966003 325.715973,265.179169 325.930542,265.739441
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M346.404358,289.813019
|
||||
C346.380920,289.931335 346.116699,289.685883 346.071350,289.612030
|
||||
C346.026001,289.538177 346.427826,289.694702 346.404358,289.813019
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M341.825653,284.817505
|
||||
C341.616180,284.914307 341.383728,284.725189 341.095520,284.274323
|
||||
C341.316101,284.141113 341.570374,284.314148 341.825653,284.817505
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M339.918762,282.747803
|
||||
C339.751312,282.777252 339.494598,282.569092 339.138489,282.129456
|
||||
C339.302551,282.102081 339.566040,282.306152 339.918762,282.747803
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M338.024841,280.701233
|
||||
C337.854126,280.735229 337.571594,280.528931 337.181824,280.077972
|
||||
C337.354034,280.042511 337.633545,280.251709 338.024841,280.701233
|
||||
z"/>
|
||||
<path fill="#F3B7BD" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M336.081360,278.657837
|
||||
C335.909760,278.687286 335.617859,278.475677 335.228912,278.004883
|
||||
C335.408264,277.969360 335.684631,278.193085 336.081360,278.657837
|
||||
z"/>
|
||||
<path fill="#D4CED0" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M211.090744,380.318542
|
||||
C218.794434,376.776215 226.587387,373.561920 234.703705,370.575012
|
||||
C236.225922,378.957703 237.774445,380.741486 243.869568,380.988098
|
||||
C255.511353,381.459229 255.656281,381.319641 256.060913,369.487579
|
||||
C256.072998,369.134949 256.282776,368.789062 256.569244,367.938904
|
||||
C257.852478,371.579498 258.939972,374.664795 260.081329,378.163086
|
||||
C260.105682,383.393982 260.076202,388.211945 260.046692,393.029877
|
||||
C260.046661,393.029877 260.032471,393.026764 260.030823,393.031677
|
||||
C250.799500,392.301697 241.485840,392.101410 232.365631,390.669281
|
||||
C224.525116,389.438049 217.213715,386.160065 211.090744,380.318542
|
||||
z"/>
|
||||
<path fill="#C9C0C5" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M260.479736,393.022827
|
||||
C260.076202,388.211945 260.105682,383.393982 260.526337,378.237915
|
||||
C271.721008,378.474976 273.500488,377.427826 274.225067,370.068817
|
||||
C282.288818,373.212067 290.352600,376.355316 298.705750,379.731995
|
||||
C295.382141,386.137482 288.733490,387.570587 282.792023,389.290771
|
||||
C275.731262,391.334930 268.225647,391.842438 260.479736,393.022827
|
||||
z"/>
|
||||
<path fill="#FEFEFE" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M274.104248,369.733521
|
||||
C273.500488,377.427826 271.721008,378.474976 260.472473,377.824951
|
||||
C258.939972,374.664795 257.852478,371.579498 256.569244,367.938904
|
||||
C256.282776,368.789062 256.072998,369.134949 256.060913,369.487579
|
||||
C255.656281,381.319641 255.511353,381.459229 243.869568,380.988098
|
||||
C237.774445,380.741486 236.225922,378.957703 234.999115,370.406067
|
||||
C239.743393,364.358734 244.801987,358.918427 249.175873,352.974274
|
||||
C251.631958,349.636414 252.956131,345.465698 255.144684,340.936829
|
||||
C256.859558,344.359283 258.157684,346.950043 259.706177,349.770752
|
||||
C263.276215,354.840057 266.554016,359.709045 269.937866,364.503143
|
||||
C271.155029,366.227570 272.627472,367.771759 274.104248,369.733521
|
||||
z"/>
|
||||
<path fill="#545152" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M226.843674,264.196960
|
||||
C226.318207,271.820679 222.893372,276.137970 216.621262,277.500458
|
||||
C211.542465,278.603760 206.080322,276.190369 203.371155,271.646027
|
||||
C200.496170,266.823517 201.140274,260.451782 205.026184,256.397003
|
||||
C208.577087,252.691727 212.991531,251.629059 217.832474,252.988266
|
||||
C223.202942,254.496170 225.998428,258.384125 226.843674,264.196960
|
||||
M213.714188,261.026093
|
||||
C212.543411,262.555603 210.993347,263.952118 210.387665,265.679718
|
||||
C210.143784,266.375305 211.970764,268.695496 212.853363,268.694427
|
||||
C214.525513,268.692444 217.100754,267.989136 217.685272,266.789825
|
||||
C219.031723,264.027191 217.859756,261.682312 213.714188,261.026093
|
||||
z"/>
|
||||
<path fill="#E79F9F" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M261.024841,320.061737
|
||||
C260.751404,320.488037 260.477997,320.914337 260.081116,321.557922
|
||||
C258.512390,323.091522 257.067139,324.407806 256.157166,325.236542
|
||||
C252.118683,322.328552 248.055679,319.412415 244.004745,316.479614
|
||||
C242.933426,315.703979 241.671799,315.045959 240.913452,314.025024
|
||||
C240.189651,313.050537 239.394333,311.411987 239.762634,310.547913
|
||||
C240.121613,309.705597 241.901611,309.080292 243.079636,309.042511
|
||||
C248.406372,308.871613 253.740875,308.942719 259.541077,309.416077
|
||||
C260.347992,313.290894 260.686401,316.676331 261.024841,320.061737
|
||||
z"/>
|
||||
<path fill="#E08A8A" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M261.376526,319.995789
|
||||
C260.686401,316.676331 260.347992,313.290894 260.008301,309.459991
|
||||
C260.172150,308.956177 260.337189,308.897888 260.740112,308.725891
|
||||
C263.278534,308.666931 265.637390,308.432770 267.858429,308.881287
|
||||
C269.260468,309.164429 271.332062,310.310150 271.519806,311.353821
|
||||
C271.746368,312.613403 270.649780,314.647034 269.499115,315.506348
|
||||
C267.129303,317.276123 264.343079,318.488281 261.376526,319.995789
|
||||
z"/>
|
||||
<path fill="#292426" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M293.341583,252.539398
|
||||
C301.323578,252.973465 306.101593,256.724701 306.961121,262.890320
|
||||
C307.829224,269.117188 304.560913,274.863800 298.966736,276.946747
|
||||
C292.044647,279.524200 284.200958,275.623901 282.225677,268.622253
|
||||
C280.101990,261.094727 284.554016,254.437103 293.341583,252.539398
|
||||
M292.354797,261.570312
|
||||
C289.490845,264.210541 289.588135,266.860138 292.953247,268.696503
|
||||
C293.991150,269.262878 296.293427,268.619019 297.330811,267.729370
|
||||
C298.160095,267.018188 298.628174,264.405273 298.062531,263.847595
|
||||
C296.772827,262.576111 294.750092,262.048157 292.354797,261.570312
|
||||
z"/>
|
||||
<path fill="#F3F3F3" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M214.107452,261.017273
|
||||
C217.859756,261.682312 219.031723,264.027191 217.685272,266.789825
|
||||
C217.100754,267.989136 214.525513,268.692444 212.853363,268.694427
|
||||
C211.970764,268.695496 210.143784,266.375305 210.387665,265.679718
|
||||
C210.993347,263.952118 212.543411,262.555603 214.107452,261.017273
|
||||
z"/>
|
||||
<path fill="#EDEBEC" opacity="1.000000" stroke="none"
|
||||
d="
|
||||
M292.690002,261.394226
|
||||
C294.750092,262.048157 296.772827,262.576111 298.062531,263.847595
|
||||
C298.628174,264.405273 298.160095,267.018188 297.330811,267.729370
|
||||
C296.293427,268.619019 293.991150,269.262878 292.953247,268.696503
|
||||
C289.588135,266.860138 289.490845,264.210541 292.690002,261.394226
|
||||
z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 70 KiB |
|
@ -0,0 +1 @@
|
|||
import{S as t,i as o,a as e,b as s,s as n,e as i,c as r,n as a,d as u,f as c,l as m,g as l,r as g,h as p,j as d}from"./index-db20528a.js";import{sendText as f}from"../../../../../../../../../js/libraries/serverTools.js";import*as h from"../../../../../../../../../js/libraries/authTools.js";import"../../../../../../../../../js/components/login-component.js";import"../../../../../../../../../js/components/signup-component.js";function j(t){let o,e,n,p,d,f,h,j,w;return{c(){o=i("div"),e=i("div"),n=i("login-component"),p=r(),d=i("signup-component"),f=r(),h=i("div"),h.innerHTML="<span>OR</span>",this.c=a,u(e,"id","auth-grid-group"),u(h,"id","auth-or"),u(h,"class","pane"),u(o,"id","auth-group")},m(i,r){s(i,o,r),c(o,e),c(e,n),t[3](n),c(e,p),c(e,d),t[5](d),c(o,f),c(o,h),j||(w=[m(n,"click",t[4]),m(n,"keydown",y),m(d,"click",t[6]),m(d,"keydown",b)],j=!0)},p:a,i:a,o:a,d(e){e&&l(o),t[3](null),t[5](null),j=!1,g(w)}}}const y=()=>"",b=()=>"";function w(t,o,e){let s,n;h.redirectLogged();let i={googleInit:!1};function r(t){t==s?(e(0,s.focused=!0,s),e(1,n.focused=!1,n)):(e(0,s.focused=!1,s),e(1,n.focused=!0,n))}function a(t){console.log(t),f("/signup-google",t.credential,(t=>h.processLoginResponse(t,i.msgs,i.remember.checked)))}p("auth",i),function t(){"undefined"!=typeof google?(google.accounts.id.initialize({client_id:"93612176787-sr8qjqem4e3kok4msrnj8s1illt85a9g.apps.googleusercontent.com",callback:a,auto_select:!0,context:"signin"}),i.googleInit=!0):setTimeout(t,100)}();return[s,n,r,function(t){d[t?"unshift":"push"]((()=>{s=t,e(0,s)}))},()=>r(s),function(t){d[t?"unshift":"push"]((()=>{n=t,e(1,n)}))},()=>r(n)]}class k extends t{constructor(t){super(),this.shadowRoot.innerHTML="<style>@import '/css/common.css';@import '/css/auth.css';span{font-size:1.4rem;font-family:var(--sans-serif,sans-serif)}#auth-group{margin:auto;width:auto;margin-bottom:3rem}#auth-grid-group{display:grid;grid-template-columns:30rem 30rem;justify-content:center;gap:1.37rem;width:100%}#auth-or{display:flex;position:absolute;margin:auto;top:40%;left:50%;transform:translate(-50%, -50%);width:5.4rem;height:5.4rem;border-radius:6.8rem;background-color:white;align-items:center;justify-content:center;font-family:var(--sans-serif,sans-serif);font-weight:500}@media only screen and (max-width: 1200px){#auth-grid-group{display:grid;grid-template-columns:30rem;grid-template-rows:auto auto;justify-content:center;gap:1.37rem;width:100%}#auth-or{top:40rem}#auth-group{margin-top:2rem;margin-bottom:3rem}}</style>",o(this,{target:this.shadowRoot,props:e(this.attributes),customElement:!0},w,j,n,{},null),t&&t.target&&s(t.target,this,t.anchor)}}customElements.define("auth-component",k);export{k as default};
|
|
@ -0,0 +1 @@
|
|||
import{S as t,i as n,a as i,b as a,s,e as o,c as e,n as r,d as u,f as l,l as m,g as p,r as f,o as h,j as c}from"./index-db20528a.js";import*as d from"../../../../../../../../../js/libraries/authTools.js";function g(t){let n,i,s,h,c,d,g,x,b,C,y,v,I,w,j,k,E,T,z,M,O,R,D;return{c(){n=o("div"),i=o("h2"),i.textContent="CONFIRMATION CODE",s=e(),h=o("div"),c=o("input"),d=o("span"),d.textContent="-",g=e(),x=o("input"),b=o("span"),b.textContent="-",C=e(),y=o("input"),v=o("span"),v.textContent="-",I=e(),w=o("input"),j=o("span"),j.textContent="-",k=e(),E=o("input"),T=e(),z=o("span"),M=e(),O=o("button"),O.textContent="Confirm",this.c=r,u(i,"class","auth-title title-highlight"),u(c,"class","authConfirmationInput"),u(c,"type","text"),u(c,"maxlength","1"),u(d,"class","dash"),u(x,"class","authConfirmationInput"),u(x,"type","text"),u(x,"maxlength","1"),u(b,"class","dash"),u(y,"class","authConfirmationInput"),u(y,"type","text"),u(y,"maxlength","1"),u(v,"class","dash"),u(w,"class","authConfirmationInput"),u(w,"type","text"),u(w,"maxlength","1"),u(j,"class","dash"),u(E,"class","authConfirmationInput"),u(E,"type","text"),u(E,"maxlength","1"),u(h,"id","confirmationInputs"),u(z,"id","confirmation-msg"),u(O,"class","auth-button"),u(n,"class","pane auth-pane")},m(o,e){a(o,n,e),l(n,i),l(n,s),l(n,h),l(h,c),t[6](c),l(h,d),l(h,g),l(h,x),t[8](x),l(h,b),l(h,C),l(h,y),t[10](y),l(h,v),l(h,I),l(h,w),t[12](w),l(h,j),l(h,k),l(h,E),t[14](E),l(n,T),l(n,z),t[16](z),l(n,M),l(n,O),t[17](O),R||(D=[m(c,"input",t[7]),m(x,"input",t[9]),m(y,"input",t[11]),m(w,"input",t[13]),m(E,"input",t[15]),m(O,"click",t[18])],R=!0)},p:r,i:r,o:r,d(i){i&&p(n),t[6](null),t[8](null),t[10](null),t[12](null),t[14](null),t[16](null),t[17](null),R=!1,f(D)}}}function x(t,n,i){let a,s,o=[];function e(t,n){n.data in["0","1","2","3","4","5","6","7","8","9"]?t<4?o[t+1].focus():d.confirmEmail(a,r(),u):i(0,o[t].value="",o)}function r(){let t="";for(let n of o)t+=n.value;return parseInt(t)}function u(t){"true"==t?d.toDashboard():i(1,a.innerHTML="Wrong code",a)}h((()=>{}));return[o,a,s,e,r,u,function(t){c[t?"unshift":"push"]((()=>{o[0]=t,i(0,o)}))},t=>e(0,t),function(t){c[t?"unshift":"push"]((()=>{o[1]=t,i(0,o)}))},t=>e(1,t),function(t){c[t?"unshift":"push"]((()=>{o[2]=t,i(0,o)}))},t=>e(2,t),function(t){c[t?"unshift":"push"]((()=>{o[3]=t,i(0,o)}))},t=>e(3,t),function(t){c[t?"unshift":"push"]((()=>{o[4]=t,i(0,o)}))},t=>e(4,t),function(t){c[t?"unshift":"push"]((()=>{a=t,i(1,a)}))},function(t){c[t?"unshift":"push"]((()=>{s=t,i(2,s)}))},()=>d.confirmEmail(a,r(),u)]}class b extends t{constructor(t){super(),this.shadowRoot.innerHTML="<style>@import '/css/common.css';.auth-pane{position:relative;padding:3.4rem;padding-top:5.5rem;padding-bottom:5.5rem;width:33rem;height:auto;margin:auto}.auth-title{position:relative;left:0.7rem;top:0.2rem;margin-bottom:1.4rem}.authConfirmationInput{position:relative;width:3.16rem;font-family:var(--serif,serif);font-size:3rem;border-radius:0.34rem;margin-bottom:0.7rem;text-align:center;padding-left:0;padding-bottom:0.3 rem}.dash{display:block;font-size:3rem;font-family:var(--serif,serif)}#confirmationInputs{margin:auto;display:grid;justify-content:space-between;grid-auto-flow:column}.auth-button{margin-top:1.4rem;height:3.4rem;width:100%;font-family:var(--sans-serif,sans-serif);font-size:1.6rem;color:white;background-color:var(--pink);border-color:var(--pink);border-radius:0.5rem;filter:drop-shadow(0.07rem 0.14rem 0.07rem rgb(0 0 0 / 0.4))}#confirmation-msg{display:inline;color:red}</style>",n(this,{target:this.shadowRoot,props:i(this.attributes),customElement:!0},x,g,s,{},null),t&&t.target&&a(t.target,this,t.anchor)}}customElements.define("confirmation-component",b);export{b as default};
|
|
@ -1 +1 @@
|
|||
import{S as e,i as s,a as t,b as o,s as i,g as a,n as r,j as n,d as c,o as d}from"./index-8c09578c.js";function p(e){let s;return{c(){s=a("div"),s.innerHTML="<div><p>We use cookies to improve your experience, personalise your content and analyse site usage. By clicking “OK”, you agree to the use of cookies.</p></div>",this.c=r,n(s,"id","wrapper")},m(e,t){o(e,s,t)},p:r,i:r,o:r,d(e){e&&c(s)}}}function u(e){return d((()=>{})),[]}class h extends e{constructor(e){super(),this.shadowRoot.innerHTML="<style>@import '/css/common.css';#wrapper{display:none;position:relative;height:5rem;width:100%;background:white;box-shadow:0 0 0.314rem rgb(187, 187, 187);;}</style>",s(this,{target:this.shadowRoot,props:t(this.attributes),customElement:!0},u,p,i,{},null),e&&e.target&&o(e.target,this,e.anchor)}}customElements.define("cookies-dialog",h);export{h as default};
|
||||
import{S as e,i as s,a as t,b as o,s as i,e as a,n as r,d as n,g as c,o as d}from"./index-db20528a.js";function p(e){let s;return{c(){s=a("div"),s.innerHTML="<div><p>We use cookies to improve your experience, personalise your content and analyse site usage. By clicking “OK”, you agree to the use of cookies.</p></div>",this.c=r,n(s,"id","wrapper")},m(e,t){o(e,s,t)},p:r,i:r,o:r,d(e){e&&c(s)}}}function u(e){return d((()=>{})),[]}class h extends e{constructor(e){super(),this.shadowRoot.innerHTML="<style>@import '/css/common.css';#wrapper{display:none;position:relative;height:5rem;width:100%;background:white;box-shadow:0 0 0.314rem rgb(187, 187, 187);;}</style>",s(this,{target:this.shadowRoot,props:t(this.attributes),customElement:!0},u,p,i,{},null),e&&e.target&&o(e.target,this,e.anchor)}}customElements.define("cookies-dialog",h);export{h as default};
|
||||
|
|
|
@ -1 +1 @@
|
|||
import{S as t,i as e,a as o,b as r,s as a,e as i,n,d as s,c as m,g as c,t as f,h as d,j as l,w as g,m as p,p as h,q as u}from"./index-8c09578c.js";import{w}from"./index-77787e10.js";import{loadLocaleContent as b}from"../../../../../../../../../js/libraries/serverTools.js";function v(t){let e,o,a,i,n,m,w,b,v,k,y,x,L,j,z,U,_,C,T,B,H,M,R=t[1].contactUs+"",A=t[1].inviteLink+"",D=t[1].inviteLink+"";return{c(){e=c("footer"),o=c("div"),a=c("div"),i=c("div"),n=c("h2"),m=f(R),w=d(),b=c("p"),v=f("Discord: "),k=c("a"),y=f(A),x=d(),L=c("p"),j=f("WhatsApp: "),z=c("a"),U=f(D),_=d(),C=c("button"),C.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="42.545" height="72.601" viewBox="0 0 42.545 72.601"><g id="Group_268" data-name="Group 268" transform="translate(-6.177 -2.399)"><rect id="Rectangle_146" data-name="Rectangle 146" width="11" height="51" rx="5.5" transform="translate(22 24)" fill="#cb1816"></rect><path id="Path_1145" data-name="Path 1145" d="M23.814,4.021a5,5,0,0,1,7.372,0l16.134,17.6c2.94,3.207,1.046,10.4-3.686,8.379S28.02,14.081,28.391,13.524,16.544,27.976,11.366,30,4.741,24.828,7.68,21.621Z" fill="#DD1C1A"></path></g></svg>',T=d(),B=c("p"),B.innerHTML='Licensed under a Creative Commons <a href="https://creativecommons.org/licenses/by/4.0/legalcode " target="_blank" rel="noreferrer">CC BY 4.0 license</a>',l(k,"href","https://discord.gg/Qk8KUk787z"),l(k,"target","_blank"),l(k,"rel","noreferrer"),g(k,"margin-left","1.8rem"),l(z,"href","https://chat.whatsapp.com/BhnmUNljUxJ2AjeHUwyTKh"),l(z,"target","_blank"),l(z,"rel","noreferrer"),g(z,"margin-left","0.5rem"),l(i,"id","contact-us-container"),l(a,"id","footer-grid-content-container"),l(a,"class","logged"),l(C,"id","footer-up"),l(C,"aria-label","go up"),l(B,"id","footer-copyright"),l(o,"id","footer-content-container")},m(s,c){r(s,e,c),p(e,o),p(o,a),p(a,i),p(i,n),p(n,m),p(i,w),p(i,b),p(b,v),p(b,k),p(k,y),p(i,x),p(i,L),p(L,j),p(L,z),p(z,U),p(o,_),p(o,C),p(o,T),p(o,B),H||(M=h(C,"click",t[4]),H=!0)},p(t,e){2&e&&R!==(R=t[1].contactUs+"")&&u(m,R),2&e&&A!==(A=t[1].inviteLink+"")&&u(y,A),2&e&&D!==(D=t[1].inviteLink+"")&&u(U,D)},d(t){t&&s(e),H=!1,M()}}}function k(t){let e,o=2==t[0]&&v(t);return{c(){o&&o.c(),e=i()},m(t,a){o&&o.m(t,a),r(t,e,a)},p(t,r){2==t[0]?o?o.p(t,r):(o=v(t),o.c(),o.m(e.parentNode,e)):o&&(o.d(1),o=null)},d(t){o&&o.d(t),t&&s(e)}}}function y(t){let e,o=t[0],m=k(t);return{c(){m.c(),e=i(),this.c=n},m(t,o){m.m(t,o),r(t,e,o)},p(t,[r]){1&r&&a(o,o=t[0])?(m.d(1),m=k(t),m.c(),m.m(e.parentNode,e)):m.p(t,r)},i:n,o:n,d(t){t&&s(e),m.d(t)}}}function x(t,e,o){let r,a,i=w(0);m(t,i,(t=>o(0,r=t)));let n=w({});m(t,n,(t=>o(1,a=t))),b(n,"countries",i),b(n,"footer-component",i);return[r,a,i,n,()=>{location.href="#"}]}class L extends t{constructor(t){super(),this.shadowRoot.innerHTML="<style>@import '/css/common.css';footer{position:relative;bottom:0;width:100%;height:auto;background:#5B6970;border-top:#cb1816 solid 0.5rem}footer p,footer a{font-family:var(--sans-serif)}#footer-content-container{position:relative;margin:auto;padding-top:2rem;max-width:116rem;width:97vw}#footer-grid-content-container{display:grid;margin-left:2rem;margin-right:2rem;margin-bottom:1rem}.logged{grid-template-columns:auto auto 2rem}footer h2{color:#ffffff;font-size:1.3rem;margin-bottom:0.5rem}#footer-copyright{position:relative;margin:auto;width:100%;bottom:0rem;height:3rem;top:0rem;margin-bottom:0;font-size:1rem;text-align:center}#footer-copyright *{font-size:1rem}footer a{font-size:1.1rem;color:#ffffff}footer p{display:block;font-size:1.1rem;color:#d8d8d8;font-family:var(--sans-serif,sans-serif);margin-bottom:0.5rem}#contact-us-container{width:16rem}#footer-up{position:absolute;width:4.8rem;height:4.8rem;border-radius:3.4rem;top:4rem;right:2rem;background:#ffffff}#footer-up svg{width:40%;height:auto}@media only screen and (max-width: 1170px){.logged{grid-template-rows:auto auto auto;grid-template-columns:auto;row-gap:2rem}#footer-copyright{height:1rem;top:-2rem}}</style>",e(this,{target:this.shadowRoot,props:o(this.attributes),customElement:!0},x,y,a,{},null),t&&t.target&&r(t.target,this,t.anchor)}}customElements.define("footer-component",L);export{L as default};
|
||||
import{S as t,i as e,a as r,b as o,s as a,p as i,n,g as s,q as m,e as c,v as d,c as f,d as l,y as g,f as p,l as h,w as u}from"./index-db20528a.js";import{w as v}from"./index-720c0a59.js";import{loadLocaleContent as w}from"../../../../../../../../../js/libraries/serverTools.js";function b(t){let e,r,a,i,n,m,v,w,b,y,k,x,L,j,z,U,_,T,C,H,M,R,B=t[1].contactUs+"",N=t[1].inviteLink+"",A=t[1].inviteLink+"";return{c(){e=c("footer"),r=c("div"),a=c("div"),i=c("div"),n=c("h2"),m=d(B),v=f(),w=c("p"),b=d("Discord: "),y=c("a"),k=d(N),x=f(),L=c("p"),j=d("WhatsApp: "),z=c("a"),U=d(A),_=f(),T=c("button"),T.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="42.545" height="72.601" viewBox="0 0 42.545 72.601"><g id="Group_268" data-name="Group 268" transform="translate(-6.177 -2.399)"><rect id="Rectangle_146" data-name="Rectangle 146" width="11" height="51" rx="5.5" transform="translate(22 24)" fill="var(--red)"></rect><path id="Path_1145" data-name="Path 1145" d="M23.814,4.021a5,5,0,0,1,7.372,0l16.134,17.6c2.94,3.207,1.046,10.4-3.686,8.379S28.02,14.081,28.391,13.524,16.544,27.976,11.366,30,4.741,24.828,7.68,21.621Z" fill="var(--red)"></path></g></svg>',C=f(),H=c("p"),H.innerHTML='Licensed under a Creative Commons <a href="https://creativecommons.org/licenses/by/4.0/legalcode " target="_blank" rel="noreferrer">CC BY 4.0 license</a>',l(y,"href","https://discord.gg/Qk8KUk787z"),l(y,"target","_blank"),l(y,"rel","noreferrer"),g(y,"margin-left","1.8rem"),l(z,"href","https://chat.whatsapp.com/BhnmUNljUxJ2AjeHUwyTKh"),l(z,"target","_blank"),l(z,"rel","noreferrer"),g(z,"margin-left","0.5rem"),l(i,"id","contact-us-container"),l(a,"id","footer-grid-content-container"),l(a,"class","logged"),l(T,"id","footer-up"),l(T,"aria-label","go up"),l(H,"id","footer-copyright"),l(r,"id","footer-content-container")},m(s,c){o(s,e,c),p(e,r),p(r,a),p(a,i),p(i,n),p(n,m),p(i,v),p(i,w),p(w,b),p(w,y),p(y,k),p(i,x),p(i,L),p(L,j),p(L,z),p(z,U),p(r,_),p(r,T),p(r,C),p(r,H),M||(R=h(T,"click",t[4]),M=!0)},p(t,e){2&e&&B!==(B=t[1].contactUs+"")&&u(m,B),2&e&&N!==(N=t[1].inviteLink+"")&&u(k,N),2&e&&A!==(A=t[1].inviteLink+"")&&u(U,A)},d(t){t&&s(e),M=!1,R()}}}function y(t){let e,r=2==t[0]&&b(t);return{c(){r&&r.c(),e=i()},m(t,a){r&&r.m(t,a),o(t,e,a)},p(t,o){2==t[0]?r?r.p(t,o):(r=b(t),r.c(),r.m(e.parentNode,e)):r&&(r.d(1),r=null)},d(t){r&&r.d(t),t&&s(e)}}}function k(t){let e,r=t[0],m=y(t);return{c(){m.c(),e=i(),this.c=n},m(t,r){m.m(t,r),o(t,e,r)},p(t,[o]){1&o&&a(r,r=t[0])?(m.d(1),m=y(t),m.c(),m.m(e.parentNode,e)):m.p(t,o)},i:n,o:n,d(t){t&&s(e),m.d(t)}}}function x(t,e,r){let o,a,i=v(0);m(t,i,(t=>r(0,o=t)));let n=v({});m(t,n,(t=>r(1,a=t))),w(n,"countries",i),w(n,"footer-component",i);return[o,a,i,n,()=>{location.href="#"}]}class L extends t{constructor(t){super(),this.shadowRoot.innerHTML="<style>@import '/css/common.css';footer{position:relative;bottom:0;width:100%;height:auto;background:var(--gray);border-top:var(--red) solid 0.5rem}footer p,footer a{font-family:var(--sans-serif)}#footer-content-container{position:relative;margin:auto;padding-top:2rem;max-width:116rem;width:97vw}#footer-grid-content-container{display:grid;margin-left:2rem;margin-right:2rem;margin-bottom:1rem}.logged{grid-template-columns:auto auto 2rem}footer h2{color:#ffffff;font-size:1.3rem;margin-bottom:0.5rem}#footer-copyright{position:relative;margin:auto;width:100%;bottom:0rem;height:3rem;top:0rem;margin-bottom:0;font-size:1rem;text-align:center}#footer-copyright *{font-size:1rem}footer a{font-size:1.1rem;color:#ffffff}footer p{display:block;font-size:1.1rem;color:#d8d8d8;font-family:var(--sans-serif,sans-serif);margin-bottom:0.5rem}#contact-us-container{width:16rem}#footer-up{position:absolute;width:4.8rem;height:4.8rem;border-radius:3.4rem;top:4rem;right:2rem;background:#ffffff}#footer-up svg{width:40%;height:auto}@media only screen and (max-width: 1170px){.logged{grid-template-rows:auto auto auto;grid-template-columns:auto;row-gap:2rem}#footer-copyright{height:1rem;top:-2rem}}</style>",e(this,{target:this.shadowRoot,props:r(this.attributes),customElement:!0},x,k,a,{},null),t&&t.target&&o(t.target,this,t.anchor)}}customElements.define("footer-component",L);export{L as default};
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
import { n as noop, s as safe_not_equal } from './index-e7d4b1a1.js';
|
||||
|
||||
const subscriber_queue = [];
|
||||
/**
|
||||
* Create a `Writable` store that allows both updating and reading by subscription.
|
||||
* @param {*=}value initial value
|
||||
* @param {StartStopNotifier=}start start and stop notifications for subscriptions
|
||||
*/
|
||||
function writable(value, start = noop) {
|
||||
let stop;
|
||||
const subscribers = new Set();
|
||||
function set(new_value) {
|
||||
if (safe_not_equal(value, new_value)) {
|
||||
value = new_value;
|
||||
if (stop) { // store is ready
|
||||
const run_queue = !subscriber_queue.length;
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber[1]();
|
||||
subscriber_queue.push(subscriber, value);
|
||||
}
|
||||
if (run_queue) {
|
||||
for (let i = 0; i < subscriber_queue.length; i += 2) {
|
||||
subscriber_queue[i][0](subscriber_queue[i + 1]);
|
||||
}
|
||||
subscriber_queue.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function update(fn) {
|
||||
set(fn(value));
|
||||
}
|
||||
function subscribe(run, invalidate = noop) {
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.add(subscriber);
|
||||
if (subscribers.size === 1) {
|
||||
stop = start(set) || noop;
|
||||
}
|
||||
run(value);
|
||||
return () => {
|
||||
subscribers.delete(subscriber);
|
||||
if (subscribers.size === 0) {
|
||||
stop();
|
||||
stop = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return { set, update, subscribe };
|
||||
}
|
||||
|
||||
export { writable as w };
|
|
@ -0,0 +1,513 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
function noop() { }
|
||||
function add_location(element, file, line, column, char) {
|
||||
element.__svelte_meta = {
|
||||
loc: { file, line, column, char }
|
||||
};
|
||||
}
|
||||
function run(fn) {
|
||||
return fn();
|
||||
}
|
||||
function blank_object() {
|
||||
return Object.create(null);
|
||||
}
|
||||
function run_all(fns) {
|
||||
fns.forEach(run);
|
||||
}
|
||||
function is_function(thing) {
|
||||
return typeof thing === 'function';
|
||||
}
|
||||
function safe_not_equal(a, b) {
|
||||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
|
||||
}
|
||||
let src_url_equal_anchor;
|
||||
function src_url_equal(element_src, url) {
|
||||
if (!src_url_equal_anchor) {
|
||||
src_url_equal_anchor = document.createElement('a');
|
||||
}
|
||||
src_url_equal_anchor.href = url;
|
||||
return element_src === src_url_equal_anchor.href;
|
||||
}
|
||||
function is_empty(obj) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
function validate_store(store, name) {
|
||||
if (store != null && typeof store.subscribe !== 'function') {
|
||||
throw new Error(`'${name}' is not a store with a 'subscribe' method`);
|
||||
}
|
||||
}
|
||||
function subscribe(store, ...callbacks) {
|
||||
if (store == null) {
|
||||
return noop;
|
||||
}
|
||||
const unsub = store.subscribe(...callbacks);
|
||||
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
|
||||
}
|
||||
function component_subscribe(component, store, callback) {
|
||||
component.$$.on_destroy.push(subscribe(store, callback));
|
||||
}
|
||||
function append(target, node) {
|
||||
target.appendChild(node);
|
||||
}
|
||||
function insert(target, node, anchor) {
|
||||
target.insertBefore(node, anchor || null);
|
||||
}
|
||||
function detach(node) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
function destroy_each(iterations, detaching) {
|
||||
for (let i = 0; i < iterations.length; i += 1) {
|
||||
if (iterations[i])
|
||||
iterations[i].d(detaching);
|
||||
}
|
||||
}
|
||||
function element(name) {
|
||||
return document.createElement(name);
|
||||
}
|
||||
function svg_element(name) {
|
||||
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||
}
|
||||
function text(data) {
|
||||
return document.createTextNode(data);
|
||||
}
|
||||
function space() {
|
||||
return text(' ');
|
||||
}
|
||||
function empty() {
|
||||
return text('');
|
||||
}
|
||||
function listen(node, event, handler, options) {
|
||||
node.addEventListener(event, handler, options);
|
||||
return () => node.removeEventListener(event, handler, options);
|
||||
}
|
||||
function attr(node, attribute, value) {
|
||||
if (value == null)
|
||||
node.removeAttribute(attribute);
|
||||
else if (node.getAttribute(attribute) !== value)
|
||||
node.setAttribute(attribute, value);
|
||||
}
|
||||
function set_custom_element_data(node, prop, value) {
|
||||
if (prop in node) {
|
||||
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
|
||||
}
|
||||
else {
|
||||
attr(node, prop, value);
|
||||
}
|
||||
}
|
||||
function children(element) {
|
||||
return Array.from(element.childNodes);
|
||||
}
|
||||
function set_style(node, key, value, important) {
|
||||
if (value === null) {
|
||||
node.style.removeProperty(key);
|
||||
}
|
||||
else {
|
||||
node.style.setProperty(key, value, important ? 'important' : '');
|
||||
}
|
||||
}
|
||||
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
|
||||
const e = document.createEvent('CustomEvent');
|
||||
e.initCustomEvent(type, bubbles, cancelable, detail);
|
||||
return e;
|
||||
}
|
||||
class HtmlTag {
|
||||
constructor(is_svg = false) {
|
||||
this.is_svg = false;
|
||||
this.is_svg = is_svg;
|
||||
this.e = this.n = null;
|
||||
}
|
||||
c(html) {
|
||||
this.h(html);
|
||||
}
|
||||
m(html, target, anchor = null) {
|
||||
if (!this.e) {
|
||||
if (this.is_svg)
|
||||
this.e = svg_element(target.nodeName);
|
||||
else
|
||||
this.e = element(target.nodeName);
|
||||
this.t = target;
|
||||
this.c(html);
|
||||
}
|
||||
this.i(anchor);
|
||||
}
|
||||
h(html) {
|
||||
this.e.innerHTML = html;
|
||||
this.n = Array.from(this.e.childNodes);
|
||||
}
|
||||
i(anchor) {
|
||||
for (let i = 0; i < this.n.length; i += 1) {
|
||||
insert(this.t, this.n[i], anchor);
|
||||
}
|
||||
}
|
||||
p(html) {
|
||||
this.d();
|
||||
this.h(html);
|
||||
this.i(this.a);
|
||||
}
|
||||
d() {
|
||||
this.n.forEach(detach);
|
||||
}
|
||||
}
|
||||
function attribute_to_object(attributes) {
|
||||
const result = {};
|
||||
for (const attribute of attributes) {
|
||||
result[attribute.name] = attribute.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let current_component;
|
||||
function set_current_component(component) {
|
||||
current_component = component;
|
||||
}
|
||||
function get_current_component() {
|
||||
if (!current_component)
|
||||
throw new Error('Function called outside component initialization');
|
||||
return current_component;
|
||||
}
|
||||
/**
|
||||
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
|
||||
* It must be called during the component's initialisation (but doesn't need to live *inside* the component;
|
||||
* it can be called from an external module).
|
||||
*
|
||||
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-onmount
|
||||
*/
|
||||
function onMount(fn) {
|
||||
get_current_component().$$.on_mount.push(fn);
|
||||
}
|
||||
/**
|
||||
* Associates an arbitrary `context` object with the current component and the specified `key`
|
||||
* and returns that object. The context is then available to children of the component
|
||||
* (including slotted content) with `getContext`.
|
||||
*
|
||||
* Like lifecycle functions, this must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-setcontext
|
||||
*/
|
||||
function setContext(key, context) {
|
||||
get_current_component().$$.context.set(key, context);
|
||||
return context;
|
||||
}
|
||||
/**
|
||||
* Retrieves the context that belongs to the closest parent component with the specified `key`.
|
||||
* Must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-getcontext
|
||||
*/
|
||||
function getContext(key) {
|
||||
return get_current_component().$$.context.get(key);
|
||||
}
|
||||
|
||||
const dirty_components = [];
|
||||
const binding_callbacks = [];
|
||||
const render_callbacks = [];
|
||||
const flush_callbacks = [];
|
||||
const resolved_promise = Promise.resolve();
|
||||
let update_scheduled = false;
|
||||
function schedule_update() {
|
||||
if (!update_scheduled) {
|
||||
update_scheduled = true;
|
||||
resolved_promise.then(flush);
|
||||
}
|
||||
}
|
||||
function add_render_callback(fn) {
|
||||
render_callbacks.push(fn);
|
||||
}
|
||||
// flush() calls callbacks in this order:
|
||||
// 1. All beforeUpdate callbacks, in order: parents before children
|
||||
// 2. All bind:this callbacks, in reverse order: children before parents.
|
||||
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
|
||||
// for afterUpdates called during the initial onMount, which are called in
|
||||
// reverse order: children before parents.
|
||||
// Since callbacks might update component values, which could trigger another
|
||||
// call to flush(), the following steps guard against this:
|
||||
// 1. During beforeUpdate, any updated components will be added to the
|
||||
// dirty_components array and will cause a reentrant call to flush(). Because
|
||||
// the flush index is kept outside the function, the reentrant call will pick
|
||||
// up where the earlier call left off and go through all dirty components. The
|
||||
// current_component value is saved and restored so that the reentrant call will
|
||||
// not interfere with the "parent" flush() call.
|
||||
// 2. bind:this callbacks cannot trigger new flush() calls.
|
||||
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
|
||||
// callback called a second time; the seen_callbacks set, outside the flush()
|
||||
// function, guarantees this behavior.
|
||||
const seen_callbacks = new Set();
|
||||
let flushidx = 0; // Do *not* move this inside the flush() function
|
||||
function flush() {
|
||||
const saved_component = current_component;
|
||||
do {
|
||||
// first, call beforeUpdate functions
|
||||
// and update components
|
||||
while (flushidx < dirty_components.length) {
|
||||
const component = dirty_components[flushidx];
|
||||
flushidx++;
|
||||
set_current_component(component);
|
||||
update(component.$$);
|
||||
}
|
||||
set_current_component(null);
|
||||
dirty_components.length = 0;
|
||||
flushidx = 0;
|
||||
while (binding_callbacks.length)
|
||||
binding_callbacks.pop()();
|
||||
// then, once components are updated, call
|
||||
// afterUpdate functions. This may cause
|
||||
// subsequent updates...
|
||||
for (let i = 0; i < render_callbacks.length; i += 1) {
|
||||
const callback = render_callbacks[i];
|
||||
if (!seen_callbacks.has(callback)) {
|
||||
// ...so guard against infinite loops
|
||||
seen_callbacks.add(callback);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
render_callbacks.length = 0;
|
||||
} while (dirty_components.length);
|
||||
while (flush_callbacks.length) {
|
||||
flush_callbacks.pop()();
|
||||
}
|
||||
update_scheduled = false;
|
||||
seen_callbacks.clear();
|
||||
set_current_component(saved_component);
|
||||
}
|
||||
function update($$) {
|
||||
if ($$.fragment !== null) {
|
||||
$$.update();
|
||||
run_all($$.before_update);
|
||||
const dirty = $$.dirty;
|
||||
$$.dirty = [-1];
|
||||
$$.fragment && $$.fragment.p($$.ctx, dirty);
|
||||
$$.after_update.forEach(add_render_callback);
|
||||
}
|
||||
}
|
||||
const outroing = new Set();
|
||||
function transition_in(block, local) {
|
||||
if (block && block.i) {
|
||||
outroing.delete(block);
|
||||
block.i(local);
|
||||
}
|
||||
}
|
||||
|
||||
const globals = (typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof globalThis !== 'undefined'
|
||||
? globalThis
|
||||
: global);
|
||||
function mount_component(component, target, anchor, customElement) {
|
||||
const { fragment, after_update } = component.$$;
|
||||
fragment && fragment.m(target, anchor);
|
||||
if (!customElement) {
|
||||
// onMount happens before the initial afterUpdate
|
||||
add_render_callback(() => {
|
||||
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
||||
// if the component was destroyed immediately
|
||||
// it will update the `$$.on_destroy` reference to `null`.
|
||||
// the destructured on_destroy may still reference to the old array
|
||||
if (component.$$.on_destroy) {
|
||||
component.$$.on_destroy.push(...new_on_destroy);
|
||||
}
|
||||
else {
|
||||
// Edge case - component was destroyed immediately,
|
||||
// most likely as a result of a binding initialising
|
||||
run_all(new_on_destroy);
|
||||
}
|
||||
component.$$.on_mount = [];
|
||||
});
|
||||
}
|
||||
after_update.forEach(add_render_callback);
|
||||
}
|
||||
function destroy_component(component, detaching) {
|
||||
const $$ = component.$$;
|
||||
if ($$.fragment !== null) {
|
||||
run_all($$.on_destroy);
|
||||
$$.fragment && $$.fragment.d(detaching);
|
||||
// TODO null out other refs, including component.$$ (but need to
|
||||
// preserve final state?)
|
||||
$$.on_destroy = $$.fragment = null;
|
||||
$$.ctx = [];
|
||||
}
|
||||
}
|
||||
function make_dirty(component, i) {
|
||||
if (component.$$.dirty[0] === -1) {
|
||||
dirty_components.push(component);
|
||||
schedule_update();
|
||||
component.$$.dirty.fill(0);
|
||||
}
|
||||
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
|
||||
}
|
||||
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
|
||||
const parent_component = current_component;
|
||||
set_current_component(component);
|
||||
const $$ = component.$$ = {
|
||||
fragment: null,
|
||||
ctx: [],
|
||||
// state
|
||||
props,
|
||||
update: noop,
|
||||
not_equal,
|
||||
bound: blank_object(),
|
||||
// lifecycle
|
||||
on_mount: [],
|
||||
on_destroy: [],
|
||||
on_disconnect: [],
|
||||
before_update: [],
|
||||
after_update: [],
|
||||
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
||||
// everything else
|
||||
callbacks: blank_object(),
|
||||
dirty,
|
||||
skip_bound: false,
|
||||
root: options.target || parent_component.$$.root
|
||||
};
|
||||
append_styles && append_styles($$.root);
|
||||
let ready = false;
|
||||
$$.ctx = instance
|
||||
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
||||
const value = rest.length ? rest[0] : ret;
|
||||
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
|
||||
if (!$$.skip_bound && $$.bound[i])
|
||||
$$.bound[i](value);
|
||||
if (ready)
|
||||
make_dirty(component, i);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
: [];
|
||||
$$.update();
|
||||
ready = true;
|
||||
run_all($$.before_update);
|
||||
// `false` as a special case of no DOM component
|
||||
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
|
||||
if (options.target) {
|
||||
if (options.hydrate) {
|
||||
const nodes = children(options.target);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.l(nodes);
|
||||
nodes.forEach(detach);
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.c();
|
||||
}
|
||||
if (options.intro)
|
||||
transition_in(component.$$.fragment);
|
||||
mount_component(component, options.target, options.anchor, options.customElement);
|
||||
flush();
|
||||
}
|
||||
set_current_component(parent_component);
|
||||
}
|
||||
let SvelteElement;
|
||||
if (typeof HTMLElement === 'function') {
|
||||
SvelteElement = class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
connectedCallback() {
|
||||
const { on_mount } = this.$$;
|
||||
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
|
||||
// @ts-ignore todo: improve typings
|
||||
for (const key in this.$$.slotted) {
|
||||
// @ts-ignore todo: improve typings
|
||||
this.appendChild(this.$$.slotted[key]);
|
||||
}
|
||||
}
|
||||
attributeChangedCallback(attr, _oldValue, newValue) {
|
||||
this[attr] = newValue;
|
||||
}
|
||||
disconnectedCallback() {
|
||||
run_all(this.$$.on_disconnect);
|
||||
}
|
||||
$destroy() {
|
||||
destroy_component(this, 1);
|
||||
this.$destroy = noop;
|
||||
}
|
||||
$on(type, callback) {
|
||||
// TODO should this delegate to addEventListener?
|
||||
if (!is_function(callback)) {
|
||||
return noop;
|
||||
}
|
||||
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
|
||||
callbacks.push(callback);
|
||||
return () => {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index !== -1)
|
||||
callbacks.splice(index, 1);
|
||||
};
|
||||
}
|
||||
$set($$props) {
|
||||
if (this.$$set && !is_empty($$props)) {
|
||||
this.$$.skip_bound = true;
|
||||
this.$$set($$props);
|
||||
this.$$.skip_bound = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function dispatch_dev(type, detail) {
|
||||
document.dispatchEvent(custom_event(type, Object.assign({ version: '3.52.0' }, detail), { bubbles: true }));
|
||||
}
|
||||
function append_dev(target, node) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node });
|
||||
append(target, node);
|
||||
}
|
||||
function insert_dev(target, node, anchor) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node, anchor });
|
||||
insert(target, node, anchor);
|
||||
}
|
||||
function detach_dev(node) {
|
||||
dispatch_dev('SvelteDOMRemove', { node });
|
||||
detach(node);
|
||||
}
|
||||
function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation) {
|
||||
const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
|
||||
if (has_prevent_default)
|
||||
modifiers.push('preventDefault');
|
||||
if (has_stop_propagation)
|
||||
modifiers.push('stopPropagation');
|
||||
dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
|
||||
const dispose = listen(node, event, handler, options);
|
||||
return () => {
|
||||
dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
|
||||
dispose();
|
||||
};
|
||||
}
|
||||
function attr_dev(node, attribute, value) {
|
||||
attr(node, attribute, value);
|
||||
if (value == null)
|
||||
dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
|
||||
else
|
||||
dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
|
||||
}
|
||||
function prop_dev(node, property, value) {
|
||||
node[property] = value;
|
||||
dispatch_dev('SvelteDOMSetProperty', { node, property, value });
|
||||
}
|
||||
function set_data_dev(text, data) {
|
||||
data = '' + data;
|
||||
if (text.wholeText === data)
|
||||
return;
|
||||
dispatch_dev('SvelteDOMSetData', { node: text, data });
|
||||
text.data = data;
|
||||
}
|
||||
function validate_each_argument(arg) {
|
||||
if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
|
||||
let msg = '{#each} only iterates over array-like objects.';
|
||||
if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
|
||||
msg += ' You can use a spread to convert this iterable into an array.';
|
||||
}
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
function validate_slots(name, slot, keys) {
|
||||
for (const slot_key of Object.keys(slot)) {
|
||||
if (!~keys.indexOf(slot_key)) {
|
||||
console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { validate_each_argument as A, text as B, set_data_dev as C, destroy_each as D, prop_dev as E, set_style as F, svg_element as G, is_function as H, HtmlTag as I, SvelteElement as S, attribute_to_object as a, insert_dev as b, setContext as c, dispatch_dev as d, globals as e, element as f, getContext as g, space as h, init as i, add_location as j, attr_dev as k, append_dev as l, listen_dev as m, noop as n, onMount as o, detach_dev as p, binding_callbacks as q, run_all as r, safe_not_equal as s, flush as t, src_url_equal as u, validate_slots as v, validate_store as w, component_subscribe as x, empty as y, set_custom_element_data as z };
|
|
@ -0,0 +1,521 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
function noop() { }
|
||||
function add_location(element, file, line, column, char) {
|
||||
element.__svelte_meta = {
|
||||
loc: { file, line, column, char }
|
||||
};
|
||||
}
|
||||
function run(fn) {
|
||||
return fn();
|
||||
}
|
||||
function blank_object() {
|
||||
return Object.create(null);
|
||||
}
|
||||
function run_all(fns) {
|
||||
fns.forEach(run);
|
||||
}
|
||||
function is_function(thing) {
|
||||
return typeof thing === 'function';
|
||||
}
|
||||
function safe_not_equal(a, b) {
|
||||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
|
||||
}
|
||||
let src_url_equal_anchor;
|
||||
function src_url_equal(element_src, url) {
|
||||
if (!src_url_equal_anchor) {
|
||||
src_url_equal_anchor = document.createElement('a');
|
||||
}
|
||||
src_url_equal_anchor.href = url;
|
||||
return element_src === src_url_equal_anchor.href;
|
||||
}
|
||||
function is_empty(obj) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
function validate_store(store, name) {
|
||||
if (store != null && typeof store.subscribe !== 'function') {
|
||||
throw new Error(`'${name}' is not a store with a 'subscribe' method`);
|
||||
}
|
||||
}
|
||||
function subscribe(store, ...callbacks) {
|
||||
if (store == null) {
|
||||
return noop;
|
||||
}
|
||||
const unsub = store.subscribe(...callbacks);
|
||||
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
|
||||
}
|
||||
function component_subscribe(component, store, callback) {
|
||||
component.$$.on_destroy.push(subscribe(store, callback));
|
||||
}
|
||||
function append(target, node) {
|
||||
target.appendChild(node);
|
||||
}
|
||||
function insert(target, node, anchor) {
|
||||
target.insertBefore(node, anchor || null);
|
||||
}
|
||||
function detach(node) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
function destroy_each(iterations, detaching) {
|
||||
for (let i = 0; i < iterations.length; i += 1) {
|
||||
if (iterations[i])
|
||||
iterations[i].d(detaching);
|
||||
}
|
||||
}
|
||||
function element(name) {
|
||||
return document.createElement(name);
|
||||
}
|
||||
function svg_element(name) {
|
||||
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||
}
|
||||
function text(data) {
|
||||
return document.createTextNode(data);
|
||||
}
|
||||
function space() {
|
||||
return text(' ');
|
||||
}
|
||||
function empty() {
|
||||
return text('');
|
||||
}
|
||||
function listen(node, event, handler, options) {
|
||||
node.addEventListener(event, handler, options);
|
||||
return () => node.removeEventListener(event, handler, options);
|
||||
}
|
||||
function attr(node, attribute, value) {
|
||||
if (value == null)
|
||||
node.removeAttribute(attribute);
|
||||
else if (node.getAttribute(attribute) !== value)
|
||||
node.setAttribute(attribute, value);
|
||||
}
|
||||
function set_custom_element_data(node, prop, value) {
|
||||
if (prop in node) {
|
||||
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
|
||||
}
|
||||
else {
|
||||
attr(node, prop, value);
|
||||
}
|
||||
}
|
||||
function children(element) {
|
||||
return Array.from(element.childNodes);
|
||||
}
|
||||
function set_style(node, key, value, important) {
|
||||
if (value === null) {
|
||||
node.style.removeProperty(key);
|
||||
}
|
||||
else {
|
||||
node.style.setProperty(key, value, important ? 'important' : '');
|
||||
}
|
||||
}
|
||||
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
|
||||
const e = document.createEvent('CustomEvent');
|
||||
e.initCustomEvent(type, bubbles, cancelable, detail);
|
||||
return e;
|
||||
}
|
||||
class HtmlTag {
|
||||
constructor(is_svg = false) {
|
||||
this.is_svg = false;
|
||||
this.is_svg = is_svg;
|
||||
this.e = this.n = null;
|
||||
}
|
||||
c(html) {
|
||||
this.h(html);
|
||||
}
|
||||
m(html, target, anchor = null) {
|
||||
if (!this.e) {
|
||||
if (this.is_svg)
|
||||
this.e = svg_element(target.nodeName);
|
||||
else
|
||||
this.e = element(target.nodeName);
|
||||
this.t = target;
|
||||
this.c(html);
|
||||
}
|
||||
this.i(anchor);
|
||||
}
|
||||
h(html) {
|
||||
this.e.innerHTML = html;
|
||||
this.n = Array.from(this.e.childNodes);
|
||||
}
|
||||
i(anchor) {
|
||||
for (let i = 0; i < this.n.length; i += 1) {
|
||||
insert(this.t, this.n[i], anchor);
|
||||
}
|
||||
}
|
||||
p(html) {
|
||||
this.d();
|
||||
this.h(html);
|
||||
this.i(this.a);
|
||||
}
|
||||
d() {
|
||||
this.n.forEach(detach);
|
||||
}
|
||||
}
|
||||
function attribute_to_object(attributes) {
|
||||
const result = {};
|
||||
for (const attribute of attributes) {
|
||||
result[attribute.name] = attribute.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let current_component;
|
||||
function set_current_component(component) {
|
||||
current_component = component;
|
||||
}
|
||||
function get_current_component() {
|
||||
if (!current_component)
|
||||
throw new Error('Function called outside component initialization');
|
||||
return current_component;
|
||||
}
|
||||
/**
|
||||
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
|
||||
* It must be called during the component's initialisation (but doesn't need to live *inside* the component;
|
||||
* it can be called from an external module).
|
||||
*
|
||||
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-onmount
|
||||
*/
|
||||
function onMount(fn) {
|
||||
get_current_component().$$.on_mount.push(fn);
|
||||
}
|
||||
/**
|
||||
* Schedules a callback to run immediately after the component has been updated.
|
||||
*
|
||||
* The first time the callback runs will be after the initial `onMount`
|
||||
*/
|
||||
function afterUpdate(fn) {
|
||||
get_current_component().$$.after_update.push(fn);
|
||||
}
|
||||
/**
|
||||
* Associates an arbitrary `context` object with the current component and the specified `key`
|
||||
* and returns that object. The context is then available to children of the component
|
||||
* (including slotted content) with `getContext`.
|
||||
*
|
||||
* Like lifecycle functions, this must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-setcontext
|
||||
*/
|
||||
function setContext(key, context) {
|
||||
get_current_component().$$.context.set(key, context);
|
||||
return context;
|
||||
}
|
||||
/**
|
||||
* Retrieves the context that belongs to the closest parent component with the specified `key`.
|
||||
* Must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-getcontext
|
||||
*/
|
||||
function getContext(key) {
|
||||
return get_current_component().$$.context.get(key);
|
||||
}
|
||||
|
||||
const dirty_components = [];
|
||||
const binding_callbacks = [];
|
||||
const render_callbacks = [];
|
||||
const flush_callbacks = [];
|
||||
const resolved_promise = Promise.resolve();
|
||||
let update_scheduled = false;
|
||||
function schedule_update() {
|
||||
if (!update_scheduled) {
|
||||
update_scheduled = true;
|
||||
resolved_promise.then(flush);
|
||||
}
|
||||
}
|
||||
function add_render_callback(fn) {
|
||||
render_callbacks.push(fn);
|
||||
}
|
||||
// flush() calls callbacks in this order:
|
||||
// 1. All beforeUpdate callbacks, in order: parents before children
|
||||
// 2. All bind:this callbacks, in reverse order: children before parents.
|
||||
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
|
||||
// for afterUpdates called during the initial onMount, which are called in
|
||||
// reverse order: children before parents.
|
||||
// Since callbacks might update component values, which could trigger another
|
||||
// call to flush(), the following steps guard against this:
|
||||
// 1. During beforeUpdate, any updated components will be added to the
|
||||
// dirty_components array and will cause a reentrant call to flush(). Because
|
||||
// the flush index is kept outside the function, the reentrant call will pick
|
||||
// up where the earlier call left off and go through all dirty components. The
|
||||
// current_component value is saved and restored so that the reentrant call will
|
||||
// not interfere with the "parent" flush() call.
|
||||
// 2. bind:this callbacks cannot trigger new flush() calls.
|
||||
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
|
||||
// callback called a second time; the seen_callbacks set, outside the flush()
|
||||
// function, guarantees this behavior.
|
||||
const seen_callbacks = new Set();
|
||||
let flushidx = 0; // Do *not* move this inside the flush() function
|
||||
function flush() {
|
||||
const saved_component = current_component;
|
||||
do {
|
||||
// first, call beforeUpdate functions
|
||||
// and update components
|
||||
while (flushidx < dirty_components.length) {
|
||||
const component = dirty_components[flushidx];
|
||||
flushidx++;
|
||||
set_current_component(component);
|
||||
update(component.$$);
|
||||
}
|
||||
set_current_component(null);
|
||||
dirty_components.length = 0;
|
||||
flushidx = 0;
|
||||
while (binding_callbacks.length)
|
||||
binding_callbacks.pop()();
|
||||
// then, once components are updated, call
|
||||
// afterUpdate functions. This may cause
|
||||
// subsequent updates...
|
||||
for (let i = 0; i < render_callbacks.length; i += 1) {
|
||||
const callback = render_callbacks[i];
|
||||
if (!seen_callbacks.has(callback)) {
|
||||
// ...so guard against infinite loops
|
||||
seen_callbacks.add(callback);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
render_callbacks.length = 0;
|
||||
} while (dirty_components.length);
|
||||
while (flush_callbacks.length) {
|
||||
flush_callbacks.pop()();
|
||||
}
|
||||
update_scheduled = false;
|
||||
seen_callbacks.clear();
|
||||
set_current_component(saved_component);
|
||||
}
|
||||
function update($$) {
|
||||
if ($$.fragment !== null) {
|
||||
$$.update();
|
||||
run_all($$.before_update);
|
||||
const dirty = $$.dirty;
|
||||
$$.dirty = [-1];
|
||||
$$.fragment && $$.fragment.p($$.ctx, dirty);
|
||||
$$.after_update.forEach(add_render_callback);
|
||||
}
|
||||
}
|
||||
const outroing = new Set();
|
||||
function transition_in(block, local) {
|
||||
if (block && block.i) {
|
||||
outroing.delete(block);
|
||||
block.i(local);
|
||||
}
|
||||
}
|
||||
|
||||
const globals = (typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof globalThis !== 'undefined'
|
||||
? globalThis
|
||||
: global);
|
||||
function mount_component(component, target, anchor, customElement) {
|
||||
const { fragment, after_update } = component.$$;
|
||||
fragment && fragment.m(target, anchor);
|
||||
if (!customElement) {
|
||||
// onMount happens before the initial afterUpdate
|
||||
add_render_callback(() => {
|
||||
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
||||
// if the component was destroyed immediately
|
||||
// it will update the `$$.on_destroy` reference to `null`.
|
||||
// the destructured on_destroy may still reference to the old array
|
||||
if (component.$$.on_destroy) {
|
||||
component.$$.on_destroy.push(...new_on_destroy);
|
||||
}
|
||||
else {
|
||||
// Edge case - component was destroyed immediately,
|
||||
// most likely as a result of a binding initialising
|
||||
run_all(new_on_destroy);
|
||||
}
|
||||
component.$$.on_mount = [];
|
||||
});
|
||||
}
|
||||
after_update.forEach(add_render_callback);
|
||||
}
|
||||
function destroy_component(component, detaching) {
|
||||
const $$ = component.$$;
|
||||
if ($$.fragment !== null) {
|
||||
run_all($$.on_destroy);
|
||||
$$.fragment && $$.fragment.d(detaching);
|
||||
// TODO null out other refs, including component.$$ (but need to
|
||||
// preserve final state?)
|
||||
$$.on_destroy = $$.fragment = null;
|
||||
$$.ctx = [];
|
||||
}
|
||||
}
|
||||
function make_dirty(component, i) {
|
||||
if (component.$$.dirty[0] === -1) {
|
||||
dirty_components.push(component);
|
||||
schedule_update();
|
||||
component.$$.dirty.fill(0);
|
||||
}
|
||||
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
|
||||
}
|
||||
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
|
||||
const parent_component = current_component;
|
||||
set_current_component(component);
|
||||
const $$ = component.$$ = {
|
||||
fragment: null,
|
||||
ctx: [],
|
||||
// state
|
||||
props,
|
||||
update: noop,
|
||||
not_equal,
|
||||
bound: blank_object(),
|
||||
// lifecycle
|
||||
on_mount: [],
|
||||
on_destroy: [],
|
||||
on_disconnect: [],
|
||||
before_update: [],
|
||||
after_update: [],
|
||||
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
||||
// everything else
|
||||
callbacks: blank_object(),
|
||||
dirty,
|
||||
skip_bound: false,
|
||||
root: options.target || parent_component.$$.root
|
||||
};
|
||||
append_styles && append_styles($$.root);
|
||||
let ready = false;
|
||||
$$.ctx = instance
|
||||
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
||||
const value = rest.length ? rest[0] : ret;
|
||||
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
|
||||
if (!$$.skip_bound && $$.bound[i])
|
||||
$$.bound[i](value);
|
||||
if (ready)
|
||||
make_dirty(component, i);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
: [];
|
||||
$$.update();
|
||||
ready = true;
|
||||
run_all($$.before_update);
|
||||
// `false` as a special case of no DOM component
|
||||
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
|
||||
if (options.target) {
|
||||
if (options.hydrate) {
|
||||
const nodes = children(options.target);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.l(nodes);
|
||||
nodes.forEach(detach);
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.c();
|
||||
}
|
||||
if (options.intro)
|
||||
transition_in(component.$$.fragment);
|
||||
mount_component(component, options.target, options.anchor, options.customElement);
|
||||
flush();
|
||||
}
|
||||
set_current_component(parent_component);
|
||||
}
|
||||
let SvelteElement;
|
||||
if (typeof HTMLElement === 'function') {
|
||||
SvelteElement = class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
connectedCallback() {
|
||||
const { on_mount } = this.$$;
|
||||
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
|
||||
// @ts-ignore todo: improve typings
|
||||
for (const key in this.$$.slotted) {
|
||||
// @ts-ignore todo: improve typings
|
||||
this.appendChild(this.$$.slotted[key]);
|
||||
}
|
||||
}
|
||||
attributeChangedCallback(attr, _oldValue, newValue) {
|
||||
this[attr] = newValue;
|
||||
}
|
||||
disconnectedCallback() {
|
||||
run_all(this.$$.on_disconnect);
|
||||
}
|
||||
$destroy() {
|
||||
destroy_component(this, 1);
|
||||
this.$destroy = noop;
|
||||
}
|
||||
$on(type, callback) {
|
||||
// TODO should this delegate to addEventListener?
|
||||
if (!is_function(callback)) {
|
||||
return noop;
|
||||
}
|
||||
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
|
||||
callbacks.push(callback);
|
||||
return () => {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index !== -1)
|
||||
callbacks.splice(index, 1);
|
||||
};
|
||||
}
|
||||
$set($$props) {
|
||||
if (this.$$set && !is_empty($$props)) {
|
||||
this.$$.skip_bound = true;
|
||||
this.$$set($$props);
|
||||
this.$$.skip_bound = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function dispatch_dev(type, detail) {
|
||||
document.dispatchEvent(custom_event(type, Object.assign({ version: '3.52.0' }, detail), { bubbles: true }));
|
||||
}
|
||||
function append_dev(target, node) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node });
|
||||
append(target, node);
|
||||
}
|
||||
function insert_dev(target, node, anchor) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node, anchor });
|
||||
insert(target, node, anchor);
|
||||
}
|
||||
function detach_dev(node) {
|
||||
dispatch_dev('SvelteDOMRemove', { node });
|
||||
detach(node);
|
||||
}
|
||||
function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation) {
|
||||
const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
|
||||
if (has_prevent_default)
|
||||
modifiers.push('preventDefault');
|
||||
if (has_stop_propagation)
|
||||
modifiers.push('stopPropagation');
|
||||
dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
|
||||
const dispose = listen(node, event, handler, options);
|
||||
return () => {
|
||||
dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
|
||||
dispose();
|
||||
};
|
||||
}
|
||||
function attr_dev(node, attribute, value) {
|
||||
attr(node, attribute, value);
|
||||
if (value == null)
|
||||
dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
|
||||
else
|
||||
dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
|
||||
}
|
||||
function prop_dev(node, property, value) {
|
||||
node[property] = value;
|
||||
dispatch_dev('SvelteDOMSetProperty', { node, property, value });
|
||||
}
|
||||
function set_data_dev(text, data) {
|
||||
data = '' + data;
|
||||
if (text.wholeText === data)
|
||||
return;
|
||||
dispatch_dev('SvelteDOMSetData', { node: text, data });
|
||||
text.data = data;
|
||||
}
|
||||
function validate_each_argument(arg) {
|
||||
if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
|
||||
let msg = '{#each} only iterates over array-like objects.';
|
||||
if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
|
||||
msg += ' You can use a spread to convert this iterable into an array.';
|
||||
}
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
function validate_slots(name, slot, keys) {
|
||||
for (const slot_key of Object.keys(slot)) {
|
||||
if (!~keys.indexOf(slot_key)) {
|
||||
console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { validate_each_argument as A, text as B, set_data_dev as C, destroy_each as D, prop_dev as E, set_style as F, svg_element as G, is_function as H, HtmlTag as I, afterUpdate as J, SvelteElement as S, attribute_to_object as a, insert_dev as b, setContext as c, dispatch_dev as d, globals as e, element as f, getContext as g, space as h, init as i, add_location as j, attr_dev as k, append_dev as l, listen_dev as m, noop as n, onMount as o, detach_dev as p, binding_callbacks as q, run_all as r, safe_not_equal as s, flush as t, src_url_equal as u, validate_slots as v, validate_store as w, component_subscribe as x, empty as y, set_custom_element_data as z };
|
|
@ -0,0 +1 @@
|
|||
import{n,s as t}from"./index-db20528a.js";const e=[];function s(s,o=n){let i;const c=new Set;function f(n){if(t(s,n)&&(s=n,i)){const n=!e.length;for(const n of c)n[1](),e.push(n,s);if(n){for(let n=0;n<e.length;n+=2)e[n][0](e[n+1]);e.length=0}}}return{set:f,update:function(n){f(n(s))},subscribe:function(t,e=n){const r=[t,e];return c.add(r),1===c.size&&(i=o(f)||n),t(s),()=>{c.delete(r),0===c.size&&(i(),i=null)}}}}export{s as w};
|
|
@ -0,0 +1,524 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
function noop() { }
|
||||
function add_location(element, file, line, column, char) {
|
||||
element.__svelte_meta = {
|
||||
loc: { file, line, column, char }
|
||||
};
|
||||
}
|
||||
function run(fn) {
|
||||
return fn();
|
||||
}
|
||||
function blank_object() {
|
||||
return Object.create(null);
|
||||
}
|
||||
function run_all(fns) {
|
||||
fns.forEach(run);
|
||||
}
|
||||
function is_function(thing) {
|
||||
return typeof thing === 'function';
|
||||
}
|
||||
function safe_not_equal(a, b) {
|
||||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
|
||||
}
|
||||
let src_url_equal_anchor;
|
||||
function src_url_equal(element_src, url) {
|
||||
if (!src_url_equal_anchor) {
|
||||
src_url_equal_anchor = document.createElement('a');
|
||||
}
|
||||
src_url_equal_anchor.href = url;
|
||||
return element_src === src_url_equal_anchor.href;
|
||||
}
|
||||
function is_empty(obj) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
function validate_store(store, name) {
|
||||
if (store != null && typeof store.subscribe !== 'function') {
|
||||
throw new Error(`'${name}' is not a store with a 'subscribe' method`);
|
||||
}
|
||||
}
|
||||
function subscribe(store, ...callbacks) {
|
||||
if (store == null) {
|
||||
return noop;
|
||||
}
|
||||
const unsub = store.subscribe(...callbacks);
|
||||
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
|
||||
}
|
||||
function component_subscribe(component, store, callback) {
|
||||
component.$$.on_destroy.push(subscribe(store, callback));
|
||||
}
|
||||
function append(target, node) {
|
||||
target.appendChild(node);
|
||||
}
|
||||
function insert(target, node, anchor) {
|
||||
target.insertBefore(node, anchor || null);
|
||||
}
|
||||
function detach(node) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
function destroy_each(iterations, detaching) {
|
||||
for (let i = 0; i < iterations.length; i += 1) {
|
||||
if (iterations[i])
|
||||
iterations[i].d(detaching);
|
||||
}
|
||||
}
|
||||
function element(name) {
|
||||
return document.createElement(name);
|
||||
}
|
||||
function svg_element(name) {
|
||||
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||
}
|
||||
function text(data) {
|
||||
return document.createTextNode(data);
|
||||
}
|
||||
function space() {
|
||||
return text(' ');
|
||||
}
|
||||
function empty() {
|
||||
return text('');
|
||||
}
|
||||
function listen(node, event, handler, options) {
|
||||
node.addEventListener(event, handler, options);
|
||||
return () => node.removeEventListener(event, handler, options);
|
||||
}
|
||||
function attr(node, attribute, value) {
|
||||
if (value == null)
|
||||
node.removeAttribute(attribute);
|
||||
else if (node.getAttribute(attribute) !== value)
|
||||
node.setAttribute(attribute, value);
|
||||
}
|
||||
function set_custom_element_data(node, prop, value) {
|
||||
if (prop in node) {
|
||||
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
|
||||
}
|
||||
else {
|
||||
attr(node, prop, value);
|
||||
}
|
||||
}
|
||||
function children(element) {
|
||||
return Array.from(element.childNodes);
|
||||
}
|
||||
function set_input_value(input, value) {
|
||||
input.value = value == null ? '' : value;
|
||||
}
|
||||
function set_style(node, key, value, important) {
|
||||
if (value === null) {
|
||||
node.style.removeProperty(key);
|
||||
}
|
||||
else {
|
||||
node.style.setProperty(key, value, important ? 'important' : '');
|
||||
}
|
||||
}
|
||||
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
|
||||
const e = document.createEvent('CustomEvent');
|
||||
e.initCustomEvent(type, bubbles, cancelable, detail);
|
||||
return e;
|
||||
}
|
||||
class HtmlTag {
|
||||
constructor(is_svg = false) {
|
||||
this.is_svg = false;
|
||||
this.is_svg = is_svg;
|
||||
this.e = this.n = null;
|
||||
}
|
||||
c(html) {
|
||||
this.h(html);
|
||||
}
|
||||
m(html, target, anchor = null) {
|
||||
if (!this.e) {
|
||||
if (this.is_svg)
|
||||
this.e = svg_element(target.nodeName);
|
||||
else
|
||||
this.e = element(target.nodeName);
|
||||
this.t = target;
|
||||
this.c(html);
|
||||
}
|
||||
this.i(anchor);
|
||||
}
|
||||
h(html) {
|
||||
this.e.innerHTML = html;
|
||||
this.n = Array.from(this.e.childNodes);
|
||||
}
|
||||
i(anchor) {
|
||||
for (let i = 0; i < this.n.length; i += 1) {
|
||||
insert(this.t, this.n[i], anchor);
|
||||
}
|
||||
}
|
||||
p(html) {
|
||||
this.d();
|
||||
this.h(html);
|
||||
this.i(this.a);
|
||||
}
|
||||
d() {
|
||||
this.n.forEach(detach);
|
||||
}
|
||||
}
|
||||
function attribute_to_object(attributes) {
|
||||
const result = {};
|
||||
for (const attribute of attributes) {
|
||||
result[attribute.name] = attribute.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let current_component;
|
||||
function set_current_component(component) {
|
||||
current_component = component;
|
||||
}
|
||||
function get_current_component() {
|
||||
if (!current_component)
|
||||
throw new Error('Function called outside component initialization');
|
||||
return current_component;
|
||||
}
|
||||
/**
|
||||
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
|
||||
* It must be called during the component's initialisation (but doesn't need to live *inside* the component;
|
||||
* it can be called from an external module).
|
||||
*
|
||||
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-onmount
|
||||
*/
|
||||
function onMount(fn) {
|
||||
get_current_component().$$.on_mount.push(fn);
|
||||
}
|
||||
/**
|
||||
* Schedules a callback to run immediately after the component has been updated.
|
||||
*
|
||||
* The first time the callback runs will be after the initial `onMount`
|
||||
*/
|
||||
function afterUpdate(fn) {
|
||||
get_current_component().$$.after_update.push(fn);
|
||||
}
|
||||
/**
|
||||
* Associates an arbitrary `context` object with the current component and the specified `key`
|
||||
* and returns that object. The context is then available to children of the component
|
||||
* (including slotted content) with `getContext`.
|
||||
*
|
||||
* Like lifecycle functions, this must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-setcontext
|
||||
*/
|
||||
function setContext(key, context) {
|
||||
get_current_component().$$.context.set(key, context);
|
||||
return context;
|
||||
}
|
||||
/**
|
||||
* Retrieves the context that belongs to the closest parent component with the specified `key`.
|
||||
* Must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-getcontext
|
||||
*/
|
||||
function getContext(key) {
|
||||
return get_current_component().$$.context.get(key);
|
||||
}
|
||||
|
||||
const dirty_components = [];
|
||||
const binding_callbacks = [];
|
||||
const render_callbacks = [];
|
||||
const flush_callbacks = [];
|
||||
const resolved_promise = Promise.resolve();
|
||||
let update_scheduled = false;
|
||||
function schedule_update() {
|
||||
if (!update_scheduled) {
|
||||
update_scheduled = true;
|
||||
resolved_promise.then(flush);
|
||||
}
|
||||
}
|
||||
function add_render_callback(fn) {
|
||||
render_callbacks.push(fn);
|
||||
}
|
||||
// flush() calls callbacks in this order:
|
||||
// 1. All beforeUpdate callbacks, in order: parents before children
|
||||
// 2. All bind:this callbacks, in reverse order: children before parents.
|
||||
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
|
||||
// for afterUpdates called during the initial onMount, which are called in
|
||||
// reverse order: children before parents.
|
||||
// Since callbacks might update component values, which could trigger another
|
||||
// call to flush(), the following steps guard against this:
|
||||
// 1. During beforeUpdate, any updated components will be added to the
|
||||
// dirty_components array and will cause a reentrant call to flush(). Because
|
||||
// the flush index is kept outside the function, the reentrant call will pick
|
||||
// up where the earlier call left off and go through all dirty components. The
|
||||
// current_component value is saved and restored so that the reentrant call will
|
||||
// not interfere with the "parent" flush() call.
|
||||
// 2. bind:this callbacks cannot trigger new flush() calls.
|
||||
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
|
||||
// callback called a second time; the seen_callbacks set, outside the flush()
|
||||
// function, guarantees this behavior.
|
||||
const seen_callbacks = new Set();
|
||||
let flushidx = 0; // Do *not* move this inside the flush() function
|
||||
function flush() {
|
||||
const saved_component = current_component;
|
||||
do {
|
||||
// first, call beforeUpdate functions
|
||||
// and update components
|
||||
while (flushidx < dirty_components.length) {
|
||||
const component = dirty_components[flushidx];
|
||||
flushidx++;
|
||||
set_current_component(component);
|
||||
update(component.$$);
|
||||
}
|
||||
set_current_component(null);
|
||||
dirty_components.length = 0;
|
||||
flushidx = 0;
|
||||
while (binding_callbacks.length)
|
||||
binding_callbacks.pop()();
|
||||
// then, once components are updated, call
|
||||
// afterUpdate functions. This may cause
|
||||
// subsequent updates...
|
||||
for (let i = 0; i < render_callbacks.length; i += 1) {
|
||||
const callback = render_callbacks[i];
|
||||
if (!seen_callbacks.has(callback)) {
|
||||
// ...so guard against infinite loops
|
||||
seen_callbacks.add(callback);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
render_callbacks.length = 0;
|
||||
} while (dirty_components.length);
|
||||
while (flush_callbacks.length) {
|
||||
flush_callbacks.pop()();
|
||||
}
|
||||
update_scheduled = false;
|
||||
seen_callbacks.clear();
|
||||
set_current_component(saved_component);
|
||||
}
|
||||
function update($$) {
|
||||
if ($$.fragment !== null) {
|
||||
$$.update();
|
||||
run_all($$.before_update);
|
||||
const dirty = $$.dirty;
|
||||
$$.dirty = [-1];
|
||||
$$.fragment && $$.fragment.p($$.ctx, dirty);
|
||||
$$.after_update.forEach(add_render_callback);
|
||||
}
|
||||
}
|
||||
const outroing = new Set();
|
||||
function transition_in(block, local) {
|
||||
if (block && block.i) {
|
||||
outroing.delete(block);
|
||||
block.i(local);
|
||||
}
|
||||
}
|
||||
|
||||
const globals = (typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof globalThis !== 'undefined'
|
||||
? globalThis
|
||||
: global);
|
||||
function mount_component(component, target, anchor, customElement) {
|
||||
const { fragment, after_update } = component.$$;
|
||||
fragment && fragment.m(target, anchor);
|
||||
if (!customElement) {
|
||||
// onMount happens before the initial afterUpdate
|
||||
add_render_callback(() => {
|
||||
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
||||
// if the component was destroyed immediately
|
||||
// it will update the `$$.on_destroy` reference to `null`.
|
||||
// the destructured on_destroy may still reference to the old array
|
||||
if (component.$$.on_destroy) {
|
||||
component.$$.on_destroy.push(...new_on_destroy);
|
||||
}
|
||||
else {
|
||||
// Edge case - component was destroyed immediately,
|
||||
// most likely as a result of a binding initialising
|
||||
run_all(new_on_destroy);
|
||||
}
|
||||
component.$$.on_mount = [];
|
||||
});
|
||||
}
|
||||
after_update.forEach(add_render_callback);
|
||||
}
|
||||
function destroy_component(component, detaching) {
|
||||
const $$ = component.$$;
|
||||
if ($$.fragment !== null) {
|
||||
run_all($$.on_destroy);
|
||||
$$.fragment && $$.fragment.d(detaching);
|
||||
// TODO null out other refs, including component.$$ (but need to
|
||||
// preserve final state?)
|
||||
$$.on_destroy = $$.fragment = null;
|
||||
$$.ctx = [];
|
||||
}
|
||||
}
|
||||
function make_dirty(component, i) {
|
||||
if (component.$$.dirty[0] === -1) {
|
||||
dirty_components.push(component);
|
||||
schedule_update();
|
||||
component.$$.dirty.fill(0);
|
||||
}
|
||||
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
|
||||
}
|
||||
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
|
||||
const parent_component = current_component;
|
||||
set_current_component(component);
|
||||
const $$ = component.$$ = {
|
||||
fragment: null,
|
||||
ctx: [],
|
||||
// state
|
||||
props,
|
||||
update: noop,
|
||||
not_equal,
|
||||
bound: blank_object(),
|
||||
// lifecycle
|
||||
on_mount: [],
|
||||
on_destroy: [],
|
||||
on_disconnect: [],
|
||||
before_update: [],
|
||||
after_update: [],
|
||||
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
||||
// everything else
|
||||
callbacks: blank_object(),
|
||||
dirty,
|
||||
skip_bound: false,
|
||||
root: options.target || parent_component.$$.root
|
||||
};
|
||||
append_styles && append_styles($$.root);
|
||||
let ready = false;
|
||||
$$.ctx = instance
|
||||
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
||||
const value = rest.length ? rest[0] : ret;
|
||||
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
|
||||
if (!$$.skip_bound && $$.bound[i])
|
||||
$$.bound[i](value);
|
||||
if (ready)
|
||||
make_dirty(component, i);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
: [];
|
||||
$$.update();
|
||||
ready = true;
|
||||
run_all($$.before_update);
|
||||
// `false` as a special case of no DOM component
|
||||
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
|
||||
if (options.target) {
|
||||
if (options.hydrate) {
|
||||
const nodes = children(options.target);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.l(nodes);
|
||||
nodes.forEach(detach);
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.c();
|
||||
}
|
||||
if (options.intro)
|
||||
transition_in(component.$$.fragment);
|
||||
mount_component(component, options.target, options.anchor, options.customElement);
|
||||
flush();
|
||||
}
|
||||
set_current_component(parent_component);
|
||||
}
|
||||
let SvelteElement;
|
||||
if (typeof HTMLElement === 'function') {
|
||||
SvelteElement = class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
connectedCallback() {
|
||||
const { on_mount } = this.$$;
|
||||
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
|
||||
// @ts-ignore todo: improve typings
|
||||
for (const key in this.$$.slotted) {
|
||||
// @ts-ignore todo: improve typings
|
||||
this.appendChild(this.$$.slotted[key]);
|
||||
}
|
||||
}
|
||||
attributeChangedCallback(attr, _oldValue, newValue) {
|
||||
this[attr] = newValue;
|
||||
}
|
||||
disconnectedCallback() {
|
||||
run_all(this.$$.on_disconnect);
|
||||
}
|
||||
$destroy() {
|
||||
destroy_component(this, 1);
|
||||
this.$destroy = noop;
|
||||
}
|
||||
$on(type, callback) {
|
||||
// TODO should this delegate to addEventListener?
|
||||
if (!is_function(callback)) {
|
||||
return noop;
|
||||
}
|
||||
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
|
||||
callbacks.push(callback);
|
||||
return () => {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index !== -1)
|
||||
callbacks.splice(index, 1);
|
||||
};
|
||||
}
|
||||
$set($$props) {
|
||||
if (this.$$set && !is_empty($$props)) {
|
||||
this.$$.skip_bound = true;
|
||||
this.$$set($$props);
|
||||
this.$$.skip_bound = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function dispatch_dev(type, detail) {
|
||||
document.dispatchEvent(custom_event(type, Object.assign({ version: '3.52.0' }, detail), { bubbles: true }));
|
||||
}
|
||||
function append_dev(target, node) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node });
|
||||
append(target, node);
|
||||
}
|
||||
function insert_dev(target, node, anchor) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node, anchor });
|
||||
insert(target, node, anchor);
|
||||
}
|
||||
function detach_dev(node) {
|
||||
dispatch_dev('SvelteDOMRemove', { node });
|
||||
detach(node);
|
||||
}
|
||||
function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation) {
|
||||
const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
|
||||
if (has_prevent_default)
|
||||
modifiers.push('preventDefault');
|
||||
if (has_stop_propagation)
|
||||
modifiers.push('stopPropagation');
|
||||
dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
|
||||
const dispose = listen(node, event, handler, options);
|
||||
return () => {
|
||||
dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
|
||||
dispose();
|
||||
};
|
||||
}
|
||||
function attr_dev(node, attribute, value) {
|
||||
attr(node, attribute, value);
|
||||
if (value == null)
|
||||
dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
|
||||
else
|
||||
dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
|
||||
}
|
||||
function prop_dev(node, property, value) {
|
||||
node[property] = value;
|
||||
dispatch_dev('SvelteDOMSetProperty', { node, property, value });
|
||||
}
|
||||
function set_data_dev(text, data) {
|
||||
data = '' + data;
|
||||
if (text.wholeText === data)
|
||||
return;
|
||||
dispatch_dev('SvelteDOMSetData', { node: text, data });
|
||||
text.data = data;
|
||||
}
|
||||
function validate_each_argument(arg) {
|
||||
if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
|
||||
let msg = '{#each} only iterates over array-like objects.';
|
||||
if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
|
||||
msg += ' You can use a spread to convert this iterable into an array.';
|
||||
}
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
function validate_slots(name, slot, keys) {
|
||||
for (const slot_key of Object.keys(slot)) {
|
||||
if (!~keys.indexOf(slot_key)) {
|
||||
console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { validate_each_argument as A, text as B, set_data_dev as C, destroy_each as D, prop_dev as E, set_style as F, svg_element as G, is_function as H, HtmlTag as I, afterUpdate as J, set_input_value as K, SvelteElement as S, attribute_to_object as a, insert_dev as b, setContext as c, dispatch_dev as d, globals as e, element as f, getContext as g, space as h, init as i, add_location as j, attr_dev as k, append_dev as l, listen_dev as m, noop as n, onMount as o, detach_dev as p, binding_callbacks as q, run_all as r, safe_not_equal as s, flush as t, src_url_equal as u, validate_slots as v, validate_store as w, component_subscribe as x, empty as y, set_custom_element_data as z };
|
|
@ -0,0 +1 @@
|
|||
function t(){}function n(t){return t()}function e(){return Object.create(null)}function o(t){t.forEach(n)}function s(t){return"function"==typeof t}function r(t,n){return t!=t?n==n:t!==n||t&&"object"==typeof t||"function"==typeof t}let i,c;function u(t,n){return i||(i=document.createElement("a")),i.href=n,t===i.href}function a(n,e,o){n.$$.on_destroy.push(function(n,...e){if(null==n)return t;const o=n.subscribe(...e);return o.unsubscribe?()=>o.unsubscribe():o}(e,o))}function f(t,n){t.appendChild(n)}function l(t,n,e){t.insertBefore(n,e||null)}function h(t){t.parentNode.removeChild(t)}function d(t,n){for(let e=0;e<t.length;e+=1)t[e]&&t[e].d(n)}function $(t){return document.createElement(t)}function p(t){return document.createTextNode(t)}function m(){return p(" ")}function g(){return p("")}function b(t,n,e,o){return t.addEventListener(n,e,o),()=>t.removeEventListener(n,e,o)}function y(t,n,e){null==e?t.removeAttribute(n):t.getAttribute(n)!==e&&t.setAttribute(n,e)}function _(t,n,e){n in t?t[n]="boolean"==typeof t[n]&&""===e||e:y(t,n,e)}function x(t,n){n=""+n,t.wholeText!==n&&(t.data=n)}function v(t,n){t.value=null==n?"":n}function E(t,n,e,o){null===e?t.style.removeProperty(n):t.style.setProperty(n,e,o?"important":"")}class w{constructor(t=!1){this.is_svg=!1,this.is_svg=t,this.e=this.n=null}c(t){this.h(t)}m(t,n,e=null){var o;this.e||(this.is_svg?this.e=(o=n.nodeName,document.createElementNS("http://www.w3.org/2000/svg",o)):this.e=$(n.nodeName),this.t=n,this.c(t)),this.i(e)}h(t){this.e.innerHTML=t,this.n=Array.from(this.e.childNodes)}i(t){for(let n=0;n<this.n.length;n+=1)l(this.t,this.n[n],t)}p(t){this.d(),this.h(t),this.i(this.a)}d(){this.n.forEach(h)}}function k(t){const n={};for(const e of t)n[e.name]=e.value;return n}function C(t){c=t}function N(){if(!c)throw new Error("Function called outside component initialization");return c}function A(t){N().$$.on_mount.push(t)}function L(t,n){return N().$$.context.set(t,n),n}function S(t){return N().$$.context.get(t)}const T=[],j=[],H=[],M=[],O=Promise.resolve();let P=!1;function q(t){H.push(t)}const z=new Set;let B=0;function F(){const t=c;do{for(;B<T.length;){const t=T[B];B++,C(t),D(t.$$)}for(C(null),T.length=0,B=0;j.length;)j.pop()();for(let t=0;t<H.length;t+=1){const n=H[t];z.has(n)||(z.add(n),n())}H.length=0}while(T.length);for(;M.length;)M.pop()();P=!1,z.clear(),C(t)}function D(t){if(null!==t.fragment){t.update(),o(t.before_update);const n=t.dirty;t.dirty=[-1],t.fragment&&t.fragment.p(t.ctx,n),t.after_update.forEach(q)}}const G=new Set;function I(t,n){-1===t.$$.dirty[0]&&(T.push(t),P||(P=!0,O.then(F)),t.$$.dirty.fill(0)),t.$$.dirty[n/31|0]|=1<<n%31}function J(r,i,u,a,f,l,d,$=[-1]){const p=c;C(r);const m=r.$$={fragment:null,ctx:[],props:l,update:t,not_equal:f,bound:e(),on_mount:[],on_destroy:[],on_disconnect:[],before_update:[],after_update:[],context:new Map(i.context||(p?p.$$.context:[])),callbacks:e(),dirty:$,skip_bound:!1,root:i.target||p.$$.root};d&&d(m.root);let g=!1;if(m.ctx=u?u(r,i.props||{},((t,n,...e)=>{const o=e.length?e[0]:n;return m.ctx&&f(m.ctx[t],m.ctx[t]=o)&&(!m.skip_bound&&m.bound[t]&&m.bound[t](o),g&&I(r,t)),n})):[],m.update(),g=!0,o(m.before_update),m.fragment=!!a&&a(m.ctx),i.target){if(i.hydrate){const t=function(t){return Array.from(t.childNodes)}(i.target);m.fragment&&m.fragment.l(t),t.forEach(h)}else m.fragment&&m.fragment.c();i.intro&&((b=r.$$.fragment)&&b.i&&(G.delete(b),b.i(y))),function(t,e,r,i){const{fragment:c,after_update:u}=t.$$;c&&c.m(e,r),i||q((()=>{const e=t.$$.on_mount.map(n).filter(s);t.$$.on_destroy?t.$$.on_destroy.push(...e):o(e),t.$$.on_mount=[]})),u.forEach(q)}(r,i.target,i.anchor,i.customElement),F()}var b,y;C(p)}let K;"function"==typeof HTMLElement&&(K=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){const{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(n).filter(s);for(const t in this.$$.slotted)this.appendChild(this.$$.slotted[t])}attributeChangedCallback(t,n,e){this[t]=e}disconnectedCallback(){o(this.$$.on_disconnect)}$destroy(){!function(t,n){const e=t.$$;null!==e.fragment&&(o(e.on_destroy),e.fragment&&e.fragment.d(n),e.on_destroy=e.fragment=null,e.ctx=[])}(this,1),this.$destroy=t}$on(n,e){if(!s(e))return t;const o=this.$$.callbacks[n]||(this.$$.callbacks[n]=[]);return o.push(e),()=>{const t=o.indexOf(e);-1!==t&&o.splice(t,1)}}$set(t){var n;this.$$set&&(n=t,0!==Object.keys(n).length)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});export{v as A,w as H,K as S,k as a,l as b,m as c,y as d,$ as e,f,h as g,L as h,J as i,j,F as k,b as l,S as m,t as n,A as o,g as p,a as q,o as r,r as s,u as t,_ as u,p as v,x as w,d as x,E as y,s as z};
|
|
@ -0,0 +1,524 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
function noop() { }
|
||||
function add_location(element, file, line, column, char) {
|
||||
element.__svelte_meta = {
|
||||
loc: { file, line, column, char }
|
||||
};
|
||||
}
|
||||
function run(fn) {
|
||||
return fn();
|
||||
}
|
||||
function blank_object() {
|
||||
return Object.create(null);
|
||||
}
|
||||
function run_all(fns) {
|
||||
fns.forEach(run);
|
||||
}
|
||||
function is_function(thing) {
|
||||
return typeof thing === 'function';
|
||||
}
|
||||
function safe_not_equal(a, b) {
|
||||
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
|
||||
}
|
||||
let src_url_equal_anchor;
|
||||
function src_url_equal(element_src, url) {
|
||||
if (!src_url_equal_anchor) {
|
||||
src_url_equal_anchor = document.createElement('a');
|
||||
}
|
||||
src_url_equal_anchor.href = url;
|
||||
return element_src === src_url_equal_anchor.href;
|
||||
}
|
||||
function is_empty(obj) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
function validate_store(store, name) {
|
||||
if (store != null && typeof store.subscribe !== 'function') {
|
||||
throw new Error(`'${name}' is not a store with a 'subscribe' method`);
|
||||
}
|
||||
}
|
||||
function subscribe(store, ...callbacks) {
|
||||
if (store == null) {
|
||||
return noop;
|
||||
}
|
||||
const unsub = store.subscribe(...callbacks);
|
||||
return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
|
||||
}
|
||||
function component_subscribe(component, store, callback) {
|
||||
component.$$.on_destroy.push(subscribe(store, callback));
|
||||
}
|
||||
function append(target, node) {
|
||||
target.appendChild(node);
|
||||
}
|
||||
function insert(target, node, anchor) {
|
||||
target.insertBefore(node, anchor || null);
|
||||
}
|
||||
function detach(node) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
function destroy_each(iterations, detaching) {
|
||||
for (let i = 0; i < iterations.length; i += 1) {
|
||||
if (iterations[i])
|
||||
iterations[i].d(detaching);
|
||||
}
|
||||
}
|
||||
function element(name) {
|
||||
return document.createElement(name);
|
||||
}
|
||||
function svg_element(name) {
|
||||
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||
}
|
||||
function text(data) {
|
||||
return document.createTextNode(data);
|
||||
}
|
||||
function space() {
|
||||
return text(' ');
|
||||
}
|
||||
function empty() {
|
||||
return text('');
|
||||
}
|
||||
function listen(node, event, handler, options) {
|
||||
node.addEventListener(event, handler, options);
|
||||
return () => node.removeEventListener(event, handler, options);
|
||||
}
|
||||
function attr(node, attribute, value) {
|
||||
if (value == null)
|
||||
node.removeAttribute(attribute);
|
||||
else if (node.getAttribute(attribute) !== value)
|
||||
node.setAttribute(attribute, value);
|
||||
}
|
||||
function set_custom_element_data(node, prop, value) {
|
||||
if (prop in node) {
|
||||
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
|
||||
}
|
||||
else {
|
||||
attr(node, prop, value);
|
||||
}
|
||||
}
|
||||
function children(element) {
|
||||
return Array.from(element.childNodes);
|
||||
}
|
||||
function set_input_value(input, value) {
|
||||
input.value = value == null ? '' : value;
|
||||
}
|
||||
function set_style(node, key, value, important) {
|
||||
if (value === null) {
|
||||
node.style.removeProperty(key);
|
||||
}
|
||||
else {
|
||||
node.style.setProperty(key, value, important ? 'important' : '');
|
||||
}
|
||||
}
|
||||
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
|
||||
const e = document.createEvent('CustomEvent');
|
||||
e.initCustomEvent(type, bubbles, cancelable, detail);
|
||||
return e;
|
||||
}
|
||||
class HtmlTag {
|
||||
constructor(is_svg = false) {
|
||||
this.is_svg = false;
|
||||
this.is_svg = is_svg;
|
||||
this.e = this.n = null;
|
||||
}
|
||||
c(html) {
|
||||
this.h(html);
|
||||
}
|
||||
m(html, target, anchor = null) {
|
||||
if (!this.e) {
|
||||
if (this.is_svg)
|
||||
this.e = svg_element(target.nodeName);
|
||||
else
|
||||
this.e = element(target.nodeName);
|
||||
this.t = target;
|
||||
this.c(html);
|
||||
}
|
||||
this.i(anchor);
|
||||
}
|
||||
h(html) {
|
||||
this.e.innerHTML = html;
|
||||
this.n = Array.from(this.e.childNodes);
|
||||
}
|
||||
i(anchor) {
|
||||
for (let i = 0; i < this.n.length; i += 1) {
|
||||
insert(this.t, this.n[i], anchor);
|
||||
}
|
||||
}
|
||||
p(html) {
|
||||
this.d();
|
||||
this.h(html);
|
||||
this.i(this.a);
|
||||
}
|
||||
d() {
|
||||
this.n.forEach(detach);
|
||||
}
|
||||
}
|
||||
function attribute_to_object(attributes) {
|
||||
const result = {};
|
||||
for (const attribute of attributes) {
|
||||
result[attribute.name] = attribute.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let current_component;
|
||||
function set_current_component(component) {
|
||||
current_component = component;
|
||||
}
|
||||
function get_current_component() {
|
||||
if (!current_component)
|
||||
throw new Error('Function called outside component initialization');
|
||||
return current_component;
|
||||
}
|
||||
/**
|
||||
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
|
||||
* It must be called during the component's initialisation (but doesn't need to live *inside* the component;
|
||||
* it can be called from an external module).
|
||||
*
|
||||
* `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-onmount
|
||||
*/
|
||||
function onMount(fn) {
|
||||
get_current_component().$$.on_mount.push(fn);
|
||||
}
|
||||
/**
|
||||
* Schedules a callback to run immediately after the component has been updated.
|
||||
*
|
||||
* The first time the callback runs will be after the initial `onMount`
|
||||
*/
|
||||
function afterUpdate(fn) {
|
||||
get_current_component().$$.after_update.push(fn);
|
||||
}
|
||||
/**
|
||||
* Associates an arbitrary `context` object with the current component and the specified `key`
|
||||
* and returns that object. The context is then available to children of the component
|
||||
* (including slotted content) with `getContext`.
|
||||
*
|
||||
* Like lifecycle functions, this must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-setcontext
|
||||
*/
|
||||
function setContext(key, context) {
|
||||
get_current_component().$$.context.set(key, context);
|
||||
return context;
|
||||
}
|
||||
/**
|
||||
* Retrieves the context that belongs to the closest parent component with the specified `key`.
|
||||
* Must be called during component initialisation.
|
||||
*
|
||||
* https://svelte.dev/docs#run-time-svelte-getcontext
|
||||
*/
|
||||
function getContext(key) {
|
||||
return get_current_component().$$.context.get(key);
|
||||
}
|
||||
|
||||
const dirty_components = [];
|
||||
const binding_callbacks = [];
|
||||
const render_callbacks = [];
|
||||
const flush_callbacks = [];
|
||||
const resolved_promise = Promise.resolve();
|
||||
let update_scheduled = false;
|
||||
function schedule_update() {
|
||||
if (!update_scheduled) {
|
||||
update_scheduled = true;
|
||||
resolved_promise.then(flush);
|
||||
}
|
||||
}
|
||||
function add_render_callback(fn) {
|
||||
render_callbacks.push(fn);
|
||||
}
|
||||
// flush() calls callbacks in this order:
|
||||
// 1. All beforeUpdate callbacks, in order: parents before children
|
||||
// 2. All bind:this callbacks, in reverse order: children before parents.
|
||||
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
|
||||
// for afterUpdates called during the initial onMount, which are called in
|
||||
// reverse order: children before parents.
|
||||
// Since callbacks might update component values, which could trigger another
|
||||
// call to flush(), the following steps guard against this:
|
||||
// 1. During beforeUpdate, any updated components will be added to the
|
||||
// dirty_components array and will cause a reentrant call to flush(). Because
|
||||
// the flush index is kept outside the function, the reentrant call will pick
|
||||
// up where the earlier call left off and go through all dirty components. The
|
||||
// current_component value is saved and restored so that the reentrant call will
|
||||
// not interfere with the "parent" flush() call.
|
||||
// 2. bind:this callbacks cannot trigger new flush() calls.
|
||||
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
|
||||
// callback called a second time; the seen_callbacks set, outside the flush()
|
||||
// function, guarantees this behavior.
|
||||
const seen_callbacks = new Set();
|
||||
let flushidx = 0; // Do *not* move this inside the flush() function
|
||||
function flush() {
|
||||
const saved_component = current_component;
|
||||
do {
|
||||
// first, call beforeUpdate functions
|
||||
// and update components
|
||||
while (flushidx < dirty_components.length) {
|
||||
const component = dirty_components[flushidx];
|
||||
flushidx++;
|
||||
set_current_component(component);
|
||||
update(component.$$);
|
||||
}
|
||||
set_current_component(null);
|
||||
dirty_components.length = 0;
|
||||
flushidx = 0;
|
||||
while (binding_callbacks.length)
|
||||
binding_callbacks.pop()();
|
||||
// then, once components are updated, call
|
||||
// afterUpdate functions. This may cause
|
||||
// subsequent updates...
|
||||
for (let i = 0; i < render_callbacks.length; i += 1) {
|
||||
const callback = render_callbacks[i];
|
||||
if (!seen_callbacks.has(callback)) {
|
||||
// ...so guard against infinite loops
|
||||
seen_callbacks.add(callback);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
render_callbacks.length = 0;
|
||||
} while (dirty_components.length);
|
||||
while (flush_callbacks.length) {
|
||||
flush_callbacks.pop()();
|
||||
}
|
||||
update_scheduled = false;
|
||||
seen_callbacks.clear();
|
||||
set_current_component(saved_component);
|
||||
}
|
||||
function update($$) {
|
||||
if ($$.fragment !== null) {
|
||||
$$.update();
|
||||
run_all($$.before_update);
|
||||
const dirty = $$.dirty;
|
||||
$$.dirty = [-1];
|
||||
$$.fragment && $$.fragment.p($$.ctx, dirty);
|
||||
$$.after_update.forEach(add_render_callback);
|
||||
}
|
||||
}
|
||||
const outroing = new Set();
|
||||
function transition_in(block, local) {
|
||||
if (block && block.i) {
|
||||
outroing.delete(block);
|
||||
block.i(local);
|
||||
}
|
||||
}
|
||||
|
||||
const globals = (typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof globalThis !== 'undefined'
|
||||
? globalThis
|
||||
: global);
|
||||
function mount_component(component, target, anchor, customElement) {
|
||||
const { fragment, after_update } = component.$$;
|
||||
fragment && fragment.m(target, anchor);
|
||||
if (!customElement) {
|
||||
// onMount happens before the initial afterUpdate
|
||||
add_render_callback(() => {
|
||||
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
||||
// if the component was destroyed immediately
|
||||
// it will update the `$$.on_destroy` reference to `null`.
|
||||
// the destructured on_destroy may still reference to the old array
|
||||
if (component.$$.on_destroy) {
|
||||
component.$$.on_destroy.push(...new_on_destroy);
|
||||
}
|
||||
else {
|
||||
// Edge case - component was destroyed immediately,
|
||||
// most likely as a result of a binding initialising
|
||||
run_all(new_on_destroy);
|
||||
}
|
||||
component.$$.on_mount = [];
|
||||
});
|
||||
}
|
||||
after_update.forEach(add_render_callback);
|
||||
}
|
||||
function destroy_component(component, detaching) {
|
||||
const $$ = component.$$;
|
||||
if ($$.fragment !== null) {
|
||||
run_all($$.on_destroy);
|
||||
$$.fragment && $$.fragment.d(detaching);
|
||||
// TODO null out other refs, including component.$$ (but need to
|
||||
// preserve final state?)
|
||||
$$.on_destroy = $$.fragment = null;
|
||||
$$.ctx = [];
|
||||
}
|
||||
}
|
||||
function make_dirty(component, i) {
|
||||
if (component.$$.dirty[0] === -1) {
|
||||
dirty_components.push(component);
|
||||
schedule_update();
|
||||
component.$$.dirty.fill(0);
|
||||
}
|
||||
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
|
||||
}
|
||||
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
|
||||
const parent_component = current_component;
|
||||
set_current_component(component);
|
||||
const $$ = component.$$ = {
|
||||
fragment: null,
|
||||
ctx: [],
|
||||
// state
|
||||
props,
|
||||
update: noop,
|
||||
not_equal,
|
||||
bound: blank_object(),
|
||||
// lifecycle
|
||||
on_mount: [],
|
||||
on_destroy: [],
|
||||
on_disconnect: [],
|
||||
before_update: [],
|
||||
after_update: [],
|
||||
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
||||
// everything else
|
||||
callbacks: blank_object(),
|
||||
dirty,
|
||||
skip_bound: false,
|
||||
root: options.target || parent_component.$$.root
|
||||
};
|
||||
append_styles && append_styles($$.root);
|
||||
let ready = false;
|
||||
$$.ctx = instance
|
||||
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
||||
const value = rest.length ? rest[0] : ret;
|
||||
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
|
||||
if (!$$.skip_bound && $$.bound[i])
|
||||
$$.bound[i](value);
|
||||
if (ready)
|
||||
make_dirty(component, i);
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
: [];
|
||||
$$.update();
|
||||
ready = true;
|
||||
run_all($$.before_update);
|
||||
// `false` as a special case of no DOM component
|
||||
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
|
||||
if (options.target) {
|
||||
if (options.hydrate) {
|
||||
const nodes = children(options.target);
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.l(nodes);
|
||||
nodes.forEach(detach);
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
$$.fragment && $$.fragment.c();
|
||||
}
|
||||
if (options.intro)
|
||||
transition_in(component.$$.fragment);
|
||||
mount_component(component, options.target, options.anchor, options.customElement);
|
||||
flush();
|
||||
}
|
||||
set_current_component(parent_component);
|
||||
}
|
||||
let SvelteElement;
|
||||
if (typeof HTMLElement === 'function') {
|
||||
SvelteElement = class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
connectedCallback() {
|
||||
const { on_mount } = this.$$;
|
||||
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
|
||||
// @ts-ignore todo: improve typings
|
||||
for (const key in this.$$.slotted) {
|
||||
// @ts-ignore todo: improve typings
|
||||
this.appendChild(this.$$.slotted[key]);
|
||||
}
|
||||
}
|
||||
attributeChangedCallback(attr, _oldValue, newValue) {
|
||||
this[attr] = newValue;
|
||||
}
|
||||
disconnectedCallback() {
|
||||
run_all(this.$$.on_disconnect);
|
||||
}
|
||||
$destroy() {
|
||||
destroy_component(this, 1);
|
||||
this.$destroy = noop;
|
||||
}
|
||||
$on(type, callback) {
|
||||
// TODO should this delegate to addEventListener?
|
||||
if (!is_function(callback)) {
|
||||
return noop;
|
||||
}
|
||||
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
|
||||
callbacks.push(callback);
|
||||
return () => {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index !== -1)
|
||||
callbacks.splice(index, 1);
|
||||
};
|
||||
}
|
||||
$set($$props) {
|
||||
if (this.$$set && !is_empty($$props)) {
|
||||
this.$$.skip_bound = true;
|
||||
this.$$set($$props);
|
||||
this.$$.skip_bound = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function dispatch_dev(type, detail) {
|
||||
document.dispatchEvent(custom_event(type, Object.assign({ version: '3.52.0' }, detail), { bubbles: true }));
|
||||
}
|
||||
function append_dev(target, node) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node });
|
||||
append(target, node);
|
||||
}
|
||||
function insert_dev(target, node, anchor) {
|
||||
dispatch_dev('SvelteDOMInsert', { target, node, anchor });
|
||||
insert(target, node, anchor);
|
||||
}
|
||||
function detach_dev(node) {
|
||||
dispatch_dev('SvelteDOMRemove', { node });
|
||||
detach(node);
|
||||
}
|
||||
function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation) {
|
||||
const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
|
||||
if (has_prevent_default)
|
||||
modifiers.push('preventDefault');
|
||||
if (has_stop_propagation)
|
||||
modifiers.push('stopPropagation');
|
||||
dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
|
||||
const dispose = listen(node, event, handler, options);
|
||||
return () => {
|
||||
dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
|
||||
dispose();
|
||||
};
|
||||
}
|
||||
function attr_dev(node, attribute, value) {
|
||||
attr(node, attribute, value);
|
||||
if (value == null)
|
||||
dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
|
||||
else
|
||||
dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
|
||||
}
|
||||
function prop_dev(node, property, value) {
|
||||
node[property] = value;
|
||||
dispatch_dev('SvelteDOMSetProperty', { node, property, value });
|
||||
}
|
||||
function set_data_dev(text, data) {
|
||||
data = '' + data;
|
||||
if (text.wholeText === data)
|
||||
return;
|
||||
dispatch_dev('SvelteDOMSetData', { node: text, data });
|
||||
text.data = data;
|
||||
}
|
||||
function validate_each_argument(arg) {
|
||||
if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
|
||||
let msg = '{#each} only iterates over array-like objects.';
|
||||
if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
|
||||
msg += ' You can use a spread to convert this iterable into an array.';
|
||||
}
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
function validate_slots(name, slot, keys) {
|
||||
for (const slot_key of Object.keys(slot)) {
|
||||
if (!~keys.indexOf(slot_key)) {
|
||||
console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { validate_each_argument as A, text as B, set_data_dev as C, destroy_each as D, prop_dev as E, set_style as F, svg_element as G, is_function as H, HtmlTag as I, afterUpdate as J, set_input_value as K, SvelteElement as S, attribute_to_object as a, insert_dev as b, setContext as c, dispatch_dev as d, globals as e, element as f, getContext as g, space as h, init as i, add_location as j, attr_dev as k, append_dev as l, listen_dev as m, noop as n, onMount as o, detach_dev as p, binding_callbacks as q, run_all as r, safe_not_equal as s, flush as t, validate_store as u, validate_slots as v, component_subscribe as w, empty as x, src_url_equal as y, set_custom_element_data as z };
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
import { n as noop, s as safe_not_equal } from './index-6b4fe380.js';
|
||||
|
||||
const subscriber_queue = [];
|
||||
/**
|
||||
* Create a `Writable` store that allows both updating and reading by subscription.
|
||||
* @param {*=}value initial value
|
||||
* @param {StartStopNotifier=}start start and stop notifications for subscriptions
|
||||
*/
|
||||
function writable(value, start = noop) {
|
||||
let stop;
|
||||
const subscribers = new Set();
|
||||
function set(new_value) {
|
||||
if (safe_not_equal(value, new_value)) {
|
||||
value = new_value;
|
||||
if (stop) { // store is ready
|
||||
const run_queue = !subscriber_queue.length;
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber[1]();
|
||||
subscriber_queue.push(subscriber, value);
|
||||
}
|
||||
if (run_queue) {
|
||||
for (let i = 0; i < subscriber_queue.length; i += 2) {
|
||||
subscriber_queue[i][0](subscriber_queue[i + 1]);
|
||||
}
|
||||
subscriber_queue.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function update(fn) {
|
||||
set(fn(value));
|
||||
}
|
||||
function subscribe(run, invalidate = noop) {
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.add(subscriber);
|
||||
if (subscribers.size === 1) {
|
||||
stop = start(set) || noop;
|
||||
}
|
||||
run(value);
|
||||
return () => {
|
||||
subscribers.delete(subscriber);
|
||||
if (subscribers.size === 0) {
|
||||
stop();
|
||||
stop = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return { set, update, subscribe };
|
||||
}
|
||||
|
||||
export { writable as w };
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
import { n as noop, s as safe_not_equal } from './index-998178c7.js';
|
||||
|
||||
const subscriber_queue = [];
|
||||
/**
|
||||
* Create a `Writable` store that allows both updating and reading by subscription.
|
||||
* @param {*=}value initial value
|
||||
* @param {StartStopNotifier=}start start and stop notifications for subscriptions
|
||||
*/
|
||||
function writable(value, start = noop) {
|
||||
let stop;
|
||||
const subscribers = new Set();
|
||||
function set(new_value) {
|
||||
if (safe_not_equal(value, new_value)) {
|
||||
value = new_value;
|
||||
if (stop) { // store is ready
|
||||
const run_queue = !subscriber_queue.length;
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber[1]();
|
||||
subscriber_queue.push(subscriber, value);
|
||||
}
|
||||
if (run_queue) {
|
||||
for (let i = 0; i < subscriber_queue.length; i += 2) {
|
||||
subscriber_queue[i][0](subscriber_queue[i + 1]);
|
||||
}
|
||||
subscriber_queue.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function update(fn) {
|
||||
set(fn(value));
|
||||
}
|
||||
function subscribe(run, invalidate = noop) {
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.add(subscriber);
|
||||
if (subscribers.size === 1) {
|
||||
stop = start(set) || noop;
|
||||
}
|
||||
run(value);
|
||||
return () => {
|
||||
subscribers.delete(subscriber);
|
||||
if (subscribers.size === 0) {
|
||||
stop();
|
||||
stop = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return { set, update, subscribe };
|
||||
}
|
||||
|
||||
export { writable as w };
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);
|
||||
import { n as noop, s as safe_not_equal } from './index-122ecbb4.js';
|
||||
|
||||
const subscriber_queue = [];
|
||||
/**
|
||||
* Create a `Writable` store that allows both updating and reading by subscription.
|
||||
* @param {*=}value initial value
|
||||
* @param {StartStopNotifier=}start start and stop notifications for subscriptions
|
||||
*/
|
||||
function writable(value, start = noop) {
|
||||
let stop;
|
||||
const subscribers = new Set();
|
||||
function set(new_value) {
|
||||
if (safe_not_equal(value, new_value)) {
|
||||
value = new_value;
|
||||
if (stop) { // store is ready
|
||||
const run_queue = !subscriber_queue.length;
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber[1]();
|
||||
subscriber_queue.push(subscriber, value);
|
||||
}
|
||||
if (run_queue) {
|
||||
for (let i = 0; i < subscriber_queue.length; i += 2) {
|
||||
subscriber_queue[i][0](subscriber_queue[i + 1]);
|
||||
}
|
||||
subscriber_queue.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function update(fn) {
|
||||
set(fn(value));
|
||||
}
|
||||
function subscribe(run, invalidate = noop) {
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.add(subscriber);
|
||||
if (subscribers.size === 1) {
|
||||
stop = start(set) || noop;
|
||||
}
|
||||
run(value);
|
||||
return () => {
|
||||
subscribers.delete(subscriber);
|
||||
if (subscribers.size === 0) {
|
||||
stop();
|
||||
stop = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return { set, update, subscribe };
|
||||
}
|
||||
|
||||
export { writable as w };
|