Merge branch 'profile-feature'
This commit is contained in:
commit
035fee2997
Server
Manifest.tomlProject.tomlrollup.config.js
app
layouts
resources
authentication
basic
communes
cooperatives
groups
parties
partners
users
svelte
public
css
js/libraries
locales/en
src
auth
communes-component.sveltecomponents
cooperatives-component.sveltefooter
groups-add-component.sveltelanding-component.sveltenavbar
profile
config
db/migrations
2019052410085235_create_table_users.jl2022026611846565_create_table_groups.jl2022026611846566_create_table_communes.jl2022026611846567_create_table_cooperatives.jl2022026611846568_create_table_partners.jl2022026611846569_create_table_groups_requests.jl2022026611846570_create_table_communes_requests.jl2022026611846571_create_table_coops_requests.jl2022026611846572_create_table_parties_requests.jl2022026611846573_create_table_groups_users.jl2022026611846574_create_table_communes_users.jl2022026611846575_create_table_cooperatives_users.jl2022026611846576_create_table_parties_users.jl2022026611846577_create_table_users_groups.jl
lib
plugins
public
assets
css
img
auth
common
profile
js/components
auth-component.jscommunes-add-component.jscommunes-component.jscompass-component.jsconfirmation-component.jscookies-dialog.jscooperatives-add-component.jscooperatives-component.jsfooter-component.jsgroups-add-component.jsgroups-component.jsindex-0f28c1ea.jsindex-122ecbb4.jsindex-6b4fe380.jsindex-720c0a59.jsindex-998178c7.jsindex-db20528a.jsindex-e7d4b1a1.jsindex-ee911aff.jsindex-f9998ce7.jsindex-fb9750f3.jsjoin-us-component.jslanding-component.js
|
@ -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 (image error) 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 (image error) 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 (image error) 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 (image error) 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 (image error) Size: 210 B After (image error) 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 (image error) 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 (image error) 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 (image error) 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 (image error) Size: 46 KiB |
File diff suppressed because it is too large
Load Diff
After (image error) 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};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -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};
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -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};
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -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 };
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue