From 7225d027c903a0b62c39cd9fcf553ed0e8a73019 Mon Sep 17 00:00:00 2001 From: Arnaud Delcasse Date: Thu, 11 Aug 2022 17:26:55 +0200 Subject: [PATCH] Big refactoring of PARCOURSMOB - Initial commit --- .gitignore | 3 + README.md | 3 + config.go | 41 + go.mod | 74 + go.sum | 695 ++++ handlers/api/api.go | 30 + handlers/api/cache.go | 51 + handlers/api/geo.go | 54 + handlers/api/oidc.go | 46 + handlers/application/administration.go | 123 + handlers/application/application.go | 36 + handlers/application/beneficiaries.go | 305 ++ handlers/application/dashboard.go | 52 + handlers/application/vehicles-management.go | 24 + handlers/auth/groups.go | 116 + main.go | 94 + renderer/administration.go | 32 + renderer/auth.go | 13 + renderer/beneficiaries.go | 67 + renderer/dashboard.go | 20 + renderer/func-maps.go | 77 + renderer/layout.go | 18 + renderer/renderer.go | 184 + renderer/vehicle-management.go | 19 + services/groupsmanagement.go | 23 + services/mobilityaccounts.go | 23 + services/services.go | 39 + themes/default/README.md | 24 + themes/default/assets/css/main.css | 19 + themes/default/assets/js/main.js | 6 + themes/default/fonts/bitter.ttf | Bin 0 -> 90628 bytes .../_partials/address_autocomplete.html | 47 + .../default/layouts/_partials/mainmenu.html | 19 + .../_partials/groups_admins.html | 37 + .../layouts/administration/create_group.html | 142 + .../layouts/administration/display_group.html | 114 + .../default/layouts/administration/home.html | 136 + themes/default/layouts/auth/groups.html | 40 + .../_partials/beneficiary-events.html | 5 + .../_partials/beneficiary-files.html | 5 + .../_partials/beneficiary-journeys.html | 5 + .../_partials/beneficiary-notes.html | 108 + .../default/layouts/beneficiaries/create.html | 173 + .../layouts/beneficiaries/display.html | 304 ++ .../default/layouts/beneficiaries/list.html | 159 + .../default/layouts/beneficiaries/update.html | 173 + .../_partials/beneficiaries-widget.html | 31 + .../default/layouts/dashboard/dashboard.html | 15 + themes/default/layouts/layout.html | 177 + .../_partials/bookings-list.html | 72 + .../_partials/vehicle-type-select.html | 63 + .../_partials/vehicles-list.html | 54 + .../vehicles_management/fleet-add.html | 106 + .../layouts/vehicles_management/overview.html | 31 + themes/default/public/css/main.css | 2543 ++++++++++++++ .../images/parcoursmob_logo_whitered.svg | 1 + themes/default/public/js/main.js | 2995 +++++++++++++++++ themes/default/tailwind.config.js | 23 + utils/cache/cache.go | 104 + utils/form-validators/form-validators.go | 14 + utils/form-validators/phone-numbers.go | 15 + utils/icons/svg-icons.go | 26 + utils/identification/groups.go | 74 + utils/identification/oidc.go | 117 + utils/profile-pictures/profile-pictures.go | 37 + 65 files changed, 10276 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 handlers/api/api.go create mode 100644 handlers/api/cache.go create mode 100644 handlers/api/geo.go create mode 100644 handlers/api/oidc.go create mode 100644 handlers/application/administration.go create mode 100644 handlers/application/application.go create mode 100644 handlers/application/beneficiaries.go create mode 100644 handlers/application/dashboard.go create mode 100644 handlers/application/vehicles-management.go create mode 100644 handlers/auth/groups.go create mode 100644 main.go create mode 100644 renderer/administration.go create mode 100644 renderer/auth.go create mode 100644 renderer/beneficiaries.go create mode 100644 renderer/dashboard.go create mode 100644 renderer/func-maps.go create mode 100644 renderer/layout.go create mode 100644 renderer/renderer.go create mode 100644 renderer/vehicle-management.go create mode 100644 services/groupsmanagement.go create mode 100644 services/mobilityaccounts.go create mode 100644 services/services.go create mode 100644 themes/default/README.md create mode 100644 themes/default/assets/css/main.css create mode 100644 themes/default/assets/js/main.js create mode 100644 themes/default/fonts/bitter.ttf create mode 100644 themes/default/layouts/_partials/address_autocomplete.html create mode 100644 themes/default/layouts/_partials/mainmenu.html create mode 100644 themes/default/layouts/administration/_partials/groups_admins.html create mode 100644 themes/default/layouts/administration/create_group.html create mode 100644 themes/default/layouts/administration/display_group.html create mode 100644 themes/default/layouts/administration/home.html create mode 100644 themes/default/layouts/auth/groups.html create mode 100644 themes/default/layouts/beneficiaries/_partials/beneficiary-events.html create mode 100644 themes/default/layouts/beneficiaries/_partials/beneficiary-files.html create mode 100644 themes/default/layouts/beneficiaries/_partials/beneficiary-journeys.html create mode 100644 themes/default/layouts/beneficiaries/_partials/beneficiary-notes.html create mode 100644 themes/default/layouts/beneficiaries/create.html create mode 100644 themes/default/layouts/beneficiaries/display.html create mode 100644 themes/default/layouts/beneficiaries/list.html create mode 100644 themes/default/layouts/beneficiaries/update.html create mode 100644 themes/default/layouts/dashboard/_partials/beneficiaries-widget.html create mode 100644 themes/default/layouts/dashboard/dashboard.html create mode 100644 themes/default/layouts/layout.html create mode 100644 themes/default/layouts/vehicles_management/_partials/bookings-list.html create mode 100644 themes/default/layouts/vehicles_management/_partials/vehicle-type-select.html create mode 100644 themes/default/layouts/vehicles_management/_partials/vehicles-list.html create mode 100644 themes/default/layouts/vehicles_management/fleet-add.html create mode 100644 themes/default/layouts/vehicles_management/overview.html create mode 100644 themes/default/public/css/main.css create mode 100644 themes/default/public/images/parcoursmob_logo_whitered.svg create mode 100644 themes/default/public/js/main.js create mode 100644 themes/default/tailwind.config.js create mode 100644 utils/cache/cache.go create mode 100644 utils/form-validators/form-validators.go create mode 100644 utils/form-validators/phone-numbers.go create mode 100644 utils/icons/svg-icons.go create mode 100644 utils/identification/groups.go create mode 100644 utils/identification/oidc.go create mode 100644 utils/profile-pictures/profile-pictures.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f702e7b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +config.yaml +.vscode +__debug_bin \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7383122 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# PARCOURSMOB + +The PARCOURSMOB inclusive mobility platform. \ No newline at end of file diff --git a/config.go b/config.go new file mode 100644 index 0000000..ac4eddb --- /dev/null +++ b/config.go @@ -0,0 +1,41 @@ +package main + +import ( + "strings" + + "github.com/spf13/viper" +) + +func ReadConfig() (*viper.Viper, error) { + defaults := map[string]any{ + "service_name": "PARCOURSMOB", + "templates": map[string]any{ + "dir": "templates/default", + "public_dir": "template/default/public", + }, + "server": map[string]any{ + "listen": "0.0.0.0:9000", + }, + "identification": map[string]any{ + "sessions": map[string]any{ + "store": "cookie", + "session_key": "SESSION_KEY", + }, + }, + "geo": map[string]any{ + "pelias": map[string]any{ + "url": "https://geocode.ridygo.fr", + }, + }, + } + v := viper.New() + for key, value := range defaults { + v.SetDefault(key, value) + } + v.SetConfigName("config") + v.AddConfigPath(".") + v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + v.AutomaticEnv() + err := v.ReadInConfig() + return v, err +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a5e9b03 --- /dev/null +++ b/go.mod @@ -0,0 +1,74 @@ +module git.coopgo.io/coopgo-apps/parcoursmob + +go 1.18 + +replace git.coopgo.io/coopgo-platform/mobility-accounts => ../../coopgo-platform/mobility-accounts/ + +replace git.coopgo.io/coopgo-platform/groups-management => ../../coopgo-platform/groups-management/ + +require ( + git.coopgo.io/coopgo-platform/groups-management v0.0.0-00010101000000-000000000000 + git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-00010101000000-000000000000 + github.com/coreos/go-oidc v2.2.1+incompatible + github.com/fogleman/gg v1.3.0 + github.com/go-playground/validator/v10 v10.11.0 + github.com/google/uuid v1.3.0 + github.com/gorilla/mux v1.8.0 + github.com/gorilla/sessions v1.2.1 + github.com/spf13/viper v1.12.0 + go.etcd.io/etcd/client/v3 v3.5.4 + golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 + golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 + google.golang.org/grpc v1.48.0 + google.golang.org/protobuf v1.28.1 +) + +require ( + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/go-playground/locales v0.14.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.1 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pquerna/cachecontrol v0.1.0 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect + github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.3.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.1 // indirect + github.com/xdg-go/stringprep v1.0.3 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + go.etcd.io/etcd/api/v3 v3.5.4 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect + go.mongodb.org/mongo-driver v1.10.1 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.17.0 // indirect + golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect + golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect + gopkg.in/ini.v1 v1.66.4 // indirect + gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3671ecc --- /dev/null +++ b/go.sum @@ -0,0 +1,695 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= +github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw= +github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc= +github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE= +github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= +github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= +go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= +go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= +go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= +go.mongodb.org/mongo-driver v1.10.1 h1:NujsPveKwHaWuKUer/ceo9DzEe7HIj1SlJ6uvXZG0S4= +go.mongodb.org/mongo-driver v1.10.1/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 h1:/eM0PCrQI2xd471rI+snWuu251/+/jpBpZqir2mPdnU= +golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= +gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 h1:lwJmuuJQGclcankpPJwh8rorzB0bNbVALv8phDGh8TQ= +gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/handlers/api/api.go b/handlers/api/api.go new file mode 100644 index 0000000..f21d85c --- /dev/null +++ b/handlers/api/api.go @@ -0,0 +1,30 @@ +package api + +import ( + "net/http" + + "git.coopgo.io/coopgo-apps/parcoursmob/services" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/cache" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" + "github.com/spf13/viper" +) + +type APIHandler struct { + idp *identification.IdentificationProvider + config *viper.Viper + services *services.ServicesHandler + cache *cache.CacheHandler +} + +func NewAPIHandler(cfg *viper.Viper, idp *identification.IdentificationProvider, svc *services.ServicesHandler, cache *cache.CacheHandler) (*APIHandler, error) { + return &APIHandler{ + idp: idp, + config: cfg, + services: svc, + cache: cache, + }, nil +} + +func (h *APIHandler) NotFound(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) +} diff --git a/handlers/api/cache.go b/handlers/api/cache.go new file mode 100644 index 0000000..433d7fc --- /dev/null +++ b/handlers/api/cache.go @@ -0,0 +1,51 @@ +package api + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + + "github.com/gorilla/mux" +) + +func (h APIHandler) GetCache(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + cacheid := vars["cacheid"] + + d, err := h.cache.Get(cacheid) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusNotFound) + return + } + + result := d + + if data, ok := d.([]any); ok { + if limitsmin, ok := r.URL.Query()["limits.min"]; ok { + min, _ := strconv.Atoi(limitsmin[0]) + if limitsmax, ok := r.URL.Query()["limits.max"]; ok { + max, _ := strconv.Atoi(limitsmax[0]) + if max > len(data) { + result = data[min:] + } else { + result = data[min:max] + } + } else { + result = data[min:] + } + } + } + + j, err := json.Marshal(result) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + w.Write(j) + +} diff --git a/handlers/api/geo.go b/handlers/api/geo.go new file mode 100644 index 0000000..ccdeca2 --- /dev/null +++ b/handlers/api/geo.go @@ -0,0 +1,54 @@ +package api + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" +) + +func (h *APIHandler) GeoAutocomplete(w http.ResponseWriter, r *http.Request) { + + pelias := h.config.GetString("geo.pelias.url") + + t, ok := r.URL.Query()["text"] + + if !ok || len(t[0]) < 1 { + w.WriteHeader(http.StatusBadRequest) + return + } + + text := t[0] + + resp, err := http.Get(fmt.Sprintf("%s/autocomplete?text=%s", pelias, text)) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + + if err != nil { + log.Fatal(err) + } + + var response map[string]any + jsonErr := json.Unmarshal(body, &response) + if jsonErr != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + j, err := json.Marshal(response["features"]) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + w.Write(j) +} diff --git a/handlers/api/oidc.go b/handlers/api/oidc.go new file mode 100644 index 0000000..f0e43cc --- /dev/null +++ b/handlers/api/oidc.go @@ -0,0 +1,46 @@ +package api + +import ( + "context" + "fmt" + "net/http" +) + +func (h APIHandler) OAuth2Callback(w http.ResponseWriter, r *http.Request) { + oauth2Token, err := h.idp.OAuth2Config.Exchange(context.Background(), r.URL.Query().Get("code")) + if err != nil { + fmt.Println("Exchange error") + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Extract the ID Token from OAuth2 token. + rawIDToken, ok := oauth2Token.Extra("id_token").(string) + if !ok { + w.WriteHeader(http.StatusInternalServerError) + return + } + + _, err = h.idp.TokenVerifier.Verify(context.Background(), rawIDToken) + if err != nil { + fmt.Println("not able to verify token") + fmt.Println(err) + w.WriteHeader(http.StatusUnauthorized) + return + } + + session, _ := h.idp.SessionsStore.Get(r, "parcoursmob_session") + session.Values["idtoken"] = rawIDToken + + redirect := "/app/" + + if session.Values["redirect"] != nil && session.Values["redirect"] != "" { + redirect = session.Values["redirect"].(string) + delete(session.Values, "redirect") + } + + session.Save(r, w) + + http.Redirect(w, r, redirect, http.StatusFound) +} diff --git a/handlers/application/administration.go b/handlers/application/administration.go new file mode 100644 index 0000000..1ea7ca0 --- /dev/null +++ b/handlers/application/administration.go @@ -0,0 +1,123 @@ +package application + +import ( + "context" + "fmt" + "net/http" + + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + "github.com/google/uuid" + "github.com/gorilla/mux" + "google.golang.org/protobuf/types/known/structpb" +) + +func (h *ApplicationHandler) Administration(w http.ResponseWriter, r *http.Request) { + + request := &groupsmanagement.GetGroupsRequest{ + Namespaces: []string{"parcoursmob_organizations"}, + } + + resp, err := h.services.GRPC.GroupsManagement.GetGroups(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var groups = []any{} + + for _, group := range resp.Groups { + g := group.ToStorageType() + groups = append(groups, g) + } + + h.Renderer.Administration(w, r, groups) +} + +func (h *ApplicationHandler) AdministrationCreateGroup(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + r.ParseForm() + + if r.FormValue("name") == "" { + + fmt.Println("invalid name") + w.WriteHeader(http.StatusBadRequest) + return + } + + modules := map[string]any{ + "beneficiaries": r.FormValue("modules.beneficiaries") == "on", + "journeys": r.FormValue("modules.journeys") == "on", + "vehicles": r.FormValue("modules.vehicles") == "on", + "vehicles_management": r.FormValue("modules.vehicles_management") == "on", + "events": r.FormValue("modules.events") == "on", + "administration": r.FormValue("modules.administration") == "on", + } + + groupid := uuid.NewString() + + dataMap := map[string]any{ + "name": r.FormValue("name"), + "modules": modules, + } + + data, err := structpb.NewValue(dataMap) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + request_organization := &groupsmanagement.AddGroupRequest{ + Group: &groupsmanagement.Group{ + Id: groupid, + Namespace: "parcoursmob_organizations", + Data: data.GetStructValue(), + }, + } + + request_role := &groupsmanagement.AddGroupRequest{ + Group: &groupsmanagement.Group{ + Id: groupid + ":admin", + Namespace: "parcoursmob_roles", + }, + } + + _, err = h.services.GRPC.GroupsManagement.AddGroup(context.TODO(), request_organization) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Create the admin role for the organization + _, err = h.services.GRPC.GroupsManagement.AddGroup(context.TODO(), request_role) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/administration/groups/%s", groupid), http.StatusFound) + return + } + h.Renderer.AdministrationCreateGroup(w, r) +} + +func (h *ApplicationHandler) AdministrationGroupDisplay(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + groupid := vars["groupid"] + + request := &groupsmanagement.GetGroupRequest{ + Id: groupid, + } + + resp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + h.Renderer.AdministrationGroupDisplay(w, r, resp.Group.ToStorageType()) +} diff --git a/handlers/application/application.go b/handlers/application/application.go new file mode 100644 index 0000000..de52c0e --- /dev/null +++ b/handlers/application/application.go @@ -0,0 +1,36 @@ +package application + +import ( + "net/http" + + "git.coopgo.io/coopgo-apps/parcoursmob/renderer" + "git.coopgo.io/coopgo-apps/parcoursmob/services" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/cache" + "github.com/spf13/viper" +) + +type ApplicationHandler struct { + config *viper.Viper + Renderer *renderer.Renderer + services *services.ServicesHandler + cache *cache.CacheHandler +} + +func NewApplicationHandler(cfg *viper.Viper, svc *services.ServicesHandler, cache *cache.CacheHandler) (*ApplicationHandler, error) { + templates_root := cfg.GetString("templates.root") + renderer := renderer.NewRenderer(cfg, templates_root) + return &ApplicationHandler{ + config: cfg, + Renderer: renderer, + services: svc, + cache: cache, + }, nil +} + +func (h *ApplicationHandler) NotFound(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) +} + +func (h *ApplicationHandler) templateFile(file string) string { + return h.config.GetString("templates.root") + file +} diff --git a/handlers/application/beneficiaries.go b/handlers/application/beneficiaries.go new file mode 100644 index 0000000..025ad37 --- /dev/null +++ b/handlers/application/beneficiaries.go @@ -0,0 +1,305 @@ +package application + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "image/png" + "log" + "net/http" + "strconv" + "strings" + "time" + + formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" + profilepictures "git.coopgo.io/coopgo-apps/parcoursmob/utils/profile-pictures" + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + "git.coopgo.io/coopgo-platform/groups-management/storage" + mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" + "github.com/google/uuid" + "github.com/gorilla/mux" + "google.golang.org/protobuf/types/known/structpb" +) + +type BeneficiariesForm struct { + FirstName string `json:"first_name" validate:"required"` + LastName string `json:"last_name" validate:"required"` + Email string `json:"email" validate:"required,email"` + Birthdate *time.Time `json:"birthdate"` + PhoneNumber string `json:"phone_number" validate:"required,phoneNumber"` + Address any `json:"address,omitempty"` + Gender string `json:"gender"` +} + +func (h *ApplicationHandler) BeneficiariesList(w http.ResponseWriter, r *http.Request) { + g := r.Context().Value(identification.GroupKey) + if g == nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + group := g.(storage.Group) + + request := &mobilityaccounts.GetAccountsBatchRequest{ + Accountids: group.Members, + } + + resp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var accounts = []any{} + + for _, account := range resp.Accounts { + if filterAccount(r, account) { + a := account.ToStorageType() + accounts = append(accounts, a) + } + } + + cacheid := uuid.NewString() + h.cache.PutWithTTL(cacheid, accounts, 1*time.Hour) + + h.Renderer.BeneficiariesList(w, r, accounts, cacheid) +} + +func (h *ApplicationHandler) BeneficiaryCreate(w http.ResponseWriter, r *http.Request) { + g := r.Context().Value(identification.GroupKey) + if g == nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + group := g.(storage.Group) + fmt.Println(group) + + if r.Method == "POST" { + + dataMap, err := parseForm(r) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusBadRequest) + return + } + + data, err := structpb.NewValue(dataMap) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + request := &mobilityaccounts.RegisterRequest{ + Account: &mobilityaccounts.Account{ + Namespace: "parcoursmob_beneficiaries", + Data: data.GetStructValue(), + }, + } + + resp, err := h.services.GRPC.MobilityAccounts.Register(context.TODO(), request) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + subscribe := &groupsmanagement.SubscribeRequest{ + Groupid: group.ID, + Memberid: resp.Account.Id, + } + + _, err = h.services.GRPC.GroupsManagement.Subscribe(context.TODO(), subscribe) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/beneficiaries/%s", resp.Account.Id), http.StatusFound) + + return + } + h.Renderer.BeneficiaryCreate(w, r) +} + +func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + beneficiaryID := vars["beneficiaryid"] + + request := &mobilityaccounts.GetAccountRequest{ + Id: beneficiaryID, + } + + resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + //TODO filter namespaces + //TODO filter groups + + h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType()) +} + +func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + beneficiaryID := vars["beneficiaryid"] + + if r.Method == "POST" { + + dataMap, err := parseForm(r) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusBadRequest) + return + } + + data, err := structpb.NewValue(dataMap) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + request := &mobilityaccounts.UpdateDataRequest{ + Account: &mobilityaccounts.Account{ + Id: beneficiaryID, + Namespace: "parcoursmob_beneficiaries", + Data: data.GetStructValue(), + }, + } + + resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/beneficiaries/%s", resp.Account.Id), http.StatusFound) + + return + } + + request := &mobilityaccounts.GetAccountRequest{ + Id: beneficiaryID, + } + + resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + //TODO filter namespaces + //TODO filter groups + + h.Renderer.BeneficiaryUpdate(w, r, resp.Account.ToStorageType()) +} + +func parseForm(r *http.Request) (map[string]any, error) { + if err := r.ParseForm(); err != nil { + return nil, err + } + + var date *time.Time + + if r.PostFormValue("birthdate") != "" { + d, err := time.Parse("2006-01-02", r.PostFormValue("birthdate")) + if err != nil { + return nil, err + } + date = &d + } + + formData := BeneficiariesForm{ + FirstName: r.PostFormValue("first_name"), + LastName: r.PostFormValue("last_name"), + Email: r.PostFormValue("email"), + Birthdate: date, + PhoneNumber: r.PostFormValue("phone_number"), + Gender: r.PostFormValue("gender"), + } + + if r.PostFormValue("address") != "" { + var a any + json.Unmarshal([]byte(r.PostFormValue("address")), &a) + + formData.Address = a + } + + validate := formvalidators.New() + if err := validate.Struct(formData); err != nil { + return nil, err + } + + d, err := json.Marshal(formData) + if err != nil { + return nil, err + } + + var dataMap map[string]any + err = json.Unmarshal(d, &dataMap) + if err != nil { + return nil, err + } + + return dataMap, nil +} + +func (h *ApplicationHandler) BeneficiaryPicture(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + beneficiaryID := vars["beneficiaryid"] + + request := &mobilityaccounts.GetAccountRequest{ + Id: beneficiaryID, + } + + resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + account := resp.Account.ToStorageType() + + firstName := account.Data["first_name"].(string) + lastName := account.Data["last_name"].(string) + picture := profilepictures.DefaultProfilePicture(strings.ToUpper(firstName[0:1] + lastName[0:1])) + + buffer := new(bytes.Buffer) + if err := png.Encode(buffer, picture); err != nil { + log.Println("unable to encode image.") + } + + w.Header().Set("Content-Type", "image/png") + w.Header().Set("Content-Length", strconv.Itoa(len(buffer.Bytes()))) + if _, err := w.Write(buffer.Bytes()); err != nil { + log.Println("unable to write image.") + } +} + +func filterAccount(r *http.Request, a *mobilityaccounts.Account) bool { + searchFilter, ok := r.URL.Query()["search"] + + if ok && len(searchFilter[0]) > 0 { + name := a.Data.AsMap()["first_name"].(string) + " " + a.Data.AsMap()["last_name"].(string) + if !strings.Contains(strings.ToLower(name), strings.ToLower(searchFilter[0])) { + return false + } + } + + return true +} diff --git a/handlers/application/dashboard.go b/handlers/application/dashboard.go new file mode 100644 index 0000000..addfaf5 --- /dev/null +++ b/handlers/application/dashboard.go @@ -0,0 +1,52 @@ +package application + +import ( + "context" + "fmt" + "net/http" + + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" + "git.coopgo.io/coopgo-platform/groups-management/storage" + mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" +) + +func (h *ApplicationHandler) Dashboard(w http.ResponseWriter, r *http.Request) { + + g := r.Context().Value(identification.GroupKey) + if g == nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + group := g.(storage.Group) + + request := &mobilityaccounts.GetAccountsBatchRequest{ + Accountids: group.Members, + } + + resp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var accounts = []any{} + + // We only display the 10 last here + count := len(resp.Accounts) + min := count - 10 + if min < 0 { + min = 0 + } + + for _, account := range resp.Accounts[min:] { + if filterAccount(r, account) { + a := account.ToStorageType() + accounts = append([]any{a}, accounts...) + } + } + + h.Renderer.Dashboard(w, r, accounts, count) + +} diff --git a/handlers/application/vehicles-management.go b/handlers/application/vehicles-management.go new file mode 100644 index 0000000..d85b121 --- /dev/null +++ b/handlers/application/vehicles-management.go @@ -0,0 +1,24 @@ +package application + +import ( + "fmt" + "net/http" +) + +func (h *ApplicationHandler) VehiclesManagementOverview(w http.ResponseWriter, r *http.Request) { + h.Renderer.VehiclesManagementOverview(w, r) +} + +func (h *ApplicationHandler) VehiclesFleetAdd(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + if err := r.ParseForm(); err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusBadRequest) + return + } + + fmt.Println(r.Form) + return + } + h.Renderer.VehiclesFleetAdd(w, r) +} diff --git a/handlers/auth/groups.go b/handlers/auth/groups.go new file mode 100644 index 0000000..7d8839f --- /dev/null +++ b/handlers/auth/groups.go @@ -0,0 +1,116 @@ +package auth + +import ( + "context" + "fmt" + "net/http" + + "git.coopgo.io/coopgo-apps/parcoursmob/renderer" + "git.coopgo.io/coopgo-apps/parcoursmob/services" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/cache" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + "github.com/spf13/viper" +) + +type AuthHandler struct { + idp *identification.IdentificationProvider + config *viper.Viper + services *services.ServicesHandler + Renderer *renderer.Renderer + cache *cache.CacheHandler +} + +func NewAuthHandler(cfg *viper.Viper, idp *identification.IdentificationProvider, svc *services.ServicesHandler, cache *cache.CacheHandler) (*AuthHandler, error) { + templates_root := cfg.GetString("templates.root") + renderer := renderer.NewRenderer(cfg, templates_root) + return &AuthHandler{ + idp: idp, + config: cfg, + services: svc, + Renderer: renderer, + cache: cache, + }, nil +} + +func (h *AuthHandler) Groups(w http.ResponseWriter, r *http.Request) { + session, _ := h.idp.SessionsStore.Get(r, "parcoursmob_session") + + if r.Method == "POST" { + r.ParseForm() + + groupid := r.FormValue("group") + + session.Values["organization"] = groupid + session.Save(r, w) + + http.Redirect(w, r, "/app/", http.StatusFound) + + return + } + + tokenstring, ok := session.Values["idtoken"] + + if !ok { + http.Redirect(w, r, "/app/", http.StatusFound) + return + } + + idtoken, err := h.idp.TokenVerifier.Verify(context.Background(), tokenstring.(string)) + if err != nil { + delete(session.Values, "idtoken") + http.Redirect(w, r, "/app/", http.StatusFound) + return + } + + var claims map[string]any + + err = idtoken.Claims(&claims) + if err != nil { + fmt.Println(err) + } + + g := claims["groups"] + + groups_interface, ok := g.([]any) + if !ok { + w.WriteHeader(http.StatusInternalServerError) + return + } + + groups := []string{} + + for _, v := range groups_interface { + groups = append(groups, v.(string)) + } + + request := &groupsmanagement.GetGroupsBatchRequest{ + Groupids: groups, + } + + resp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var groupsresponse = []any{} + + for _, group := range resp.Groups { + if group.Namespace != "parcoursmob_organizations" { + continue + } + g := group.ToStorageType() + groupsresponse = append(groupsresponse, g) + } + + h.Renderer.AuthGroups(w, r, groupsresponse) +} + +func (h *AuthHandler) GroupSwitch(w http.ResponseWriter, r *http.Request) { + session, _ := h.idp.SessionsStore.Get(r, "parcoursmob_session") + delete(session.Values, "organization") + session.Save(r, w) + http.Redirect(w, r, "/app/", http.StatusFound) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e6f27d3 --- /dev/null +++ b/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "time" + + "git.coopgo.io/coopgo-apps/parcoursmob/handlers/api" + "git.coopgo.io/coopgo-apps/parcoursmob/handlers/application" + "git.coopgo.io/coopgo-apps/parcoursmob/handlers/auth" + "git.coopgo.io/coopgo-apps/parcoursmob/services" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/cache" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" + "github.com/gorilla/mux" +) + +func main() { + cfg, err := ReadConfig() + if err != nil { + panic(err) + } + + var ( + address = cfg.GetString("server.listen") + service_name = cfg.GetString("service_name") + templates_public_dir = cfg.GetString("templates.public_dir") + ) + + svc, err := services.NewServicesHandler(cfg) + if err != nil { + panic(err) + } + + idp, err := identification.NewIdentificationProvider(cfg, svc) + if err != nil { + panic(err) + } + + cache, err := cache.NewCacheHandler(cfg) + if err != nil { + panic(err) + } + + apiHandler, _ := api.NewAPIHandler(cfg, idp, svc, cache) + applicationHandler, _ := application.NewApplicationHandler(cfg, svc, cache) + authHandler, _ := auth.NewAuthHandler(cfg, idp, svc, cache) + + fmt.Println("Running", service_name, ":") + + r := mux.NewRouter() + + r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir(templates_public_dir)))) + + r.HandleFunc("/auth/groups/", authHandler.Groups) + r.HandleFunc("/auth/groups/switch", authHandler.GroupSwitch) + + api_router := r.PathPrefix("/api").Subrouter() + api_router.HandleFunc("/", apiHandler.NotFound) + api_router.HandleFunc("/geo/autocomplete", apiHandler.GeoAutocomplete) + api_router.HandleFunc("/cache/{cacheid}", apiHandler.GetCache) + api_router.HandleFunc("/oauth2/callback", apiHandler.OAuth2Callback) + + application := r.PathPrefix("/app").Subrouter() + application.HandleFunc("/", applicationHandler.Dashboard) + application.HandleFunc("/beneficiaries/", applicationHandler.BeneficiariesList) + application.HandleFunc("/beneficiaries/create", applicationHandler.BeneficiaryCreate) + application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay) + application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate) + application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture) + application.HandleFunc("/vehicles-management/", applicationHandler.VehiclesManagementOverview) + application.HandleFunc("/vehicles-management/fleet/add", applicationHandler.VehiclesFleetAdd) + //TODO Subrouters with middlewares checking security for each module ? + application.Use(idp.Middleware) + application.Use(idp.GroupsMiddleware) + + appAdmin := application.PathPrefix("/administration").Subrouter() + appAdmin.HandleFunc("/", applicationHandler.Administration) + appAdmin.HandleFunc("/groups/", applicationHandler.AdministrationCreateGroup) + appAdmin.HandleFunc("/groups/{groupid}", applicationHandler.AdministrationGroupDisplay) + //TODO Secure with Middleware checking for modules + + fmt.Println("-> HTTP server listening on", address) + + srv := &http.Server{ + Handler: r, + Addr: address, + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) + +} diff --git a/renderer/administration.go b/renderer/administration.go new file mode 100644 index 0000000..8fb4342 --- /dev/null +++ b/renderer/administration.go @@ -0,0 +1,32 @@ +package renderer + +import "net/http" + +const administrationMenu = "administration" + +func (renderer *Renderer) Administration(w http.ResponseWriter, r *http.Request, groups any) { + files := renderer.ThemeConfig.GetStringSlice("views.administration.home.files") + state := NewState(r, renderer.ThemeConfig, administrationMenu) + state.ViewState = map[string]any{ + "groups": groups, + } + + renderer.Render("administration", w, r, files, state) +} + +func (renderer *Renderer) AdministrationCreateGroup(w http.ResponseWriter, r *http.Request) { + files := renderer.ThemeConfig.GetStringSlice("views.administration.create_group.files") + state := NewState(r, renderer.ThemeConfig, administrationMenu) + + renderer.Render("administration", w, r, files, state) +} + +func (renderer *Renderer) AdministrationGroupDisplay(w http.ResponseWriter, r *http.Request, group any) { + files := renderer.ThemeConfig.GetStringSlice("views.administration.display_group.files") + state := NewState(r, renderer.ThemeConfig, administrationMenu) + state.ViewState = map[string]any{ + "group": group, + } + + renderer.Render("administration", w, r, files, state) +} diff --git a/renderer/auth.go b/renderer/auth.go new file mode 100644 index 0000000..deb7058 --- /dev/null +++ b/renderer/auth.go @@ -0,0 +1,13 @@ +package renderer + +import "net/http" + +func (renderer *Renderer) AuthGroups(w http.ResponseWriter, r *http.Request, groups []any) { + files := renderer.ThemeConfig.GetStringSlice("views.auth.groups.files") + state := NewState(r, renderer.ThemeConfig, "") + state.ViewState = map[string]any{ + "groups": groups, + } + + renderer.RenderNoLayout("groups switch", w, r, files, state) +} diff --git a/renderer/beneficiaries.go b/renderer/beneficiaries.go new file mode 100644 index 0000000..20d5fe0 --- /dev/null +++ b/renderer/beneficiaries.go @@ -0,0 +1,67 @@ +package renderer + +import ( + "encoding/json" + "html/template" + "net/http" +) + +const beneficiariesMenu = "beneficiaries" + +type BeneficiariesListState struct { + Count int `json:"count"` + CacheId string `json:"cache_id"` + Beneficiaries []any `json:"beneficiaries"` +} + +func (s BeneficiariesListState) JSON() template.JS { + result, _ := json.Marshal(s) + return template.JS(result) +} + +func (s BeneficiariesListState) JSONWithLimits(a int, b int) template.JS { + if b < len(s.Beneficiaries) { + s.Beneficiaries = s.Beneficiaries[a:b] + } + return s.JSON() +} + +func (renderer *Renderer) BeneficiariesList(w http.ResponseWriter, r *http.Request, accounts []any, cacheid string) { + files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.list.files") + + state := NewState(r, renderer.ThemeConfig, beneficiariesMenu) + state.ViewState = BeneficiariesListState{ + Count: len(accounts), + CacheId: cacheid, + Beneficiaries: accounts, + } + + renderer.Render("beneficiaries_list", w, r, files, state) +} + +func (renderer *Renderer) BeneficiaryCreate(w http.ResponseWriter, r *http.Request) { + files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.create.files") + state := NewState(r, renderer.ThemeConfig, beneficiariesMenu) + + renderer.Render("beneficiaries_create", w, r, files, state) +} + +type BeneficiariesDisplayState struct { + Beneficiary any +} + +func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any) { + files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files") + state := NewState(r, renderer.ThemeConfig, beneficiariesMenu) + state.ViewState = beneficiary + + renderer.Render("beneficiaries_display", w, r, files, state) +} + +func (renderer *Renderer) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request, beneficiary any) { + files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.update.files") + state := NewState(r, renderer.ThemeConfig, beneficiariesMenu) + state.ViewState = beneficiary + + renderer.Render("beneficiaries_update", w, r, files, state) +} diff --git a/renderer/dashboard.go b/renderer/dashboard.go new file mode 100644 index 0000000..31ad9a8 --- /dev/null +++ b/renderer/dashboard.go @@ -0,0 +1,20 @@ +package renderer + +import ( + "net/http" +) + +const dashboardMenu = "dashboard" + +func (renderer *Renderer) Dashboard(w http.ResponseWriter, r *http.Request, accounts []any, nbaccounts int) { + files := renderer.ThemeConfig.GetStringSlice("views.dashboard.files") + state := NewState(r, renderer.ThemeConfig, dashboardMenu) + state.ViewState = map[string]any{ + "beneficiaries": map[string]any{ + "count": nbaccounts, + "latest": accounts, + }, + } + + renderer.Render("dashboard", w, r, files, state) +} diff --git a/renderer/func-maps.go b/renderer/func-maps.go new file mode 100644 index 0000000..1b062c3 --- /dev/null +++ b/renderer/func-maps.go @@ -0,0 +1,77 @@ +package renderer + +import ( + "fmt" + "time" +) + +func TimeFrom(d any) *time.Time { + + if date, ok := d.(time.Time); ok { + return &date + } else if date, ok := d.(string); ok { + datetime, err := time.Parse("2006-01-02T15:04:05Z", date) + if err != nil { + panic(err) + } + return &datetime + } + return nil +} + +func GenderISO5218(d any) string { + if date, ok := d.(string); ok { + switch date { + case "0": + return "Inconnu" + case "1": + return "Masculin" + case "2": + return "Féminin" + case "9": + return "Sans objet" + } + } + if date, ok := d.(int64); ok { + switch date { + case 0: + return "Inconnu" + case 1: + return "Masculin" + case 2: + return "Féminin" + case 9: + return "Sans objet" + } + } + return "" +} + +func Dict(v ...interface{}) map[string]interface{} { + dict := map[string]interface{}{} + lenv := len(v) + for i := 0; i < lenv; i += 2 { + key := strval(v[i]) + if i+1 >= lenv { + dict[key] = "" + continue + } + dict[key] = v[i+1] + } + return dict +} + +func strval(v interface{}) string { + switch v := v.(type) { + case string: + return v + case []byte: + return string(v) + case error: + return v.Error() + case fmt.Stringer: + return v.String() + default: + return fmt.Sprintf("%v", v) + } +} diff --git a/renderer/layout.go b/renderer/layout.go new file mode 100644 index 0000000..27ecffc --- /dev/null +++ b/renderer/layout.go @@ -0,0 +1,18 @@ +package renderer + +type LayoutState struct { + AdministrationState AdministrationState + MenuItems []MenuItem +} + +type MenuItem struct { + Title string + Link string + Active bool + Icon string +} + +type AdministrationState struct { + Display bool + Active bool +} diff --git a/renderer/renderer.go b/renderer/renderer.go new file mode 100644 index 0000000..7673bbc --- /dev/null +++ b/renderer/renderer.go @@ -0,0 +1,184 @@ +package renderer + +import ( + "fmt" + "html/template" + "net/http" + + "git.coopgo.io/coopgo-apps/parcoursmob/utils/icons" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" + "git.coopgo.io/coopgo-platform/groups-management/storage" + "github.com/spf13/viper" +) + +type Renderer struct { + TemplatesDir string + GlobalConfig *viper.Viper + ThemeConfig *viper.Viper +} + +func NewRenderer(global *viper.Viper, templates_dir string) *Renderer { + theme := viper.New() + theme.SetConfigName("config") + theme.AddConfigPath(templates_dir) + err := theme.ReadInConfig() + if err != nil { + panic(fmt.Errorf("fatal error config file: %w", err)) + } + return &Renderer{ + TemplatesDir: templates_dir, + GlobalConfig: global, + ThemeConfig: theme, + } +} + +func (renderer *Renderer) Render(name string, w http.ResponseWriter, r *http.Request, files []string, state RenderState) { + genericFiles := renderer.ThemeConfig.GetStringSlice("views.generic.files") + + prefixed_files := []string{} + for _, f := range genericFiles { + prefixed_files = append(prefixed_files, renderer.templateFile(f)) + } + for _, f := range files { + prefixed_files = append(prefixed_files, renderer.templateFile(f)) + } + + w.WriteHeader(http.StatusOK) + t := template.New(name).Funcs( + template.FuncMap{ + "timeFrom": TimeFrom, + "genderISO5218": GenderISO5218, + "dict": Dict, + }, + ) + t = template.Must(t.ParseFiles(prefixed_files...)) + err := t.ExecuteTemplate(w, "main", state) + if err != nil { + fmt.Println(err) + } +} + +func (renderer *Renderer) RenderNoLayout(name string, w http.ResponseWriter, r *http.Request, files []string, state RenderState) { + prefixed_files := []string{} + for _, f := range files { + prefixed_files = append(prefixed_files, renderer.templateFile(f)) + } + + w.WriteHeader(http.StatusOK) + t := template.New(name).Funcs( + template.FuncMap{ + "timeFrom": TimeFrom, + "genderISO5218": GenderISO5218, + "dict": Dict, + }, + ) + + t = template.Must(t.ParseFiles(prefixed_files...)) + err := t.ExecuteTemplate(w, "main", state) + if err != nil { + fmt.Println(err) + } +} + +func (r *Renderer) templateFile(file string) string { + return r.TemplatesDir + file +} + +type RenderState struct { + icons.IconSet + LayoutState + Group any + Roles any + ViewState any // This is a state specific to a given view +} + +func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) RenderState { + iconset := themeConfig.GetStringMapString("icons.svg") + // Get State elements from Request + + g := r.Context().Value(identification.GroupKey) + if g == nil { + return RenderState{ + IconSet: icons.NewIconSet(iconset), + LayoutState: LayoutState{}, + } + } + + var roles map[string]any + + ro, ok := r.Context().Value(identification.RolesKey).(map[string]any) + if ok { + roles = ro + } + + group := g.(storage.Group) + + modules := group.Data["modules"].(map[string]any) + + ls := LayoutState{ + AdministrationState: AdministrationState{ + Display: modules["administration"].(bool), + Active: menuState == administrationMenu, + }, + MenuItems: []MenuItem{ + { + Title: "Tableau de bord", + Link: "/app/", + Active: menuState == "dashboard", + Icon: "hero:outline/home", + }, + }, + } + + if modules["beneficiaries"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Bénéficiaires", + Link: "/app/beneficiaries/", + Active: menuState == "beneficiaries", + Icon: "hero:outline/user-group", + }) + } + + if modules["journeys"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Déplacements", + Link: "/app/journeys/", + Active: menuState == "journeys", + Icon: "hero:outline/user-group", + }) + } + + if modules["vehicles"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Véhicules", + Link: "/app/vehicles/", + Active: menuState == "vehicles", + Icon: "hero:outline/user-group", + }) + } + + if modules["vehicles_management"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Gestion des véhicules", + Link: "/app/vehicles-management/", + Active: menuState == "vehicles_management", + Icon: "hero:outline/user-group", + }) + } + + if modules["events"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Dispositifs", + Link: "/app/events/", + Active: menuState == "events", + Icon: "hero:outline/user-group", + }) + } + + return RenderState{ + IconSet: icons.NewIconSet(iconset), + Group: group, + Roles: roles, + LayoutState: ls, + } +} diff --git a/renderer/vehicle-management.go b/renderer/vehicle-management.go new file mode 100644 index 0000000..36c4ffd --- /dev/null +++ b/renderer/vehicle-management.go @@ -0,0 +1,19 @@ +package renderer + +import "net/http" + +const vehiclesmanagementMenu = "vehicles_management" + +func (renderer *Renderer) VehiclesManagementOverview(w http.ResponseWriter, r *http.Request) { + files := renderer.ThemeConfig.GetStringSlice("views.vehicles_management.overview.files") + state := NewState(r, renderer.ThemeConfig, vehiclesmanagementMenu) + + renderer.Render("fleet", w, r, files, state) +} + +func (renderer *Renderer) VehiclesFleetAdd(w http.ResponseWriter, r *http.Request) { + files := renderer.ThemeConfig.GetStringSlice("views.vehicles_management.fleet_add.files") + state := NewState(r, renderer.ThemeConfig, vehiclesmanagementMenu) + + renderer.Render("fleet", w, r, files, state) +} diff --git a/services/groupsmanagement.go b/services/groupsmanagement.go new file mode 100644 index 0000000..f5bf047 --- /dev/null +++ b/services/groupsmanagement.go @@ -0,0 +1,23 @@ +package services + +import ( + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + "google.golang.org/grpc" +) + +type GroupsManagementService struct { + groupsmanagement.GroupsManagementClient +} + +func NewGroupsManagementService(groupsManagementDial string) (*GroupsManagementService, error) { + groupsManagementConn, err := grpc.Dial(groupsManagementDial, grpc.WithInsecure()) + + client := groupsmanagement.NewGroupsManagementClient(groupsManagementConn) + if err != nil { + return nil, err + } + + return &GroupsManagementService{ + GroupsManagementClient: client, + }, nil +} diff --git a/services/mobilityaccounts.go b/services/mobilityaccounts.go new file mode 100644 index 0000000..e67591e --- /dev/null +++ b/services/mobilityaccounts.go @@ -0,0 +1,23 @@ +package services + +import ( + mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" + "google.golang.org/grpc" +) + +type MobilityAccountService struct { + mobilityaccounts.MobilityAccountsClient +} + +func NewMobilityAccountService(mobilityAccountsDial string) (*MobilityAccountService, error) { + mobilityAccountsConn, err := grpc.Dial(mobilityAccountsDial, grpc.WithInsecure()) + + client := mobilityaccounts.NewMobilityAccountsClient(mobilityAccountsConn) + if err != nil { + return nil, err + } + + return &MobilityAccountService{ + MobilityAccountsClient: client, + }, nil +} diff --git a/services/services.go b/services/services.go new file mode 100644 index 0000000..ac6be54 --- /dev/null +++ b/services/services.go @@ -0,0 +1,39 @@ +package services + +import ( + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" + "github.com/spf13/viper" +) + +type ServicesHandler struct { + GRPC GRPCServices +} + +type GRPCServices struct { + MobilityAccounts mobilityaccounts.MobilityAccountsClient + GroupsManagement groupsmanagement.GroupsManagementClient +} + +func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) { + var ( + mobilityAccountsDial = cfg.GetString("services.grpc.mobilityaccounts.dial") + groupsManagementDial = cfg.GetString("services.grpc.groupsmanagement.dial") + ) + mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial) + if err != nil { + return nil, err + } + + groupsManagement, err := NewGroupsManagementService(groupsManagementDial) + if err != nil { + return nil, err + } + + return &ServicesHandler{ + GRPC: GRPCServices{ + MobilityAccounts: mobilityAccounts, + GroupsManagement: groupsManagement, + }, + }, nil +} diff --git a/themes/default/README.md b/themes/default/README.md new file mode 100644 index 0000000..660575e --- /dev/null +++ b/themes/default/README.md @@ -0,0 +1,24 @@ +# PARCOURSMOB default template + +This theme uses : + +- [TailwindCSS](https://tailwindcss.com/) as CSS framework and [Tailwind UI components](https://tailwindui.com/) +- [AlpineJS](https://alpinejs.dev/) lightweight Javascript framework + +## TailwindCSS + +Look at the [Tailwind CSS docs](https://tailwindcss.com/docs/installation) to know how to install and use Tailwind. + +If you installed the Tailwind CLI, run this command from this repository while developing. + +``` +npx tailwind -i ./assets/css/main.css -o public/css/main.css --watch +``` + +## Esbuild + +To bundle Javascript with esbuild : + +``` +npx esbuild assets/js/main.js --bundle --outfile=public/js/main.js +``` \ No newline at end of file diff --git a/themes/default/assets/css/main.css b/themes/default/assets/css/main.css new file mode 100644 index 0000000..15ab027 --- /dev/null +++ b/themes/default/assets/css/main.css @@ -0,0 +1,19 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@font-face { + font-family: "Manometer"; + src: url("https://coopgo.fr/fonts/manometer.woff2") format("woff2"), url("/fonts/manometer.woff") format("woff"); } + +@font-face { + font-family: "Bitter"; + font-style: normal; + src: url("https://coopgo.fr/fonts/Bitter-Regular.woff") format("woff"); } + + +@layer base { + html { + font-family: Bitter, serif; + } +} \ No newline at end of file diff --git a/themes/default/assets/js/main.js b/themes/default/assets/js/main.js new file mode 100644 index 0000000..0b0b059 --- /dev/null +++ b/themes/default/assets/js/main.js @@ -0,0 +1,6 @@ +import '@kingshott/iodine'; +import Alpine from 'alpinejs' + +window.Alpine = Alpine + +Alpine.start() \ No newline at end of file diff --git a/themes/default/fonts/bitter.ttf b/themes/default/fonts/bitter.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3b66905adfd60bb56d8abf34c21d6324f5b01222 GIT binary patch literal 90628 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�dk|cH2cdcz(yKi`S-`cj$4OcC`wPK)Z z!MdKFjf>*(MH_o|)iyL7?Owbnm=kN*(2$jzlb;=GXh@V*Cx5l}*5SQt+grvi8{%1i zdw5UZhDFu!MH_ng@XR$0*+0#y^>j85M+-xP*$orHNRDS?c7rb7RvPV~tZ8uW*L}__ zkToI78ptf!LrBDwh^I({&Ufw~r4QYuKdX1+UM?a2TO;LiNZ8L9Bc4gom{0%-QtpL7 zzBJ%VSYH z6E1OaAoD-u8Sa3B*;`eMLkj%3w**I{JQG45k)&0MM^;Y<4el6RueyI-HW6*?k1yL0 zZJb|S*WTRJ)ZDH=JGLy|UthFlS$tk&(QB>EOeFHXFO|Meeq+nQs?)_nA%GcT@LgE3EF3$+WKe?HHD~iVQzDiWMc=mt0gS+4Wg;%} zcCNcJ#uZkp;Xizu57gm>j$lGO^$ouhf}JTSrWoI(V~~e}cfM63ojY+6vvmpDQCu#} zPrNPi%J-k+zDou?D+WKhYVWf%|J*p(SXi2!nLQe-bmm`Pda!@f#^uZ6U5Q|6FsCp& zfH@u&)*-zbW026_Wo!`gjw==)#UXA4H~oFZ{NOS|SJ0Ydc2U?~a9u8jNUuF2^$8YWeNO~hqX<{?E z+8EUww8WnnG~l(JVjC6)M^C;|En7XokgvcCNzUwVcOvP-~b$wNHQZ|W_H?80*!9Qjwl~8K>?YdfJ{&T^7uLW zT*3hQ<>2RmPV#V99`4G+U3s_*#4qOd+o{KWR&=Nz#!x17WG4K#On8^9+0Y3^ex){x zOA!Zx*y-)T{4P(4xNqD1jPc>cW0Q6Br^l+7g$lz1-4|Zi*tUM8vCJ9V8=BX)p)jMT zc6f2f?;offoWF3W#}AZ(el}tMu4SGjklWiJA;`mfU6G+Ea52Y5iqfDcnVjL`7;$pB zk(UN(Nhvq-(lpdyFKggk1Mf&3Bu*sZ1Gx53N+Wcxmp$8X!ukD8$s^|dTyJrJIjjnU zQ4ET4bIOZ}$vKmM%wHu1ykpAhpim=jHz})z#F&>#34>nDO+rW~-JFw~I(O3}a!zsIcp2H^?_J3pr*Ke&QQYXjxG&jt`_A z&-on3)JN3PbD1XaYSaxiiE(A@%rPe^P3njbA#41HHp^7+0`2rpY#jT$O)IxuF@4DS zLNfg3&pkzN{v6-dxhHGy+I3f$aUI0BZ~j?d2PxY~4Ue&*XO1!TLdKZsc^bBUYb9iY zK9ba~5Q&V*9jZ*!RaPbHepVY#)YT%}0|a%&Y^@$eJ;mI!P*%KC&4_G3Rdk2w$2DdspiK$D2li_Rn6I=ZDC6qdmW zbz3?2!-S&0Q+sO;30E@FhuVsk05^#IKeW9IfL~R0?|;s3W`6JY`!SE-yeE%&B$H&4 z5J)D#5E3*I2touxNJ0__Nz4QAfdV2Zas_TJirUJ**V~8p-omxitJJ^R>c8!^tx(^! zt=igpE%nt_TSb}tKi{>_nVEp?ZTr9flbkvGx6eNNvG&?)t-bczYwK)Xaa4-@55`l- zoL5OrJmD$R1zB?y{O$99zxT-CJGcAS%+BHpb<^JYUr=vsLQnD==t(4p_4&WKWS5+6 zd=neE!Nd;&GN#n{lQnkUwaQ4NwT~iup5>-Js#!1L-UW?FV7<7Y5plluoc2OHL_Z1KP1J8Lgckm|36vXrb5*<>!ks=tBdkxat zTeuB)XxcQ;8z5+_~s7=c>VK_svZ+1mXBNkxoZ3OOfbx^EPdZmq$*7o5@l8hor z20w16R`-WByMtQ2#nnvv3MAc9&}#`i;HoIMDZ!RDNt#Cck}jZhS<(fYT;CN|_%W;S zxjWv5wY4=6N_`}^O+C|>thoBR*6K@EymFsEuy$%<vUNTCubbGh zw&#X}n`dV?Z{D(H{;%fdG=9(3yL=o{Ags>2iia*MKwgHL`O>7rg~&cnNtYbtCh;$j z=GqE?Izo9TdrIfxOXuQ71E6RFSaIgpw-WCguleqeIT|k z`ZKL+iLB~uLA$9v-4WF5jX$Gar#V^bZ@g_3s`^-=yA)VBm+OCD;G&lm6-HTuz~B*N z$`S7j_Ev(y-vltoQP$mo&g7wx>3%N^d^`+%-?j)*rzr&lk@q17S>>h_02x*+K;#?= zUAC`Sfyr!U5h9a{m~;?XYY>TevuCIM2P3ipTj70Ja^R4Y96W+nkY{y}EYCaR%`!_1 z$uAfxzbXlYl?1)1$({^!1b9ge68lyJn>6^Uk2|y&vzby~pt&mZbZ1M;$za_U8J8jG zY2&s8MIE?1z}#^FOwoSHdN}V_6m|tmEYD&yHm8)^AZIDZveX3Yd>2HR7x=w_O|A51(zD(wNz!io>J_q!*S#4dS;=_n~&Y;-NZ_rM)Aj~+cVt3D5l2xUMH~&LkGl_ zdqwvqF{Yp~a^&4hhxb~Qu`saB0&cX( zPD~`Ye_^OE6>m%`TWa?%$pQ1tE?_7D%DBB?Fa9gDca2S%eMmnqBY07GZCA)5fVXI( zGbe6ga+kAoG7Tw^M)}HFl%5UE^4~)Ptk&0tfgLU&RZ)XA68ZTIBpI3@?lNdPrUdVO zEtP5co;4I)rf7lWXUyjm8H3WrnEJWH5)4%&tx$3dsUwC5{umZaY*$tf$r#G&Bx@)F zvSY6!w$z23F?6nV7ANtV#BFM+jRZnx`b2agAJjP_(UQw=8Kg+ru5f`a258;;TYIe$ zr0Uz~w1r9y(@Q~Ai;>M7pC-&`?lFGIX6_^0)_^<0{Ju=!Tb3V5HxRg#`xs^}3PypN?KX z|DDVKYW9{RpLxejy^sGLt?4c2t+>4Bg-1)9HkFPa*WbwD?sv_9E|R-opyvXpt;Su) zo8Xt-Ufcf*AqaxAtV!Qz_(Wi@0&4nZ3%GtZvy-1kLNn-XcLC{ll1O^Ng3}Mf*RpZ( zU#)2r+x=wKuN_HdwdfRz>-0k<{38L&Q0hi2Q%WS!7|le?W71nqv~ovk*%$5b3j%J> zK%3m#4jtr%aUJ&@w{2j0GXX21q5ygkoy{YMGvxJk8k+-BJk5s#S)UQHKr ziSd;gOzh1G%(-OlE&JdGu|4GMmP|DudKacF!IsZOZXFo=Gt*M08nH4*>Sa{ANpmkF z6wnhd10Ct_B;<*`NxT!P@_YQ9l7rKgd+S?rn>5~MJ2mGzZYw=`vzGauwdDzJhOIBp?dq`)4eT z4`duD`@umz)N|PAVh0>I&@Ad?VMD~RFtEV|M9{_|XyXEvM$R}a#ePUCViS-6sMDVb z=ybJJ#I8abUj@Ar$r=kw7;^$i7i&W+S=-TCmwg$O8x$u~)*z-81`bi46%%&>P2#3t zDpM|tF3PgkBVnLsftR>#&SLj&vf5yDB-F&Q5oPgcz&<~6#g5jx?Kd4gb7OUSYAn+n zD^9H4*t@&fJ5+4X)N;+K*7_C055ITv>es!jHnVmz*Y^MRWcfedf8Ran0ne-Y#J_UlZxm0N6=DEJ!2E zR!iEUV7JQ!VmSJbqMVP~I*Rf5E&R~ih$eU1vt*i$)Gti*(a47yn z7&vYLa-+7AJZ+7L!ELS(co-zL2NIP9ghA99#XliYDoy5#K-tG88vCCPkzW*=!yEzP zuX@8hV-IY4pc|uFOcHiSzI)wu<9Br3`9gn4X*ZQ$_$zRx0{nJ$2xna1-2C6~^zJ~Y zbMko>`8?2j>@=9uYY&G3J6#MW+7h}Ll0D&2O6XDpU23$xM(Z)67LCx409|UJOMvxH zDwa;r-WPx&y#Gz)h6+3i_xkBg<>&o@&+UBv zEpL6`Zg7op9r=fjH-c;EIs6#zpl|lxyr@7L^ux_IM^#7R)F>S> z3L1@qQ=<;2P7tsbJZXV|-f~98|1kQ&eA|yMLp(n$@!xs42-`$4beZcFd zuXiGTQA`*0>VbmV0+%L9ie37x=(WmZZvE;5-ZDPWGgq(6+yv?D+ErM+_JPxja^sf&3D+`+E(IrQMVhyih8OjBV)NnD#k4f zb9g~@1gMTswGj##2}i1?@YH@UF~_+L*`6ezkvi=NyX>19k#7IT(5C-@ASrqX-b$o4 zg8DF&QcILL-!L7ywB?{F1L$eSx!VvgMWb5_mS{`mw1?1~<~(e)PbvLi!=*M_*hJcL zkmfyNgHdzP81H0%plLPh=QFjLnzoCeec!bH!ygX+`@bEAh=TTSI{QxWq`-Ip0+FAW z)E?L=;&xI1kS39UI$lb>8@LTa;eSXi`r(wG(!1JjxZ_r9zUw0=%iwzoi26Na0X2wH zs3uYWORX~qxhRA_+L9r&3^Hhz58Qrt9p9{w3e%P~NvnB6Lq?YB#7My=sTF_YF6*oK zp{(1%OG>-O__EBLT&j?A1>RH_rPM|K1tp?FP9vh4yKVOZwF@}~fD{2~t1y-uR*@P= z>vqX%b1LF76&4diTY*wTN;qv-p-!4Y8+4uv1DeCC;v%*KmRUPUu9^oQ%00*k8%~6n zQu8e_l!iOI95suwtgkjaBn>)U7ZVEuLVxSsCV}PLhUfKA)a8V5_rbC-@MSWwOy>-~ zWO}vH00P?#yaZn94U$HKmSqu_T0TVVvxOtR8(|gX5Q0}Sg(;DFi8f)RDunsGm4*GH zlXb(5Pdfd&&-Yn>#_UB05ERO_$Q82}9pW_mORqeC$L!Ai6T9!&zH4iA{s+r89lUkl z%JcqcSw~^;)z?39)!X*3>%DXEO?!Uliu?DjY2Q14Ve`Q^-TRv6{C8e=iRrkZKi@UF zxqb=VOi`D%x=xhN=#-t?x+L9g-d{r}mCl@)zbKt(qRa0Y7I0j;XANrS<|jJl(%tOc zLrGa$ zSQ2MxA>l&aa1L_Y$a!;!=US|@ga@tjkR43ZZl-bzLTV^XeDlcB*S__xIqmaXe1-j57e;Q7Y_-)vey`gzq$$!? z0JIgP}7;H6$)-LN?+22SFt*Q@Jk{hO8 z_*Hk947AM7+s@j=0+mFHIl$=|cK1Jm-1KNp;o%R`hW>Bzn2i$mU(F#94K#3JvQY`O!iiH=_V+ zqZiX)dd6X<1hExXv}CXKj)uFsu37l*bFXAf+jr8St)R|MZMVq;SGR|(jZd|45P56l zYHg`%iiX5UNr~K;)H;gyECDbjMnydsfyeC8-e}6wgxxhA(&;oiL#PuLkShbW-5DvE zQ0-0ah^ksnlB9E#y@n>Yo+n?=PJAj#TIZMK9J00e5vb4Lvra9ri7%FuW|O_qscfq) zH#s6XpAf~g>G;K!=P}WWu_edktW?CxB@uZ=*H{n{;UL-*l zoW3$3KgErc9P(>9x6oZFJq(gh}}t(7$E zT-ioS;9SOSjBX2R6;HAEINT{C@1*Gqy&9 z%rbu)g#}#o0aCNl1UUUN2+h=0^tGA49TR6C}>*y=*7}|2+v-20u z?U)^JHCFc5qOtvUK9|30?cxbt-Q71Qh6bDAagKM6&CSh!dSv;^p<<&EPkcbfcEMA} zuBf*bssm+0AdnMR#PKO6=;1vE2yGK_IrcVhBkj1=;kZc3wWikO}Bn1M5Ifl%wN zv9MI@-sJ5Dhuxsh3e;dywCix0f#7NSb+ZPLp+cZvU$iLv*XY-U!Yjx!PnLR0D$_}Y zQmO0dRO;uPN~lBWR)XX!VU#N!f@}+Q)O#!-yjbu@bu)>qwfe#WmxX~V!_VAynV+fJ zUSbLdO2|9&IjZfK98#EFHaS%un=Et>6}K+W*2jA{j1S*>{GU6rFx{-?BSY~C6ya4F z(N&h!x-W^p{dJoT24@&bPowkkjE`&sHKLyQi0lMTm<&PSVGB52?Kx@1PaX;Q$yrbH zppc)qJd4n1m*-EDU-j0L)k8)R2<%lrh_yM4F=C;Z<6%tR0*mDuuW?oChCE~;)^0U3c!D36dP^91BAf*3 zxF(T1nSr|Lzwnc9+T;S&5raV77tX)Lx#gl2tu{FdyQPf~Q@~(QOyO);%Ul@vgaw?6 zTr&cx%FU|VCNB)!6aZU1#{-{(QZN679WHeCu6xHG-1MMawT2FwcN{%Bet*}4vyiuAh6JIG1CAP!Ib>O5(qebf^$>qDrblBZZT@@l(9g>Tw(niAwpqV zDb{B88@NqgoC;;ZuZMvx3IGM^KC}V88xScxa1K<0Gsk2rJ2-I8W_AatRJfDJNRtx! zqt{wy6Dh(+zR*fE-(SfOwN*BLp`NE0e8B5#0>)nBDLWLRUM10-74EX0My#Ff3X~Kb zQ1?QtCOhcKz(=iaqgY(}!VzXjYnfHdh9>ZN1n%2r#k6Z!GhGc=l&aDx#Mb(MK7WGj##=E8~k zRT^4?_a$NA>TsHIDJlee^{Oy%saw{PN+_@-T{tCSn^jHRVq2K?f_m!GFzdrEYn_Fg zpa%j~|0UsK*~R24ue*l5yF&?Qci8&5FmMUdh*j)jgB3n>3hr12w}YxSVxDwHXR5WC zB`4&4>H1$B+IsDV6K@>YvS-7^>xM3S)7a7RwY{&n@WlO(T)b`Dg^@2!KQ#Y?3l44@ zd(#^>@4t9>`GE`OW;Qkoo6F12pMU>HcJICRx~Bq~8F`(}2VTKgk9uF2#4)kS(L>15 zL$DAG21EMFe7gFM--x`Y-{p6UU#Hq!-Wm`GDv2S(}&e9MXyB zxO{)w`&Dlo*l!N8=(r1{s7<%`IJcGsKEeGgch^$h#aSkr+qitb!1#0gFp&CRTsPxO zF73@&v39dYrda?S%8g@Fr-ATeVoV+0YTB7RNTU3S$@=^ zNc!E9se!zIX+NGeT+5oH!L!Jn#x9_1i8X)6lCZq+_-lIxhkKUX^Iwm|lX9~++}|GY z-yMdY*d;15j-I?0c{R1`^@bxC%5E*N=6Tp?jDa*DKMQo|MEI&526jmar9t#?7)yp&d%H+f>^8=G3$du?nBb<%jY489T-atBFh5mg@i9cAga zuX~7b$M*~_goa43x766JE&*`k!2tnVlsgyA=p03I)_pp&&Cwj0zR8p(1trP^u{v8| zsq#=(FnQxw_y+PiE#;sC5Yk`>hT@z}Wcep?o^u=vovaxg3 z&!im}hqU9WMUtT{!6HvV&Qi2TQM98~S23@2`G^b#l!pNC!giXh(JR#oI?Nyng+D$cl5)6ueJ97#QSW}hRJ}SQYnze&fV$I z4&D)ei&UAYd?kCFb;>-=?o6vEb+`g}9KgMXEMN$oph97)}^B z5Mr{iz~lq6^vaOr1gFn5Ox0#EIzlJ%TOX=pj;IFa1NNkdenyQKuvl3%~s(>;xfr6;hg zTgLYzf5j7S!O;8g}0~S?R>R|EDr=gxJg3YCU zP+ll!@Jp6s>NI0@+H_A+zoFy^P$(Hv zkL6*Y4He4*0ZuN-zbkKizB5K7c>S26B{eLUjFhW zx}`l=Uw@`Bw`21#TMzr2n`YAOfxc9=7Mn~ZCRg-Mv`bx)xm}AorAw}ye`a-g*XXj* zW$7X_D|84${`bJEWq6aFR!`I&UOi6GhRi2iAOV8)(cyj2j6P^apHl$l30Sh7d}slk zo1)o(&l~5bPCK3p>Q&?VGTTH33H)zKAPUj2BpzjHoF_V=>v9lITSkISCJT5L9L2YY zXNzZzf@h$V4>^&PFv`IdT?~}in?{^Xlcdy7Zq~1y>@7J&$`bB zTEww-a{go4ed==D0>>u*Di;TNP3wDS@CRFJ(IcLaC(yj9rs>J~SRzY|& z3v1bDVe4YHe}DT(<(L1cJU8FkeP!hc>#32WUzyvn>pQ1DxvBiyV>?#+Q7xuAc*-vG z06f3o_x%>-c2eKqJRK?lTvWJ}Nd`4{nvS#Y$r71a*j2LVT|R)=;sjqHi5m|9?vL@q zhVq|;ftfIXAqTJAiim_~QqP6m`afMj#{FrQqXP#B(eU+$ETB%4&-xI?Zb|%H7&~u( zlCPPu(_>x0HO1F~D&$@KP#rjH#&fGLQlhEbgqwicomv(E`aAo}x9fb{>no>p0QnP> zJ2uS!KpL@cjBlUuSJ)Yto6i2E;}-Vu!TtP)lyTsxTsD;kh$#hRp&(PrJhyR)XCyC) zU3@PL>{Y;}>nEM$DiJ#}G)koDq8+32m?;$;>A}4QZIoeDoDbaQ9Jy~1Z`ABaY!`P6 z(%1#du#*ai=nyaGC3lC(t~L(9HJ38;a(gU0Uj(yESf+Dh_Q6NNwYZZUzIt6 z^p@rT+Vnisn(^ZLNSYbCg_da9Nn6X+Dah)?$S$&N-6IR21$Ra*mcI>rb?Ksz+_VX> zXzvZYRg3m(!{=;L=#M$-TAN@srjVbW@$Y`r-#**;(l@{P&GPL0FFpQ_UzoV^jz?<4 zxj*{k?#OR7q5rEQy&B=HD`|ak zCxN}(#}%O|QRr5Vn#mGD256m9o0)l;?c;w8R?>wm#I{~psFQwIsg8l_AeH{qTMbWS<4V1%|Ez8ZaS{ zpX-3v$Cwk_l%W=|`oG%zx{#}nwo~Q7fekMkf76Bw?>Tj+mV9o%`;iA9x#+*TRluhX zFL3qDn(pq_p+j$Zla5{8^~q0idguMN@~1iS+}R&S8Xdm`FxSyh7`*o%^Y&BQoigtb zAa1aL#MKkF3<}~tL*Q%NAg;WR%mVdUr1n`pngzvYo%fL^2v`nscxn{v>jb{fEyF#P zZRa|66e;^ESN30g)$9x&vc*IdIfWt3;yRME*OIN6?6sKlu*c!Jq<^cgb%iQdqjG_v zk8FCx&4$F$|Ih4dpx&$rMK*W*67@LW)qBM;?-dS0fj`w}AUa>;4j@znLPa1{1VTk1 zR16^$cwx&E6F{g4g!ElFho7Z{FPa|nI#*WwtKO)!H=uNVB6*_R?r>ZOHRY=u{Ij1r zyWW34_EIhH_kN2}q`hg{AtCmzeg1k%Ue;6F`L)3_T!qpm&Jw?i+zOi)aGuguX;R&i zn~5@mxXEqeQm~)iX7!pS`8F;!#u>;&F>xn;59Gw}|#Yxr+_^IOLr+4M-{ z0k<{7)nga_fPT~JaXqjSRv$N}PT+kOAY*auEtF)u*!-O=XldR^@7jQSUl`bB0aqod zLe$e%3nZFB`~gKD9DHQcyOu|O_t^M@56U;1@9l~l^$#N#mOZdU25{!-lJ8P{pB7w1 zw&iqL(xDiMytw!?w!FZe`57EwtAqTNn`)!eJw4OIl})K~cX4>QEAm2D|IApmI=Z&6 zE7`2&2fEte&k1pV)(9;u}NHIsNgR0J;!VG;f2Mt1^>{3TZB4a!5Zxv#!a{P z#h~LJG8h3Yb&E(q=qFk}?Ii5iRZc-b?voU+5tLIvH1F$S;1d>*I8H2H5G*InEj1Rj zVyg|15W(ftVsi)lE$_{r zaC>uQKRM)cd?TcwPqLQlU$vwpcxW!HLzU#$ug_o5ENu3t-Hi16$>L~f{JdiSKqkGX zXJtFrC_grtNUfTvF6a1?u0T;BJlYE`|7ql>(49Y_46-y=NH|FoE(fIRjbUIa41C=J z4q>HZDp4^UENKU3C-4uPemp@yT`Fr>Cp-wbL$c-E#yK%SP6#9Pj_twHrtmxf&jawh z6Tx&??g%$@ItHt$LUgK3!dW>$c2rEBm^?9-{>4d3qmUrX1I?Qhb9On6(CJF|3>G&H zlt)*OW$Nu%e6X|JJy0o3PK{)0L-EM#2A8i%m$Q{raxmT7pUafeekBFEP{-ZCY`)`i zq{x^?p9Y$FcmdZm&^pyaa=oOHCxWd>Vuy$d^S>N^R{Z&=#{ct!+#Q8SSO4c(ZkI1} zy~uqLSsur||0anP$2tKIh&gwvLTq|wcYxsnXIyXg@P)m()B=*;FzmF6hiVj(0P=Q& z*SJ97bci{!w%1C!*U{c?|FSj>cRWjCo>7%>Em>L#J6u3!T2TgoRvqw4K(LRkXEgH->Rw5(&{C3L9hQ7Dn70I*{=|t=bmY33>4^@v{OgEFY^E|eb3w<9opfaSK^<~5 zID2pRWPfS=6{jxQ_Ue}{D-BL|-*?teHCy#WvFDcSuRk_8IhFO#?y7Ize);m9ckP*) zy!!Q*t+?{Ct&Pszvt8v@JJ)yX);sUH^PZO<-!>9OdI7lFGw=}lB=#E)FP^fDV>8<> z9xIe18|y=jnc2zBf3$b^Q~uq%FG{Z-yXa+T$vGQDDvR9w)8~_q$JX#4__qR#VMnGk z7=)|pUJZy2Q`|5mlHf75s-V@*ANV~iWLiD=zT?yX#_#!H;rm(t``%w5OJ%(a9lGOm zStp*Q;mB?ap-j#tY zDypL1a>-yvVWA}a3HjeQ88wSG^$lXm08d={UjtpK0<<7*9nqpAT8wc`u#q(B2#KfC z72s%g0U*H+3j>I3e1tv5XhcfS>6F29e)$)Nef0G(@S@IoQO}8{(|7*6t?zogUy#h~ zB$0nr50ad=Rb6LS>Fg?jWaVZ^o4L2l1 zKYI9~CB)LXoptW7wL#ZC8U}=d-!F?2ab0Xu1TNBC`0(Gm48XxdM2MGo@d%oD1K<&D&QBe z2PsQ2>@vR9l5rThUeN3iVs| zvifbV)FdCir1t2bg4#=JF-OUKD;XgYJar0^THy3nS-5L?;hVB7H^W`tkMqI|v9~x? zq-Iy)PH$)7Qj#<-@46BKH4@}7GtX0VOLO`@DY+fT2yA8^odHle-+(l_w#K1UW53q9 z8(>XEm#>Jf`em+2aqiJB0QTwm9|Npd^3bLA`lS--p}o7k_xL~W|0#2eV18nAAdx7Y zDixYCgkt%@!2c3nx_G-9a+N2T2Pd$s_Dc`Q=ImYt>o-2874G1|_ z%CI`K&yiP`1d|;z7}Ro3mN65Mcqx`;T50q?#T;1+)WHuK&Goq-ok*T#ZhOKDh%f8)h5 zCS!5dNvEB4a)!=w=XES<*s{)9C6Cw{CE?*DV7AU+Nm#w03e-!~(5({CHPXqtI@vstd{r;s z&QPz)AY@e6zpG$zT4-d}0n z3h~vf@VKbDvj3U|MEs;gkSkp&5Nwa`rPNUbMC?nQr>D*{bM%tMn%#)|2f5F1znPn( ze0VF4zLZj!(&$O3mzC%2{N4J8^H&{ZqT*Z%t7Ku73X%p^oZnoN{fAH)`g#}WVn&`q zC4|2Na0X=9K=4xg+45@zdEFXZI|#?i{lSfMbDSJ-_uc-l`}O4fk7i%>svrD@-~#`- z47k+1X&{VnoNP(f6g zCgW8`v!_81DU78)9OXH>;F~z`_`OI}2Q*n8aQj=eUw^M8 zV$XzL^J?<15u+!TJ1k;Ti2}DiS9x5_QY*IHc)`pK^?KKAX6j`lGegy`f1JOZao@9Xy0Nx7{j!a#lVi=P zt)o+$2g)5k@LxZ-;f5_M%E{#0c9r_3XZz>o=8`iPUtCY8iajIAO_f^RA6zw4o6|TL z^S5-op0S!E^oK@4v>U|{4LA9rJsKTCcu|iIX=RW%79w=Ox=5Yar_Qzz+?B9fy!LTe zi9upY0gz-wus;FkxXZYQ1U4d`gztTVTb-e8$u;2Or5oTEK}a14{aCFy{l@Pjg$+jRY1Kte1M?6|EFIHq(#bDT!6m zu126N9MnKbmKupoo{}!D(L9CD5|{LSn`aN-4)ZLj9*-fG{u;MD>2;uJl2br;#(_4i zNYtn**?U0d|H7>`8A)&2W703kzZtmD!kG6C0`KR3id!k#q!^?W31=e`02t{rg~8Y$ zN)9~k6}qqkK?%qatBMyd+3e#Cs#ftgJu|yKJ>_3BmEP`ucEfek*Ie-5*Q|Nl4g2q1 zz1qKZd_3bPF1qv1i{}4n<9OyzekJ;=pU+raa%IQIKiV;#p8ux|uHtNeaX<6eVQ-y} z6}SY9fSv~S3=2M@CV6Fjq}6K+cws>6*cRg!CTQ-I#Yo7@1~UWk6NyLNwo)x~O|4LC zV{Er=Nd=p>@#AVkuNRSBr&|#nUh2oB1hO^g4(F9bY8gNb$&mUO#Tg;_Cs}1GBdtYg z+q%_qCJc;0d@QCJ1~!HP8FJaHt1RFw4&vk+Y)Ri3=CMBfVwnX>>!#aoPlj|cl9Qx; zlP(S&@(62MzKjt}JEXm#GY?)o?e`4M9o;s$b3?nm@fEA;tCkNW%D!Kl+&*1hQOWu} z#oZgu-%{uutF7ETR_%!Vs62n~l|O%Cwr|7bt5;un!9Xfkj2CmQ%=rf|9rL5ut=!UB zap~svn&Haw^JZ%h0B?}k`U-ioy!~Z3+5MQ zvMaY1GRYB}fM$TSTJ#eK)dsU#sQbghu+aZ!oW9`y@fDE+^WXYr$K_J^m4Eu{=)qN| zUh33u^y@dY_ds=Wb#waxR3|CBR8PmOHK!G+a#EHnR`&miAeGvn^h)Dq+ls`FHR5z@GVs=Z_tDN^M^4eKS(@*Fl4S)_G1dWVqV@`ZuN3jCrtkPsaxT z4;j?M=)swR8-25H*dHR8{iFd!>_oeF>&GYnSC3M9kk%^*4>jA z5AKJucgCjkhF*w zHU^zzX=$@$7w=qb3=T{#oCG5G8tbOlRcrq7SZiQ#!0(83_>b2|(_K)qW$x!?yHkCY z$RAu3pSiU7@&hN2-`M}9bjNI@Lq89my!E=?qo@5ivn=LP2O{gxO5#Vs&tU^h<+Oq& zWA8~i+RQ%J5NRhSniqA@Fl?bXG``Iwi$=i`&AP?5Lldt4TBd9(Mp+|z$qN=aZ=Oh2 zhS!Z0XEv?Q_f4eJ6R{SD2h=W@oi6r{r;-!V&dSh?Ua!q8zOHPUU7zWhNcpwCa$}%U z>MQ$wxm;g%u)kVrm%6jR(U*$1+STGfaUs6gU-Fw!Iq-27LZiKMCGSZ$xYairyxMSp z{xMk5lY&zEQ_%t0K+3$*X;!tooguCKz{^Thmc-z-g^HweR<=4QRyLCX1u^^$wx^hW zMt(|pMhVdvmLyKcbfIp+B;IMsMBblJzfw1W z(3MQHlm)+4Ppw!xu}w9PQm^4k|M~v7zqYH=6`7(+Z=-5Io{zDA;jQ=Fx$6USGT14c z{j&cYJW)F^UZ=)}l8oR+sfXR1T$XswLA*wyqbFd^Wi zCTa@uuGbx77!4=;&L2drqcmMgMOyx6fBR#5e*0tV-tx}3j`@%J@0h=3{+7t+=bxSb zpf4LO*+@oy71??~>(>p*`_fcwmYAv;`PUS18j&F2_FB0KlXAahMd#b-3IG@Dds3i8MbywyH8I-gMc z9N31i>(g0if|$5%kL>0aA$Q~MlOvZtzhiFA`U~&vxI2W~rt5BsM_zcj02MiuoEhJ> zV-aeCTW{oQztk}djk-h>0F9qK9*4$p#|giY+cbU>$;?xx#CU`1*)Z@43y5q>6u^?D z^x45rM!s^->i4J&*~NVr`>v>mU7W3#yiWoIK#wX zaq1EYl7*g;AOXyIyYL@=;O%3NZhAEGy3o4?dnEl|^p8Yj7}n!`3~C`-tZYOUc)D4u zBe0@>@@49F{Srq}>LyVblQHzMmA%=@rV`^pC6vTSyOOGQcY$!KoxT?@!BvO!#yKX= zIfjYGPYRt!oHLT+-dDJv<9?poY{|5#;?vw;;eL+$d2VdUW;l{*bUKC+AWG*N>cSZU zL=hhwZJaqXdMLXqduTKa+%`6rYqavqmgQTGNM`l)#h0BqbJ@kyt1sSh=C;f3jCPIm zwMV<6BYhlP=6mDd!+_z#uKr}?>U(y88J={}XFrGIr0;?cc>Pi@xLz?-6S7D-T=R30_}mLWihOtc1=$?( zowxO|M|TzX<~IG%Yju1}S^Yuzx1M*;kKTXwQ}h4Sd9dSG_zfRWEEnH({L1`4F&BO( zR<%!e9<-d?yD-5w-A^C4N*-Zo-Z4&tWBJ}=C*gS0aw)@-9p7nnY zPr64rmzU!w{o9dDJ9+m!XZpU`o1JaLmwT%TkNb622HmedoAELm`2y)~v%JP4U-34vkAD;SjYYoaZR%)I-hS>wXTOa;c#OOUJ8tpD zI@mD4diEyrch3iSUPWE7R_FB zOT8{7JWo7F08qx5|6%gFl<)(Lsh#}pKl^2VH~jOxM#tw#_n76O^o__xwC|5e^Cjkp zZ=>xGa8G(&9T!mkTJBjdi4Wpg|0HGCy#v5+EOL_a-%Xk4QKxyzQJc2{8|vz>^p4OE zJ0cz40pK(4e;ych^ZpRu0DJ7%X8h|Z@7<(7MEE|=c6}}9yuKeh)rY9hZKUh;Hv3O` z$4Hm+fup|f_%v|)5celZ|7QW*1^XA>9Umv|&D2qKT5{75W$TOmUV>*O^5^6k_JjIj z=}rIZx85(ktuL-4?;l%VjT`I*|0Q?Fg|u0HK|d_L>4&`a#m=)o;hBqE!FORl2w#@o z;Hvt?`a=B?-kS{<8WBB(v+8U57x*;%BVM`Vzf$L)L0kN*4O*}wB2rH!Y(TnEbm$Qt9M8Klj+~+BeWw;8NsulnE{v zKFoWC$RALrAJPVP>r>}l{v)(+3wf;7x|q>~&+xYm;gUXM$QwHQW&RHHcE}sC@ba_Y zCcMI8#?SsG;VFw*Wq;RL{5tzPW9iqQ{S0X~@OPNp{*w9l(Aod#jq>+1C=!Owew-t4O&4 z-y~*W>1Y~%FY-?NH%E?k9PZrOc|+$fcRts3y6Zz-&qoKMyP^-o*2mrv|8mkxKAgHM zeK`GGc2jO$?%v#U`Ca+f=D%9Ft#qP%QDvfeEs-0 zC*Cl1c-87vPp#fE{rc&DT)TShb2HJIudaW`hT?|rZ@l)r@_BFH^uhB#c)>4kzHjsM zTk2aL*z)BqU!JYceroFj7tLK@Z==OJ9_Dh$2_+=Yk_THCY zzw-?{Kep@YT_4!>`B$`G@%qajxFUMRVdyM*gUxA;I4x=9sK4^_a1uguy?qA zc;(?;hi^K3*WqVxp1Aq4n{T-J!JB{m=HI#Hy|;Yq=ySJz`dIncM~@#paro7rc=i0r z>d8GPA3piysja8(JN5ggz0(7yKYaSzXYM=m!P^FI`}^Cgx39bXs@wnL?Vq_La>t1~ zzWtgTUh|>X?t1MVuYLaY7rp-B*MH^Cm3Myl4Nt!D^LPF3-TAv8xcl+De|pbn-n8!C z>b-Bj_p5JS{^on`yXd~J-(S4{%KN|dmiAjVI;@8M$=Yzv({xG~Hborv{z*w<{Oa*< z4B|cSdVae!zGSu_9O3H&LAZlevRi_%mJ;3?gmrlHJA<&4Veb#ZF*YH6FbFdv^nMV8 z6NFy~!dN!=*b=L1h&kQR5EssP5BnDc;VkE+Yjo-=dQtyds(q(+-+k1V456^^r6V5* z!VxbU`A`tXXME&SLAcZF?tlbYdNh0;oSkZ6T<>;BZ>xM_-n|{N_2|%#J-cuR<>_Ha{6%l@`I-i zp1kegf%e?-W2f6M-*@Z5_Q2L7r%xX|89XjOc<9X0eJ9D*a^2W=Z^wi9jaKZraaSEY zdFsgVW9?NFQ&X$XedT_&kDO}nYo9*3?*QJ&Pu|i#e$&6Y+7k=yTL}D1&HR_%U3r*l zShKGETU%G(+N@^;`cu9CVuVbIlmxyq$Na`L^v{ z&ex|bhuipjfS5T_AG6xLoG)%ARv!Ad+83uS<+;CZa0Xi*IkOEJof{sV}>WfkTZk@yOV^4MM`@G z3g^ps?gRssb}1fRc1{k$>7Uh`>e05hShI7>4QsQ{yN&uCF>Je$zbbnXo7K1SvvlVI^A^`E01|DJDxIpo>j1fPG#Yk7-p|i@fA9SR$ECm1dkeh!tKQ#vzlhbw58>zk=>3xS z-#BCQ_q<>CZloU`28;fH9{hdp)7~@QA9{b}eTI{eZ}L8e8=gN#Z+wV-vX6LQpktq{5Ui7zx2L=y~=<0{)&?=ev4WB|H1_2%idpbjOU+uf6msxKk>eX zMP3pUjt_djfoaPBz%%SqoF@AJVAcCOIH3G5-tT%J!w>C8{gj{P^r3g5(tHem4*%Kv zkKTK|U%~6`J2->%Bg_we+vkKi4A=60p=;vUnWINzXO112nwp&oo)<-L-M9bb@nhK& z2TvY3egJL-vp#qrw(t0%;^qoPtC09y!gz?Nho(MeeoU%{LftQKcljERCva_HR)&MFPy@IkB@K5T=;?z0GpcWz7v zNOmD8s?}5bOpYNqOMpd3uYK{IN9q@8e-|R!si#3W_k28fem!`$^*sGF2=AV6WDqI+ z`-0~~dh-66;JI1PGf#uU?rG`yZRvR0cRW8Hyw5QpmEY#z`9$#iTJU_Mp5(t*Ps_(W z-xvJ;c<`JAe9Fhp3gKz~clqv(LHya^xmQo(9}1rD3!cve&ptgV$MWN8>3Kd8#DCnL zfRi5ZmtO6qKh6yoeZQDr8dY8LW6Dqa{#3!wOcg6jqKOQy{xIO4%iSY#PHd4YpZD|G zb7C=Pv8#I_HY_+SNwq4asoy_yMS@}qzF+qBanT>)Z+^(q0|f1X=uD&_wULgFXjd%C zqmw_8u4q?yb#xHwjK!jy`p^}NDP24kBW)LVA{vc$bdjRdl6Q7RN#2o&@_lD#C+Ugq z;FHb{Vo2E)Q<5l!baF={{Ow945@fGSxse~2`%NjjTsGtsw?gzjs2_Q9*$;}1$GgZ= zRUuo-QiT&FrY4;fn^Gv6Q0i#B!+jX*AT64SWZGcR8KZ3m17%>j+h1Bh#&Lr|G#>9H zT_PTjDk2_B@|V&n*s9VQ6^uF*OG%xvXk2x&7OS?@i)KVSW7LIe#efABP9~GCt?aVV zr5eZLc2OP|1=)+}A`EDry9`DI>4(mQV7~wZ`YaynN(x|h#nOa2qe*=lOHf~u#^QoO z6l0SN442x(qls8VIM2Ind-8(##7eqfMh*t#DLl~+ zYLQ9`aSRS>0x*cH^BoML@r+uJ}9+~m3U_+ zp)L>%Qbf|%z(BPnU5ei6O1Pn&U{rz@8IF~8ZFVpa<|Y^*Tygg|4k&dk#S@DV$b>EY z0N2uK&{Mq(L{wlRnTTZos3B1-kuw;ig<=VZd4QPD1cPiIyL)I;G7bzFuJlqTz#^sE z1q>2|Qpp5a##1TAZ!Dckkv1MrC9_1+r`CGDVXSn4=|Dzk!dMZW0D}amLR_Z-CDE0n z5EZ0eh{dy+Ow8Jv%or#HgJjAs%Hz_Ivny>4*LyXDi#&xV{Gbk9nG6_1B^(UY(qxRz zH?#+d@`R#^jCwDT79~!^k}0A(JwjVptdqKr31aU>PgXVp?bzSB?}!g&^3x zO?M>|ITFS)v>%e27A7W=g+d`=ZOs&H1gMRftX(Pln`V&Mm9uWwd-Vqwd2;ap8R^yb<}$z_o)!?5v2MWt z=9S22(`1>-=3=o-vXCy)U|E>|*i5Dan<39fXGfs)UpbJpTi!BAiC!AV`|l)excQeajI{DW?RED2~7c$>>6 zOF+yZm(11$1H7@&o0%eo3kJCW29<_j0FO!)vWPnI3^HjdODi&of56#bK-XufTbRky*XW`yzeFhSd%m9N-tO~#&V~H%7mk|tLTB$7W*vG^ujpu1U!`3h{ zm9A7ONo#Swq84RE!L02n#lZkj>M9!Q8w@~8F7o8!0XC-Nl`=5MYWzZ{L6uw~mx2fg z4**`iDHvocnLHR>itED^U78{#2g|iENbHIw@|jW&8VU>&(R2>VoCR$}1eLl}$mVEv zp(q%Xi-jySAydrP^SLZ|O|Mf8!5|lpWnwkKzz8YWorYusgLF2NLnJJv(%D2oFi0eG z8jY!RwOUPCTMJ+nmtasRy4DvorOsuG)?)Bjm)?Vu4h9-A1_NqQtz=UE2j3MNPBMK&LgW#jccB>;nbrc5-<3Z|7N7hq6MWpcnEnF9uS zjmC7QR;vXtsHsJ~NhFFTHJ(x+79~m+Y_i$1u}p&jrE}%7LLfCK!+5Jzfk94mQj-Gk zwpd8lz#2gyoi21sumy7qys0Eq56))VDVTk-T-N!=I~Ik8(NUaBV^@)Pc~CYXLE@n zIDnv%XEZ`V>h*fsT3oE#kT4jO)p$yQSd{a*lC>B-)+HFIAzXQ*nGOcoM7@?vL%SKj zDW-qmZK;r{0|UdJOtA+!DVeX+mAOKd(FXz*OYw}spxMW%p3!)+n5`6$;ekOimMK6~ zsdYw-fSS?u`2x)@SAapbRw?Jog?z43Y(XA@fjCBvR;F^8W(o$-bzo4)Rf$d_szWmJ zxq^d1K3SsujM0K%kjXY0jkLA6)G$gY7?dh%d^ul+SX2u6vU)9-tJ?6_dxp9$^5hZ| z$uhd?^?bUJr#qlQNXfZExtM_v3I>3#)CUYw`9>bRD%6sB%F2|=@hmAh(xojJB$B0E zwFnGS1z^CSp#(u84*?)`wOlAL9?F$uvXre?s2vzkDRo00DILrwb%6m^OvLkvW|5&t zZxn$+o)dXV%Z{iRsiF~2uPi&m5W81U8z#PTmzT%6)>P$?twfa5F_5U{K5#fk6!zq{`p`W3*UAlFa5>tyTbomJJEPpi&hAPznUIS}as-kmPG7 zG6@FYq^<=RFd}owX0woiT0?n&0U~&*Qp&a*3;#FAhvC;$WYxzhE;63wpGs9&y8s}`!ILcUh+EtiUnZMD9@K+6s|+w(Nf*0|l|rG^ z1O_miN)?GfFz6i=43gXklN zguwu=nJeZq#d0!HO!nYH7@`F;X;3?0Pyz-egF!hA#6R#%`^WgAfV^0IxbI z7?gU7;8nSabSfA?7a&`n*EbZvpwOr={mYbKcKI@lrNqz?Go)sqf0>hRinRvy%eM>$ zrDDC>hDD%6Q0t4N&N>+Mf;2^As7<1w{RnXRQn8#UDzfI+!b&NXZ03SD0Z z2DL(Wqh6|m0gY-uJKF*nl=5Xzv64!Zl6@7(5f~}HQOu)jK!D4aOO<3H--KGHYZL+u zDuO}2(AV3SvtF1GCDx`aRN;#-CG|XU7 zs?@9bJ_iGUR~r!w%DtspsZ{As3wZe&w2^t0=k<@qJ@7SCE4Hcz10hnS0E{6Y5(t#K zRj*WNcB7e2*9tw&MyXLLmzuQ!*d+7~DUx9c-v9>5QnFnI$~hQnu|+g6sAQ9c3NR=Z zTDf95T~BA3aAvC&kTYLw_qFrZ;(FW2g4lVzsm3?T4VXr=Qf}BFDRtWb5Ddx;O)dum zb!h>b)7M+hSEz)jLng`CZPW@d11TsVpY>5@t(i(+xn3?+domT^U7$+~nG{QW17iUU zO5HVJkgdS*3stBM0A{>F1k06tccW6JLz*q>SL|&y%S}c>t3Ft-R+tzG24z@9u3Swe z%c=ev{9Ozc-dP6F8HCsZXP_iY#qNBuk^u&YJA#2kwf=U0-dfxMtGEP%MoW#S6qrV< zT4{zbQ0E&A=u9s1SN3qvXyqF&ZzFq zi1QTc&_+nN=M654doYu1z0^}}Gd5(4c>{IlFT5)7OUl2s#NUBm#Uctg&>O8M3oDr zf&PJlgTa7t1Hqu#Z7`@bVH(}FN=ukqF87$|toMvdUF6Bdqg;aK^tUU8T2*vBmt@8W z4C=)JU|`r&Y%CKDs{Iu(xYm~u@QRI=U{LnFq2+=>I@>7s)PX^+ip~lc0At991OieQ zdYd)CT50uUGR;!EyH#n`s=#2_!9W;L0S5UBFsP&k>p+=NDc)HD2H6_(?OLUlDwlfU zSlMPq;!dt!V@6Rd4Gs(zti{biBMTB~n%zQxR<&g?s0J|TU4#KcldD?M7wS^MV4%M$ z7(m1FffjjwE>(d+ty%;9YxP#G(k&R2+dbXYZbm^*a|AYtLJdi}QZ3a$McjN;(?bnNGNV$w z6FEgNNSA7ry1}4a%eKG)g#9{H8E!f>I8?M2w+4+H2nMYlHJ(ynoIUkwx3##^XVVAa z0pn5^d2;cnl%czW1Jz=^COV#H?q8`ix|=1KffQB6VyU%)c~h=7SY>QA`m^FZCD6LW zT*&iA#@TC`NavcBz6Nq-t}YlfO28OySgpYbVAOrx^#;xE>CI$Y<^JBDYEPq9>1~a+ z8iIi^Krkp&8yR3Q%)o&IY6*=Pf_$l7ZKNvYJ~$RI$fJ13H$;_7mEob`qP4ht z$hd)E(A}%X_tbiNxf-<|2ZOf3K<{e};c}HcxhSk!hUN?n){2dqWQIbDmQ@=)&C)Q` zLl7vHTH`1na`mAa7~JU3)dhoAPr7U{7@cr1XjR%xV34mP^pqRrDtrJa0E2q14*E9? z27TFVcV(cD+A#|HT4Sw79n}n@zgjET8IHi9mL6#$;|K=G54AEf05B-mYmIcJ+%8t? zxo&WP=}5D|T(wjg86GJ)7z`T>G%4um3t-U4)u{Jci>v)Mg)$g49Smv)gL<`E0S3cE zwNj%lIxZMMzj|8b5ny2Cv)s*gU=$w1^=?M>K(0<%zFF-jI)@qyO+usAOjj%YaI9PpIKXtoU{J1(j*OP9#XTd&5e)`yApoVcxtjG} zBNVko7%(n%ktY|AS_Qg0GF&e;8)fKtF`ZA>YOUVx@~DG>2I0eT;&3&vHZs zlmv|aTD{U>IJUCsdS(n5)PX?@`Jr9`225ru&PAQ<#g2>hxg&Qz|BjgFSB#l53O z8YR~CwuJzFjXr}xqtC%$z@|`wQ3!*&2nk(^`lOm09ccgq@iJhLfqwOMS73<3gL1jj zI|U31&Cy10z1|wiH-UGhr!RoP@>NMMo6O{UY6IQq_zFz~ze)>iZUO`5_UUG$DHyc+ zn)Nm?=&cU-w;OFnL4VJRo>mhWFr%tBDort)Y`T$I)?IJHg$u3PAQTJztAjx+Q>zZZ zvGTp(02A15V1UTJY-}um!I((}f-8#h7Z{XV zP54t)FsRqN+dY+K5Kxc+deXZplPMRPV~yTMy?Z#{q^wGBJ5xo^f`QevV2~~J)&_e7 zgBCETc2^tqrl5deNbghz`&!*}eS3iV)kX%WU3arS&^zAS-9$+s3}{rF499L@kX_Ee zX#j)n`Vi5;fXPg?)#wHWgMvX{uGnN++TCKlUa2i#wybQu-nYy+qF~S-Fc>u316&Kp`p$f`W*OQlOxKKtXXwD6Rq`ib4p6m;^&034{=GAqfc~ zfk0v)A>nrXowJGM-(YQj`0c6vFg^Wj_j}&c`#jxMHKBqAoXrXiLNrjJsu!u&)Wt0C z?M=KkFQv=43i70zXf>um5H=K(O;qj)OT!U;UY~8OT2yUr?r1d7XyAJVvvwtACoFs; zjRp;Wcxb5ZjyN51rO|e_X>Lyd_L8${mANAhT22G2(M}CQTS$;1@Tj|k17Te&<|nVl zZExyV7B`p>?Tu?HX!_Ywsb1AXDhWykl52dUIQLW@fDlP?nest*%zfI>-ZL$*ptu`b5?$hKQbTaBnqc8ioPB>Yf8Z&2wBqd~-s?$=8^bINMqcXw*wHz#u+ zr52CqrdG*dHDX_WvnczuvJ#m%#c5E>!ggvkh??#(2w_?0mY;+-0drcBKZuV#BF?N@uMabMYwby5n0b|Z|dd4*-X)4(p> zM!Q|l9dX`G?4Q+YkoVgYpoofowj^qeX)y3#4WiWjhRBxa5d>Lrd$ zr$y$|6xe@YP*d|MWp0?p-6)TAI#jiLvKj;p**n78r6?+Xu*{oq&S%kV(nq_P2j{QmIkjt9vB zj1QIr&0CmxEf0~e!9yLtAqSZ^@y{O&4|hC54l(QT(jN+sbUaE9V|=t6Zr0(gw>(CU zfXB)=;c;>#DbC~ND0qS#4NsJB!IR_|vlh?%vG8O$4xS>%o7eHqTb?Q>z|-VJc)FZq z*5Hvp8J^+zZ8?SUnR2RGjc?xayK)*NCj`%u(@C3tU(SF(a6DViWPFZ%$E?CtZ+WhK z51uDynU%QfElDlG^Bpgcv&{;;_UFJ0<%jU6axT0`&NHv#y#EpWx%?RZLe7U5!{uZM zE`Yz1pTJAxLbD84{YCIn$IIkrjDO9$yqA(Mu)JI@hF8ch;cwv*%+i;@D;=+rOBr7+ zmzh_{A6Q-^zk%1v0{%;;!Z~mb z35{uRt~>?#Jovm!CqX>ValXu8yg>d5Ux3e$-k1p&$}ISj%!Z5P88e&I#T>ZU@fCU2 z%#tNC7cQ0O;4*n0E|+;`CYh1>aD^;@D;-zKizJ<2lZ9}#;~H7S_;omg{Km`h4OtA= zIj)x_=4rAZOW|9x3~rF+W;zLySK&Ld0&bL*a1;Co8I@IVv%Ci1mDTV)SwrS}i>!rP z9p9HX7;lqxW}0l5_3#6E6MhJvl#gTs{8-+GpEw%XXr_+W^zoWLUem{G`gl$MKdR~S EAF(mv_W%F@ literal 0 HcmV?d00001 diff --git a/themes/default/layouts/_partials/address_autocomplete.html b/themes/default/layouts/_partials/address_autocomplete.html new file mode 100644 index 0000000..b91717d --- /dev/null +++ b/themes/default/layouts/_partials/address_autocomplete.html @@ -0,0 +1,47 @@ +{{ define "address_autocomplete" }} + +
+ + + + +
    + +
+
+{{ end }} \ No newline at end of file diff --git a/themes/default/layouts/_partials/mainmenu.html b/themes/default/layouts/_partials/mainmenu.html new file mode 100644 index 0000000..94d2108 --- /dev/null +++ b/themes/default/layouts/_partials/mainmenu.html @@ -0,0 +1,19 @@ +{{define "mainmenu"}} + +{{range .LayoutState.MenuItems}} + +{{end}} + +{{end}} \ No newline at end of file diff --git a/themes/default/layouts/administration/_partials/groups_admins.html b/themes/default/layouts/administration/_partials/groups_admins.html new file mode 100644 index 0000000..64292ef --- /dev/null +++ b/themes/default/layouts/administration/_partials/groups_admins.html @@ -0,0 +1,37 @@ +{{define "groups_admins"}} +
+ +

Administrateurs

+ + +
+
+

Ajouter

+
+
+ +
+ + +
+ +
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/administration/create_group.html b/themes/default/layouts/administration/create_group.html new file mode 100644 index 0000000..eedf35f --- /dev/null +++ b/themes/default/layouts/administration/create_group.html @@ -0,0 +1,142 @@ +{{define "content"}} + + +
+

Administration > Créer une organisation

+
+ +
+
+
+
+
+

Nouvelle organisation

+

Informations de base sur la nouvelle organisation à créer

+
+
+
+
+ + +
+
+
+
+
+
+
+
+

Paramètres

+

Paramètres de configuration de l'organisation (modules + accessibles, ...)

+
+
+ +
+ Droits d'accès aux modules + +
+
+
+ +
+
+ +

Gestion des bénéficiaires assignés à sa propre organisation. +

+
+
+
+
+ +
+
+ +

Trouver des solutions et organiser les déplacements de ses bénéficiaires.

+
+
+
+
+ +
+
+ +

Trouver et réserver des véhicules pour ses bénéficiaires. +

+
+
+
+
+ +
+
+ +

Gérer les véhicules et réservations (pour les gestionnaires de flottes) +

+
+
+
+
+ +
+
+ +

Gestion des dispositifs pour les bénéficiaires (auto-écoles sociales, événements, ...) +

+
+
+
+
+
+
+
+ +
+

Certains champs de sont pas valides.

+ + + + +
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/administration/display_group.html b/themes/default/layouts/administration/display_group.html new file mode 100644 index 0000000..fce538f --- /dev/null +++ b/themes/default/layouts/administration/display_group.html @@ -0,0 +1,114 @@ +{{define "content"}} +
+
+
+ +
+

{{.ViewState.group.Data.name}}

+
+
+
+ + +
+
+
+
+
+
+
+

+ Paramètres de l'organisation

+

Paramètres généraux de l'organisation

+
+ {{template "groups_admins" .}} +
+
+
+
+
+

Modules activés

+ +
+
+
+
+ +
+
+ +

Gestion des bénéficiaires assignés à sa propre organisation. +

+
+
+
+
+ +
+
+ +

Trouver des solutions et organiser les déplacements de ses bénéficiaires.

+
+
+
+
+ +
+
+ +

Trouver et réserver des véhicules pour ses bénéficiaires. +

+
+
+
+
+ +
+
+ +

Gérer les véhicules et réservations (pour les gestionnaires de flottes) +

+
+
+
+
+ +
+
+ +

Gestion des dispositifs pour les bénéficiaires (auto-écoles sociales, événements, ...) +

+
+
+
+
+ +
+
+ +

Administration générale de la plateforme PARCOURSMOB. Créer, ajouter des organisations et administrateurs. +

+
+
+
+
+
+ +
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/administration/home.html b/themes/default/layouts/administration/home.html new file mode 100644 index 0000000..7f7dea8 --- /dev/null +++ b/themes/default/layouts/administration/home.html @@ -0,0 +1,136 @@ +{{define "content"}} +
+

Administration

+
+ +
+

Statistiques

+
    +
  • +
    + {{.IconSet.Icon "hero:outline/user-group" "h-6 w-6"}} +
    +
    +
    + Bénéficiaires +

    160 bénéficiaires

    +
    +
    +
  • + +
  • +
    + {{.IconSet.Icon "hero:outline/office-building" "h-6 w-6"}} +
    +
    +
    + Organisations +

    12 organisations

    +
    +
    +
  • + +
  • +
    + {{.IconSet.Icon "hero:outline/briefcase" "h-6 w-6"}} +
    +
    +
    + Référents +

    53 membres

    +
    +
    +
  • + +
  • +
    + {{.IconSet.Icon "hero:outline/shield-check" "h-6 w-6"}} +
    +
    +
    + Accompagnement +

    363 actions réalisées

    +
    +
    +
  • +
+
+ + +{{end}} \ No newline at end of file diff --git a/themes/default/layouts/auth/groups.html b/themes/default/layouts/auth/groups.html new file mode 100644 index 0000000..e2aad30 --- /dev/null +++ b/themes/default/layouts/auth/groups.html @@ -0,0 +1,40 @@ +{{define "main"}} + + + PARCOURSMOB + + + + + + +
+
+ {{.IconSet.Icon "coopgo:parcoursmob/monogram" "mx-auto h-16 w-auto"}} +

Connectez vous à votre organisation

+
+ +
+
+
+
+ Organisations + {{range .ViewState.groups}} +
+ +
+ {{end}} +
+
+
+
+
+ + +{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/_partials/beneficiary-events.html b/themes/default/layouts/beneficiaries/_partials/beneficiary-events.html new file mode 100644 index 0000000..1256a08 --- /dev/null +++ b/themes/default/layouts/beneficiaries/_partials/beneficiary-events.html @@ -0,0 +1,5 @@ +{{define "beneficiary_events"}} +
+ TODO Dispositifs +
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/_partials/beneficiary-files.html b/themes/default/layouts/beneficiaries/_partials/beneficiary-files.html new file mode 100644 index 0000000..ffd6c5a --- /dev/null +++ b/themes/default/layouts/beneficiaries/_partials/beneficiary-files.html @@ -0,0 +1,5 @@ +{{define "beneficiary_files"}} +
+ TODO Fichiers +
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/_partials/beneficiary-journeys.html b/themes/default/layouts/beneficiaries/_partials/beneficiary-journeys.html new file mode 100644 index 0000000..1e3f850 --- /dev/null +++ b/themes/default/layouts/beneficiaries/_partials/beneficiary-journeys.html @@ -0,0 +1,5 @@ +{{define "beneficiary_journeys"}} +
+ TODO Déplacements +
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/_partials/beneficiary-notes.html b/themes/default/layouts/beneficiaries/_partials/beneficiary-notes.html new file mode 100644 index 0000000..34c64c4 --- /dev/null +++ b/themes/default/layouts/beneficiaries/_partials/beneficiary-notes.html @@ -0,0 +1,108 @@ +{{define "beneficiary_notes"}} +
+
    +
  • +
    +
    + +
    +
    + +
    +

    Ducimus quas delectus ad maxime totam doloribus reiciendis ex. + Tempore dolorem maiores. Similique voluptatibus tempore non ut.

    +
    +
    + 4d ago + · + +
    +
    +
    +
  • + +
  • +
    +
    + +
    +
    + +
    +

    Et ut autem. Voluptatem eum dolores sint necessitatibus quos. Quis + eum qui dolorem accusantium voluptas voluptatem ipsum. Quo facere + iusto quia accusamus veniam id explicabo et aut.

    +
    +
    + 4d ago + · + +
    +
    +
    +
  • + +
  • +
    +
    + +
    +
    + +
    +

    Expedita consequatur sit ea voluptas quo ipsam recusandae. Ab sint et + voluptatem repudiandae voluptatem et eveniet. Nihil quas consequatur + autem. Perferendis rerum et.

    +
    +
    + 4d ago + · + +
    +
    +
    +
  • +
+
+ +{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/create.html b/themes/default/layouts/beneficiaries/create.html new file mode 100644 index 0000000..d42bf43 --- /dev/null +++ b/themes/default/layouts/beneficiaries/create.html @@ -0,0 +1,173 @@ +{{define "content"}} + +
+

Ajouter un bénéficiaire

+
+ +
+
+
+
+
+

Informations obligatoires

+

Informations personnelles sur le bénéficiaire obligatoires + pour créer son profil dans PARCOURSMOB

+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+ +
+
+
+

Informations optionnelles

+

Autres informations de profil optionnelles

+
+
+
+ +
+ + +
+ +
+ +
+ +
+
+ + + + +
+
+
+
+
+
+
+

Paramètres

+

Paramètres liés au bénéficiaire, utiles pour exploiter les fonctionnalités de PARCOURSMOB

+
+
+ + {{ $fieldName := "address" }} + {{ template "address_autocomplete" dict "FieldName" $fieldName }} + + + +
+
+
+ +
+

Certains champs de sont pas valides.

+ + + + +
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/display.html b/themes/default/layouts/beneficiaries/display.html new file mode 100644 index 0000000..c14b847 --- /dev/null +++ b/themes/default/layouts/beneficiaries/display.html @@ -0,0 +1,304 @@ +{{define "content"}} +
+ +
+
+
+
+ + +
+
+
+

{{.ViewState.Data.first_name}} + {{.ViewState.Data.last_name}}

+

{{if .ViewState.Metadata.created}}Ajouté le par + Conseiller 1{{end}} +

+
+
+
+ + +
+
+ +
+
+
+
+
+

+ Informations personnelles

+

Informations générales sur le bénéficiaire.

+
+
+
+ {{if .ViewState.Data.email}} +
+
Email
+
{{.ViewState.Data.email}}
+
+ {{end}} + {{if .ViewState.Data.phone_number}} +
+
Téléphone
+
{{.ViewState.Data.phone_number}}
+
+ {{end}} + {{if .ViewState.Data.birthdate}} +
+
Date de naissance
+
{{(timeFrom .ViewState.Data.birthdate).Format + "02/01/2006"}}
+
+ {{end}} + {{if and .ViewState.Data.gender (ne .ViewState.Data.gender "0")}} +
+
Genre
+
{{genderISO5218 .ViewState.Data.gender}}
+
+ {{end}} + {{if .ViewState.Data.address}} +
+
Adresse
+
{{.ViewState.Data.address.properties.label}}
+
+ {{end}} + +
+
+
+ +
+
+
+
+
+ + +
+ +
+ +
{{template "beneficiary_notes" .}}
+
{{template "beneficiary_journeys" .}}
+
{{template "beneficiary_events" .}}
+
{{template "beneficiary_files" .}}
+
+
+
+
+ +
+
+

Actions réalisées

+ + +
+
    +
  • +
    + +
    +
    + + + + +
    +
    +
    +

    Applied to Front End Developer

    +
    +
    + +
    +
    +
    +
    +
  • + +
  • +
    + +
    +
    + + + + +
    +
    +
    +

    Advanced to phone screening by Bethany Blake

    +
    +
    + +
    +
    +
    +
    +
  • + +
  • +
    + +
    +
    + + + + +
    +
    +
    +

    Completed phone screening with Martha Gardner

    +
    +
    + +
    +
    +
    +
    +
  • + +
  • +
    + +
    +
    + + + + +
    +
    +
    +

    Advanced to interview by Bethany Blake

    +
    +
    + +
    +
    +
    +
    +
  • + +
  • +
    +
    +
    + + + + +
    +
    +
    +

    Completed interview with Katherine Snyder

    +
    +
    + +
    +
    +
    +
    +
  • +
+
+
+ +
+
+
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/list.html b/themes/default/layouts/beneficiaries/list.html new file mode 100644 index 0000000..0b4e116 --- /dev/null +++ b/themes/default/layouts/beneficiaries/list.html @@ -0,0 +1,159 @@ +{{define "content"}} + +
+
+
+
+
+ + + + + + + + + + + + + + + +
+ Nom + + Téléphone + + Adresse + + Labels + + Modifier +
+
+ + +
+
+
+ +
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/beneficiaries/update.html b/themes/default/layouts/beneficiaries/update.html new file mode 100644 index 0000000..9bd1749 --- /dev/null +++ b/themes/default/layouts/beneficiaries/update.html @@ -0,0 +1,173 @@ +{{define "content"}} + +
+

Modifier un bénéficiaire

+
+ +
+
+
+
+
+

Informations obligatoires

+

Informations personnelles sur le bénéficiaire obligatoires + pour créer son profil dans PARCOURSMOB

+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+ +
+
+
+

Informations optionnelles

+

Autres informations de profil optionnelles

+
+
+
+ +
+ + +
+ +
+ +
+ +
+
+ + + + +
+
+
+
+
+
+
+

Paramètres

+

Paramètres liés au bénéficiaire, utiles pour exploiter les fonctionnalités de PARCOURSMOB

+
+
+ + {{ $fieldName := "address" }} + {{ template "address_autocomplete" (dict "FieldName" $fieldName "Address" .ViewState.Data.address) }} + + +
+
+
+ +
+

Certains champs de sont pas valides.

+ + + + +
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/dashboard/_partials/beneficiaries-widget.html b/themes/default/layouts/dashboard/_partials/beneficiaries-widget.html new file mode 100644 index 0000000..5492312 --- /dev/null +++ b/themes/default/layouts/dashboard/_partials/beneficiaries-widget.html @@ -0,0 +1,31 @@ +{{define "beneficiaries_widget"}} +
+
+
+

Bénéficiaires

+

Derniers ajoutés

+
+ +
+ + + + + +
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/dashboard/dashboard.html b/themes/default/layouts/dashboard/dashboard.html new file mode 100644 index 0000000..a6bf543 --- /dev/null +++ b/themes/default/layouts/dashboard/dashboard.html @@ -0,0 +1,15 @@ +{{define "content"}} + +
+

Tableau de bord

+
+
+
+ + + {{template "beneficiaries_widget" .ViewState.beneficiaries}} + + +
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/layout.html b/themes/default/layouts/layout.html new file mode 100644 index 0000000..ee3448a --- /dev/null +++ b/themes/default/layouts/layout.html @@ -0,0 +1,177 @@ +{{define "main"}} + + + + + PARCOURSMOB + + + + + + + + + + + +
+
+ + +
+ +
+
+ {{ template "content" . }} +
+
+
+ + + + +{{end}} \ No newline at end of file diff --git a/themes/default/layouts/vehicles_management/_partials/bookings-list.html b/themes/default/layouts/vehicles_management/_partials/bookings-list.html new file mode 100644 index 0000000..3b803d3 --- /dev/null +++ b/themes/default/layouts/vehicles_management/_partials/bookings-list.html @@ -0,0 +1,72 @@ +{{define "bookings_list"}} +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Statut + + Type + + Immatriculation + + Beneficiaire + + Prescripteur + + Gestionnaire + + Dates + + Actions +
+
aa
+
+
aa
+
+
aa
+
+
aa
+
+
aa
+
+
aa
+
+
aa
+
+ Voir +
+
+
+
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/vehicles_management/_partials/vehicle-type-select.html b/themes/default/layouts/vehicles_management/_partials/vehicle-type-select.html new file mode 100644 index 0000000..316bdc6 --- /dev/null +++ b/themes/default/layouts/vehicles_management/_partials/vehicle-type-select.html @@ -0,0 +1,63 @@ +{{define "vehicle_type_select"}} +
+ + +
+ + +
    + +
  • + + Voiture + + + +
  • +
  • + + Vélo électrique + + + +
  • + + +
+
+
+ +{{end}} \ No newline at end of file diff --git a/themes/default/layouts/vehicles_management/_partials/vehicles-list.html b/themes/default/layouts/vehicles_management/_partials/vehicles-list.html new file mode 100644 index 0000000..36fff55 --- /dev/null +++ b/themes/default/layouts/vehicles_management/_partials/vehicles-list.html @@ -0,0 +1,54 @@ +{{define "vehicles_list"}} +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
+ Immatriculation + + Gestionnaire + + Modèle + + Gestionnaire + + Actions +
+
aa
+
+
aa
+
+
aa
+
+
aa
+
+ Voir +
+
+
+
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/vehicles_management/fleet-add.html b/themes/default/layouts/vehicles_management/fleet-add.html new file mode 100644 index 0000000..55ae759 --- /dev/null +++ b/themes/default/layouts/vehicles_management/fleet-add.html @@ -0,0 +1,106 @@ +{{define "content"}} + + +
+

Ajouter un véhicule

+
+ +
+
+
+
+
+

Identité du véhicule

+

Informations de base sur le véhicule

+
+
+
+
+ + +
+
+ {{template "vehicle_type_select" .}} +
+
+ + +
+
+
+
+
+
+
+
+

Informations pratiques

+

Informations pratiques pour la réservation

+
+
+ {{ $fieldName := "address" }} + {{ template "address_autocomplete" dict "FieldName" $fieldName }} + +
+ +
+ +
+
+
+
+
+ +
+

Certains champs de sont pas valides.

+ + + + +
+
+
+{{end}} \ No newline at end of file diff --git a/themes/default/layouts/vehicles_management/overview.html b/themes/default/layouts/vehicles_management/overview.html new file mode 100644 index 0000000..39886ea --- /dev/null +++ b/themes/default/layouts/vehicles_management/overview.html @@ -0,0 +1,31 @@ +{{define "content"}} +
+

Gestion des véhicules et réservations

+ +

Réservations

+
+ +{{template "bookings_list" .}} + + + +{{template "vehicles_list" .}} + +{{end}} \ No newline at end of file diff --git a/themes/default/public/css/main.css b/themes/default/public/css/main.css new file mode 100644 index 0000000..4f7da2c --- /dev/null +++ b/themes/default/public/css/main.css @@ -0,0 +1,2543 @@ +/* +! tailwindcss v3.1.6 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +*/ + +html { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font family by default. +2. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input:-ms-input-placeholder, textarea:-ms-input-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: #fff; + border-color: #6b7280; + border-width: 1px; + border-radius: 0px; + padding-top: 0.5rem; + padding-right: 0.75rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + font-size: 1rem; + line-height: 1.5rem; + --tw-shadow: 0 0 #0000; +} + +[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + border-color: #2563eb; +} + +input::-moz-placeholder, textarea::-moz-placeholder { + color: #6b7280; + opacity: 1; +} + +input:-ms-input-placeholder, textarea:-ms-input-placeholder { + color: #6b7280; + opacity: 1; +} + +input::placeholder,textarea::placeholder { + color: #6b7280; + opacity: 1; +} + +::-webkit-datetime-edit-fields-wrapper { + padding: 0; +} + +::-webkit-date-and-time-value { + min-height: 1.5em; +} + +::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field { + padding-top: 0; + padding-bottom: 0; +} + +select { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); + background-position: right 0.5rem center; + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + padding-right: 2.5rem; + -webkit-print-color-adjust: exact; + color-adjust: exact; + print-color-adjust: exact; +} + +[multiple] { + background-image: initial; + background-position: initial; + background-repeat: unset; + background-size: initial; + padding-right: 0.75rem; + -webkit-print-color-adjust: unset; + color-adjust: unset; + print-color-adjust: unset; +} + +[type='checkbox'],[type='radio'] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0; + -webkit-print-color-adjust: exact; + color-adjust: exact; + print-color-adjust: exact; + display: inline-block; + vertical-align: middle; + background-origin: border-box; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + flex-shrink: 0; + height: 1rem; + width: 1rem; + color: #2563eb; + background-color: #fff; + border-color: #6b7280; + border-width: 1px; + --tw-shadow: 0 0 #0000; +} + +[type='checkbox'] { + border-radius: 0px; +} + +[type='radio'] { + border-radius: 100%; +} + +[type='checkbox']:focus,[type='radio']:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 2px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); +} + +[type='checkbox']:checked,[type='radio']:checked { + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); +} + +[type='radio']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); +} + +[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='checkbox']:indeterminate { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e"); + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='file'] { + background: unset; + border-color: inherit; + border-width: 0; + border-radius: 0; + padding: 0; + font-size: unset; + line-height: inherit; +} + +[type='file']:focus { + outline: 1px solid ButtonText; + outline: 1px auto -webkit-focus-ring-color; +} + +html { + font-family: Bitter, serif; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::-webkit-backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +.pointer-events-none { + pointer-events: none; +} + +.visible { + visibility: visible; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.sticky { + position: -webkit-sticky; + position: sticky; +} + +.inset-0 { + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; +} + +.inset-y-0 { + top: 0px; + bottom: 0px; +} + +.top-0 { + top: 0px; +} + +.right-0 { + right: 0px; +} + +.left-0 { + left: 0px; +} + +.top-4 { + top: 1rem; +} + +.left-4 { + left: 1rem; +} + +.z-40 { + z-index: 40; +} + +.z-10 { + z-index: 10; +} + +.z-0 { + z-index: 0; +} + +.col-span-6 { + grid-column: span 6 / span 6; +} + +.col-span-1 { + grid-column: span 1 / span 1; +} + +.col-span-3 { + grid-column: span 3 / span 3; +} + +.col-span-2 { + grid-column: span 2 / span 2; +} + +.col-span-4 { + grid-column: span 4 / span 4; +} + +.col-span-5 { + grid-column: span 5 / span 5; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.-my-2 { + margin-top: -0.5rem; + margin-bottom: -0.5rem; +} + +.-mx-4 { + margin-left: -1rem; + margin-right: -1rem; +} + +.-mr-12 { + margin-right: -3rem; +} + +.ml-1 { + margin-left: 0.25rem; +} + +.mt-5 { + margin-top: 1.25rem; +} + +.ml-4 { + margin-left: 1rem; +} + +.ml-3 { + margin-left: 0.75rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mr-4 { + margin-right: 1rem; +} + +.mt-8 { + margin-top: 2rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.mt-6 { + margin-top: 1.5rem; +} + +.mt-3 { + margin-top: 0.75rem; +} + +.mt-10 { + margin-top: 2.5rem; +} + +.mr-3 { + margin-right: 0.75rem; +} + +.mr-1\.5 { + margin-right: 0.375rem; +} + +.mr-1 { + margin-right: 0.25rem; +} + +.ml-5 { + margin-left: 1.25rem; +} + +.ml-6 { + margin-left: 1.5rem; +} + +.-mb-px { + margin-bottom: -1px; +} + +.-mb-8 { + margin-bottom: -2rem; +} + +.-ml-px { + margin-left: -1px; +} + +.-ml-4 { + margin-left: -1rem; +} + +.-mt-2 { + margin-top: -0.5rem; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + +.inline { + display: inline; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.table { + display: table; +} + +.flow-root { + display: flow-root; +} + +.grid { + display: grid; +} + +.hidden { + display: none; +} + +.h-full { + height: 100%; +} + +.h-10 { + height: 2.5rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-8 { + height: 2rem; +} + +.h-0 { + height: 0px; +} + +.h-16 { + height: 4rem; +} + +.h-5 { + height: 1.25rem; +} + +.h-4 { + height: 1rem; +} + +.h-12 { + height: 3rem; +} + +.h-96 { + height: 24rem; +} + +.max-h-60 { + max-height: 15rem; +} + +.min-h-full { + min-height: 100%; +} + +.w-full { + width: 100%; +} + +.w-10 { + width: 2.5rem; +} + +.w-6 { + width: 1.5rem; +} + +.w-auto { + width: auto; +} + +.w-14 { + width: 3.5rem; +} + +.w-5 { + width: 1.25rem; +} + +.w-48 { + width: 12rem; +} + +.w-8 { + width: 2rem; +} + +.w-4 { + width: 1rem; +} + +.w-16 { + width: 4rem; +} + +.w-12 { + width: 3rem; +} + +.w-0\.5 { + width: 0.125rem; +} + +.w-0 { + width: 0px; +} + +.min-w-0 { + min-width: 0px; +} + +.min-w-full { + min-width: 100%; +} + +.max-w-xs { + max-width: 20rem; +} + +.max-w-7xl { + max-width: 80rem; +} + +.max-w-3xl { + max-width: 48rem; +} + +.max-w-2xl { + max-width: 42rem; +} + +.max-w-lg { + max-width: 32rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.flex-shrink-0 { + flex-shrink: 0; +} + +.shrink { + flex-shrink: 1; +} + +.flex-grow { + flex-grow: 1; +} + +.origin-top-right { + transform-origin: top right; +} + +.-translate-x-full { + --tw-translate-x: -100%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.translate-x-0 { + --tw-translate-x: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.scale-95 { + --tw-scale-x: .95; + --tw-scale-y: .95; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.scale-100 { + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.cursor-default { + cursor: default; +} + +.cursor-pointer { + cursor: pointer; +} + +.select-none { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.grid-cols-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.flex-row { + flex-direction: row; +} + +.flex-col { + flex-direction: column; +} + +.flex-col-reverse { + flex-direction: column-reverse; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.items-start { + align-items: flex-start; +} + +.items-center { + align-items: center; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-6 { + gap: 1.5rem; +} + +.gap-5 { + gap: 1.25rem; +} + +.gap-4 { + gap: 1rem; +} + +.gap-x-4 { + -moz-column-gap: 1rem; + column-gap: 1rem; +} + +.gap-y-8 { + row-gap: 2rem; +} + +.space-y-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); +} + +.space-y-6 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + +.space-x-5 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1.25rem * var(--tw-space-x-reverse)); + margin-left: calc(1.25rem * calc(1 - var(--tw-space-x-reverse))); +} + +.-space-x-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(-0.25rem * var(--tw-space-x-reverse)); + margin-left: calc(-0.25rem * calc(1 - var(--tw-space-x-reverse))); +} + +.-space-y-px > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(-1px * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(-1px * var(--tw-space-y-reverse)); +} + +.space-x-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(2rem * var(--tw-space-x-reverse)); + margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.75rem * var(--tw-space-x-reverse)); + margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); +} + +.-space-x-px > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(-1px * var(--tw-space-x-reverse)); + margin-left: calc(-1px * calc(1 - var(--tw-space-x-reverse))); +} + +.space-y-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2rem * var(--tw-space-y-reverse)); +} + +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-6 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1.5rem * var(--tw-space-x-reverse)); + margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-y-reverse > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 1; +} + +.divide-y > :not([hidden]) ~ :not([hidden]) { + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); +} + +.divide-gray-200 > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-divide-opacity)); +} + +.divide-gray-300 > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-divide-opacity)); +} + +.overflow-auto { + overflow: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-x-auto { + overflow-x: auto; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-2xl { + border-radius: 1rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-co { + border-radius: 40%; +} + +.rounded-xl { + border-radius: 0.75rem; +} + +.rounded { + border-radius: 0.25rem; +} + +.rounded-3xl { + border-radius: 1.5rem; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-l-3xl { + border-top-left-radius: 1.5rem; + border-bottom-left-radius: 1.5rem; +} + +.rounded-r-3xl { + border-top-right-radius: 1.5rem; + border-bottom-right-radius: 1.5rem; +} + +.rounded-l-md { + border-top-left-radius: 0.375rem; + border-bottom-left-radius: 0.375rem; +} + +.rounded-r-md { + border-top-right-radius: 0.375rem; + border-bottom-right-radius: 0.375rem; +} + +.rounded-b-2xl { + border-bottom-right-radius: 1rem; + border-bottom-left-radius: 1rem; +} + +.border { + border-width: 1px; +} + +.border-2 { + border-width: 2px; +} + +.border-4 { + border-width: 4px; +} + +.border-r { + border-right-width: 1px; +} + +.border-t { + border-top-width: 1px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-b-2 { + border-bottom-width: 2px; +} + +.border-dashed { + border-style: dashed; +} + +.border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} + +.border-transparent { + border-color: transparent; +} + +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + +.border-co-red { + --tw-border-opacity: 1; + border-color: rgb(255 19 0 / var(--tw-border-opacity)); +} + +.border-indigo-500 { + --tw-border-opacity: 1; + border-color: rgb(99 102 241 / var(--tw-border-opacity)); +} + +.border-co-blue { + --tw-border-opacity: 1; + border-color: rgb(36 56 135 / var(--tw-border-opacity)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.bg-gray-600 { + --tw-bg-opacity: 1; + background-color: rgb(75 85 99 / var(--tw-bg-opacity)); +} + +.bg-co-blue { + --tw-bg-opacity: 1; + background-color: rgb(36 56 135 / var(--tw-bg-opacity)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.bg-co-green { + --tw-bg-opacity: 1; + background-color: rgb(108 193 31 / var(--tw-bg-opacity)); +} + +.bg-co-red { + --tw-bg-opacity: 1; + background-color: rgb(255 19 0 / var(--tw-bg-opacity)); +} + +.bg-co-yellow { + --tw-bg-opacity: 1; + background-color: rgb(255 221 0 / var(--tw-bg-opacity)); +} + +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.bg-gray-400 { + --tw-bg-opacity: 1; + background-color: rgb(156 163 175 / var(--tw-bg-opacity)); +} + +.bg-blue-500 { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.bg-green-500 { + --tw-bg-opacity: 1; + background-color: rgb(34 197 94 / var(--tw-bg-opacity)); +} + +.bg-blue-600 { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity)); +} + +.bg-green-100 { + --tw-bg-opacity: 1; + background-color: rgb(220 252 231 / var(--tw-bg-opacity)); +} + +.bg-indigo-50 { + --tw-bg-opacity: 1; + background-color: rgb(238 242 255 / var(--tw-bg-opacity)); +} + +.bg-gray-300 { + --tw-bg-opacity: 1; + background-color: rgb(209 213 219 / var(--tw-bg-opacity)); +} + +.bg-indigo-600 { + --tw-bg-opacity: 1; + background-color: rgb(79 70 229 / var(--tw-bg-opacity)); +} + +.bg-opacity-75 { + --tw-bg-opacity: 0.75; +} + +.p-4 { + padding: 1rem; +} + +.p-6 { + padding: 1.5rem; +} + +.p-2 { + padding: 0.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.py-5 { + padding-top: 1.25rem; + padding-bottom: 1.25rem; +} + +.py-10 { + padding-top: 2.5rem; + padding-bottom: 2.5rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-12 { + padding-top: 3rem; + padding-bottom: 3rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.px-1 { + padding-left: 0.25rem; + padding-right: 0.25rem; +} + +.py-3\.5 { + padding-top: 0.875rem; + padding-bottom: 0.875rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.py-0\.5 { + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +.py-0 { + padding-top: 0px; + padding-bottom: 0px; +} + +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.pt-5 { + padding-top: 1.25rem; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pt-2 { + padding-top: 0.5rem; +} + +.pl-8 { + padding-left: 2rem; +} + +.pr-3 { + padding-right: 0.75rem; +} + +.pl-3 { + padding-left: 0.75rem; +} + +.pr-9 { + padding-right: 2.25rem; +} + +.pl-1 { + padding-left: 0.25rem; +} + +.pr-10 { + padding-right: 2.5rem; +} + +.pl-4 { + padding-left: 1rem; +} + +.pb-8 { + padding-bottom: 2rem; +} + +.pt-1\.5 { + padding-top: 0.375rem; +} + +.pt-1 { + padding-top: 0.25rem; +} + +.pr-4 { + padding-right: 1rem; +} + +.pr-2 { + padding-right: 0.5rem; +} + +.pt-8 { + padding-top: 2rem; +} + +.pl-1\.5 { + padding-left: 0.375rem; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.align-middle { + vertical-align: middle; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.font-medium { + font-weight: 500; +} + +.font-normal { + font-weight: 400; +} + +.font-semibold { + font-weight: 600; +} + +.font-bold { + font-weight: 700; +} + +.font-extrabold { + font-weight: 800; +} + +.uppercase { + text-transform: uppercase; +} + +.capitalize { + text-transform: capitalize; +} + +.leading-6 { + line-height: 1.5rem; +} + +.leading-4 { + line-height: 1rem; +} + +.leading-5 { + line-height: 1.25rem; +} + +.tracking-wide { + letter-spacing: 0.025em; +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + +.text-co-blue { + --tw-text-opacity: 1; + color: rgb(36 56 135 / var(--tw-text-opacity)); +} + +.text-co-red { + --tw-text-opacity: 1; + color: rgb(255 19 0 / var(--tw-text-opacity)); +} + +.text-indigo-600 { + --tw-text-opacity: 1; + color: rgb(79 70 229 / var(--tw-text-opacity)); +} + +.text-green-800 { + --tw-text-opacity: 1; + color: rgb(22 101 52 / var(--tw-text-opacity)); +} + +.text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} + +.placeholder-gray-500::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(107 114 128 / var(--tw-placeholder-opacity)); +} + +.placeholder-gray-500:-ms-input-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(107 114 128 / var(--tw-placeholder-opacity)); +} + +.placeholder-gray-500::placeholder { + --tw-placeholder-opacity: 1; + color: rgb(107 114 128 / var(--tw-placeholder-opacity)); +} + +.opacity-0 { + opacity: 0; +} + +.opacity-100 { + opacity: 1; +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-sm { + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-inner { + --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.ring-1 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.ring-2 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.ring-8 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.ring-black { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity)); +} + +.ring-white { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); +} + +.ring-opacity-5 { + --tw-ring-opacity: 0.05; +} + +.blur { + --tw-blur: blur(8px); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition { + transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-text-decoration-color, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.duration-300 { + transition-duration: 300ms; +} + +.duration-100 { + transition-duration: 100ms; +} + +.duration-75 { + transition-duration: 75ms; +} + +.ease-linear { + transition-timing-function: linear; +} + +.ease-in-out { + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} + +.ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} + +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} + +@font-face { + font-family: "Manometer"; + + src: url("https://coopgo.fr/fonts/manometer.woff2") format("woff2"), url("/fonts/manometer.woff") format("woff"); +} + +@font-face { + font-family: "Bitter"; + + font-style: normal; + + src: url("https://coopgo.fr/fonts/Bitter-Regular.woff") format("woff"); +} + +.focus-within\:text-gray-600:focus-within { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} + +.focus-within\:ring-2:focus-within { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus-within\:ring-co-blue:focus-within { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(36 56 135 / var(--tw-ring-opacity)); +} + +.focus-within\:ring-offset-2:focus-within { + --tw-ring-offset-width: 2px; +} + +.hover\:border-gray-300:hover { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + +.hover\:bg-gray-50:hover { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-200:hover { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.hover\:bg-white:hover { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.hover\:bg-co-blue:hover { + --tw-bg-opacity: 1; + background-color: rgb(36 56 135 / var(--tw-bg-opacity)); +} + +.hover\:bg-blue-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(29 78 216 / var(--tw-bg-opacity)); +} + +.hover\:bg-indigo-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(67 56 202 / var(--tw-bg-opacity)); +} + +.hover\:bg-opacity-5:hover { + --tw-bg-opacity: 0.05; +} + +.hover\:text-gray-600:hover { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} + +.hover\:text-white:hover { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.hover\:text-gray-700:hover { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + +.hover\:text-indigo-900:hover { + --tw-text-opacity: 1; + color: rgb(49 46 129 / var(--tw-text-opacity)); +} + +.hover\:text-gray-900:hover { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + +.hover\:text-co-blue:hover { + --tw-text-opacity: 1; + color: rgb(36 56 135 / var(--tw-text-opacity)); +} + +.hover\:text-inherit:hover { + color: inherit; +} + +.focus\:border-transparent:focus { + border-color: transparent; +} + +.focus\:border-co-blue:focus { + --tw-border-opacity: 1; + border-color: rgb(36 56 135 / var(--tw-border-opacity)); +} + +.focus\:border-indigo-500:focus { + --tw-border-opacity: 1; + border-color: rgb(99 102 241 / var(--tw-border-opacity)); +} + +.focus\:border-blue-500:focus { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.focus\:placeholder-gray-400:focus::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + +.focus\:placeholder-gray-400:focus:-ms-input-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + +.focus\:placeholder-gray-400:focus::placeholder { + --tw-placeholder-opacity: 1; + color: rgb(156 163 175 / var(--tw-placeholder-opacity)); +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:ring-2:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-0:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-1:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-inset:focus { + --tw-ring-inset: inset; +} + +.focus\:ring-white:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); +} + +.focus\:ring-co-blue:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(36 56 135 / var(--tw-ring-opacity)); +} + +.focus\:ring-indigo-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity)); +} + +.focus\:ring-blue-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); +} + +.focus\:ring-offset-2:focus { + --tw-ring-offset-width: 2px; +} + +.focus\:ring-offset-gray-100:focus { + --tw-ring-offset-color: #f3f4f6; +} + +.group:hover .group-hover\:text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +@media (min-width: 640px) { + .sm\:col-span-3 { + grid-column: span 3 / span 3; + } + + .sm\:col-span-4 { + grid-column: span 4 / span 4; + } + + .sm\:col-span-2 { + grid-column: span 2 / span 2; + } + + .sm\:col-span-1 { + grid-column: span 1 / span 1; + } + + .sm\:mx-auto { + margin-left: auto; + margin-right: auto; + } + + .sm\:-mx-6 { + margin-left: -1.5rem; + margin-right: -1.5rem; + } + + .sm\:mt-0 { + margin-top: 0px; + } + + .sm\:ml-16 { + margin-left: 4rem; + } + + .sm\:ml-5 { + margin-left: 1.25rem; + } + + .sm\:block { + display: block; + } + + .sm\:flex { + display: flex; + } + + .sm\:hidden { + display: none; + } + + .sm\:w-auto { + width: auto; + } + + .sm\:w-full { + width: 100%; + } + + .sm\:max-w-md { + max-width: 28rem; + } + + .sm\:max-w-xs { + max-width: 20rem; + } + + .sm\:flex-auto { + flex: 1 1 auto; + } + + .sm\:flex-none { + flex: none; + } + + .sm\:flex-1 { + flex: 1 1 0%; + } + + .sm\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .sm\:grid-cols-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .sm\:flex-row-reverse { + flex-direction: row-reverse; + } + + .sm\:flex-nowrap { + flex-wrap: nowrap; + } + + .sm\:items-center { + align-items: center; + } + + .sm\:justify-end { + justify-content: flex-end; + } + + .sm\:justify-between { + justify-content: space-between; + } + + .sm\:gap-6 { + gap: 1.5rem; + } + + .sm\:space-y-0 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0px * var(--tw-space-y-reverse)); + } + + .sm\:space-x-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.75rem * var(--tw-space-x-reverse)); + margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); + } + + .sm\:space-x-reverse > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 1; + } + + .sm\:overflow-hidden { + overflow: hidden; + } + + .sm\:rounded-lg { + border-radius: 0.5rem; + } + + .sm\:rounded-3xl { + border-radius: 1.5rem; + } + + .sm\:p-6 { + padding: 1.5rem; + } + + .sm\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + .sm\:pl-6 { + padding-left: 1.5rem; + } + + .sm\:pr-6 { + padding-right: 1.5rem; + } + + .sm\:text-sm { + font-size: 0.875rem; + line-height: 1.25rem; + } +} + +@media (min-width: 768px) { + .md\:fixed { + position: fixed; + } + + .md\:inset-y-0 { + top: 0px; + bottom: 0px; + } + + .md\:col-span-1 { + grid-column: span 1 / span 1; + } + + .md\:col-span-2 { + grid-column: span 2 / span 2; + } + + .md\:ml-0 { + margin-left: 0px; + } + + .md\:ml-6 { + margin-left: 1.5rem; + } + + .md\:mt-0 { + margin-top: 0px; + } + + .md\:flex { + display: flex; + } + + .md\:grid { + display: grid; + } + + .md\:hidden { + display: none; + } + + .md\:w-64 { + width: 16rem; + } + + .md\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .md\:grid-cols-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .md\:flex-row { + flex-direction: row; + } + + .md\:flex-col { + flex-direction: column; + } + + .md\:items-center { + align-items: center; + } + + .md\:justify-between { + justify-content: space-between; + } + + .md\:gap-6 { + gap: 1.5rem; + } + + .md\:space-x-5 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1.25rem * var(--tw-space-x-reverse)); + margin-left: calc(1.25rem * calc(1 - var(--tw-space-x-reverse))); + } + + .md\:space-x-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.75rem * var(--tw-space-x-reverse)); + margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); + } + + .md\:rounded-lg { + border-radius: 0.5rem; + } + + .md\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } + + .md\:px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; + } + + .md\:pl-64 { + padding-left: 16rem; + } + + .md\:pl-4 { + padding-left: 1rem; + } + + .md\:pr-6 { + padding-right: 1.5rem; + } + + .md\:pl-0 { + padding-left: 0px; + } + + .md\:text-right { + text-align: right; + } +} + +@media (min-width: 1024px) { + .lg\:col-span-2 { + grid-column: span 2 / span 2; + } + + .lg\:col-span-1 { + grid-column: span 1 / span 1; + } + + .lg\:col-start-1 { + grid-column-start: 1; + } + + .lg\:col-start-3 { + grid-column-start: 3; + } + + .lg\:-mx-8 { + margin-left: -2rem; + margin-right: -2rem; + } + + .lg\:max-w-7xl { + max-width: 80rem; + } + + .lg\:grid-flow-col-dense { + grid-auto-flow: column dense; + } + + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .lg\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .lg\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } +} \ No newline at end of file diff --git a/themes/default/public/images/parcoursmob_logo_whitered.svg b/themes/default/public/images/parcoursmob_logo_whitered.svg new file mode 100644 index 0000000..d267bdd --- /dev/null +++ b/themes/default/public/images/parcoursmob_logo_whitered.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/default/public/js/main.js b/themes/default/public/js/main.js new file mode 100644 index 0000000..c1c927c --- /dev/null +++ b/themes/default/public/js/main.js @@ -0,0 +1,2995 @@ +(() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + + // ../../../../../../node_modules/@kingshott/iodine/dist/iodine.min.js + var require_iodine_min = __commonJS({ + "../../../../../../node_modules/@kingshott/iodine/dist/iodine.min.js"(exports, module) { + var e = class { + constructor() { + this.locale = void 0, this.messages = { after: "The date must be after: '[PARAM]'", afterOrEqual: "The date must be after or equal to: '[PARAM]'", array: "[FIELD] must be an array", before: "The date must be before: '[PARAM]'", beforeOrEqual: "The date must be before or equal to: '[PARAM]'", boolean: "[FIELD] must be true or false", date: "[FIELD] must be a date", different: "[FIELD] must be different to '[PARAM]'", endsWith: "[FIELD] must end with '[PARAM]'", email: "[FIELD] must be a valid email address", falsy: "[FIELD] must be a falsy value (false, 'false', 0 or '0')", in: "[FIELD] must be one of the following options: [PARAM]", integer: "[FIELD] must be an integer", json: "[FIELD] must be a parsable JSON object string", max: "[FIELD] must be less than or equal to [PARAM]", min: "[FIELD] must be greater than or equal to [PARAM]", maxLength: "[FIELD] must not be greater than '[PARAM]' in character length", minLength: "[FIELD] must not be less than '[PARAM]' character length", notIn: "[FIELD] must not be one of the following options: [PARAM]", numeric: "[FIELD] must be numeric", optional: "[FIELD] is optional", regexMatch: "[FIELD] must satisify the regular expression: [PARAM]", required: "[FIELD] must be present", same: "[FIELD] must be '[PARAM]'", startsWith: "[FIELD] must start with '[PARAM]'", string: "[FIELD] must be a string", truthy: "[FIELD] must be a truthy value (true, 'true', 1 or '1')", url: "[FIELD] must be a valid url", uuid: "[FIELD] must be a valid UUID" }; + } + _compare(e2, t, r, s = false) { + return !!this.assertDate(e2) && !(!this.assertDate(t) && !this.assertInteger(t)) && (t = "number" == typeof t ? t : t.getTime(), "less" === r && s ? e2.getTime() <= t : "less" !== r || s ? "more" === r && s ? e2.getTime() >= t : "more" !== r || s ? void 0 : e2.getTime() > t : e2.getTime() < t); + } + _error(e2, t) { + let { param: r, field: s } = "object" == typeof t ? t : { param: t, field: void 0 }; + const a = e2.split(":"); + let i = a.shift(); + r = r || a.join(":"), ["after", "afterOrEqual", "before", "beforeOrEqual"].includes(i) && (r = new Date(parseInt(r)).toLocaleTimeString(this.locale, { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "numeric", hour12: false })); + let n = [null, void 0, ""].includes(r) ? this.messages[i] : this.messages[i].replace("[PARAM]", r); + return [null, void 0, ""].includes(s) ? n.replace("[FIELD]", this.default_field_name ?? "Value") : n.replace("[FIELD]", s); + } + _missing() { + return { valid: false, rule: "None", error: "Rules exist, but no value was provided to check" }; + } + _prepare(e2, t = []) { + return t.length ? "optional" === t[0] && this.assertOptional(e2) ? [] : t.filter((e3) => "optional" !== e3).map((e3) => "string" == typeof e3 ? [e3, this._title(e3.split(":").shift()), e3.split(":").slice(1).join(":")] : [`${e3.rule}:${e3.param}`, this._title(e3.rule), e3.param]) : []; + } + _title(e2) { + return `${e2[0].toUpperCase()}${e2.slice(1)}`; + } + _validate(e2, t) { + for (let r in t = this._prepare(e2, t)) + if (!this[`assert${t[r][1]}`].apply(this, [e2, t[r][2]])) + return { valid: false, rule: t[r][0], error: this._error(t[r][0]) }; + return { valid: true, rule: "", error: "" }; + } + assert(e2, t) { + if (Array.isArray(t)) + return this._validate(e2, t); + let r = Object.keys(t), s = { valid: true, fields: {} }; + for (let a = 0; a < r.length; a++) + s.fields[r[a]] = e2.hasOwnProperty(r[a]) ? this._validate(e2[r[a]], t[r[a]]) : this._missing(), s.fields[r[a]].valid || (s.valid = false); + return s; + } + assertAfter(e2, t) { + return this._compare(e2, t, "more", false); + } + assertAfterOrEqual(e2, t) { + return this._compare(e2, t, "more", true); + } + assertArray(e2) { + return Array.isArray(e2); + } + assertBefore(e2, t) { + return this._compare(e2, t, "less", false); + } + assertBeforeOrEqual(e2, t) { + return this._compare(e2, t, "less", true); + } + assertBoolean(e2) { + return [true, false].includes(e2); + } + assertDate(e2) { + return e2 && "[object Date]" === Object.prototype.toString.call(e2) && !isNaN(e2); + } + assertDifferent(e2, t) { + return e2 != t; + } + assertEndsWith(e2, t) { + return this.assertString(e2) && e2.endsWith(t); + } + assertEmail(e2) { + return new RegExp("^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$").test(String(e2).toLowerCase()); + } + assertFalsy(e2) { + return [0, "0", false, "false"].includes(e2); + } + assertIn(e2, t) { + return ("string" == typeof t ? t.split(",") : t).includes(e2); + } + assertInteger(e2) { + return Number.isInteger(e2) && parseInt(e2).toString() === e2.toString(); + } + assertJson(e2) { + try { + return "object" == typeof JSON.parse(e2); + } catch (e3) { + return false; + } + } + assertMax(e2, t) { + return parseFloat(e2) <= t; + } + assertMin(e2, t) { + return parseFloat(e2) >= t; + } + assertMaxLength(e2, t) { + return "string" == typeof e2 && e2.length <= t; + } + assertMinLength(e2, t) { + return "string" == typeof e2 && e2.length >= t; + } + assertNotIn(e2, t) { + return !this.assertIn(e2, t); + } + assertNumeric(e2) { + return !isNaN(parseFloat(e2)) && isFinite(e2); + } + assertOptional(e2) { + return [null, void 0, ""].includes(e2); + } + assertRegexMatch(e2, t) { + return new RegExp(t).test(String(e2)); + } + assertRequired(e2) { + return !this.assertOptional(e2); + } + assertSame(e2, t) { + return e2 == t; + } + assertStartsWith(e2, t) { + return this.assertString(e2) && e2.startsWith(t); + } + assertString(e2) { + return "string" == typeof e2; + } + assertTruthy(e2) { + return [1, "1", true, "true"].includes(e2); + } + assertUrl(e2) { + return new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$").test(String(e2).toLowerCase()); + } + assertUuid(e2) { + return new RegExp("^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$").test(String(e2).toLowerCase()); + } + rule(t, r) { + e.prototype[`assert${this._title(t)}`] = r; + } + setErrorMessages(e2) { + this.messages = e2; + } + setErrorMessage(e2, t) { + this.messages[e2] = t; + } + setLocale(e2) { + this.locale = e2; + } + setDefaultFieldName(e2) { + this.default_field_name = e2; + } + }; + "undefined" != typeof window && (window.Iodine = new e()), module.exports = e; + } + }); + + // assets/js/main.js + var import_iodine = __toESM(require_iodine_min()); + + // ../../../../../../node_modules/alpinejs/dist/module.esm.js + var flushPending = false; + var flushing = false; + var queue = []; + function scheduler(callback) { + queueJob(callback); + } + function queueJob(job) { + if (!queue.includes(job)) + queue.push(job); + queueFlush(); + } + function dequeueJob(job) { + let index = queue.indexOf(job); + if (index !== -1) + queue.splice(index, 1); + } + function queueFlush() { + if (!flushing && !flushPending) { + flushPending = true; + queueMicrotask(flushJobs); + } + } + function flushJobs() { + flushPending = false; + flushing = true; + for (let i = 0; i < queue.length; i++) { + queue[i](); + } + queue.length = 0; + flushing = false; + } + var reactive; + var effect; + var release; + var raw; + var shouldSchedule = true; + function disableEffectScheduling(callback) { + shouldSchedule = false; + callback(); + shouldSchedule = true; + } + function setReactivityEngine(engine) { + reactive = engine.reactive; + release = engine.release; + effect = (callback) => engine.effect(callback, { scheduler: (task) => { + if (shouldSchedule) { + scheduler(task); + } else { + task(); + } + } }); + raw = engine.raw; + } + function overrideEffect(override) { + effect = override; + } + function elementBoundEffect(el) { + let cleanup2 = () => { + }; + let wrappedEffect = (callback) => { + let effectReference = effect(callback); + if (!el._x_effects) { + el._x_effects = /* @__PURE__ */ new Set(); + el._x_runEffects = () => { + el._x_effects.forEach((i) => i()); + }; + } + el._x_effects.add(effectReference); + cleanup2 = () => { + if (effectReference === void 0) + return; + el._x_effects.delete(effectReference); + release(effectReference); + }; + return effectReference; + }; + return [wrappedEffect, () => { + cleanup2(); + }]; + } + var onAttributeAddeds = []; + var onElRemoveds = []; + var onElAddeds = []; + function onElAdded(callback) { + onElAddeds.push(callback); + } + function onElRemoved(el, callback) { + if (typeof callback === "function") { + if (!el._x_cleanups) + el._x_cleanups = []; + el._x_cleanups.push(callback); + } else { + callback = el; + onElRemoveds.push(callback); + } + } + function onAttributesAdded(callback) { + onAttributeAddeds.push(callback); + } + function onAttributeRemoved(el, name, callback) { + if (!el._x_attributeCleanups) + el._x_attributeCleanups = {}; + if (!el._x_attributeCleanups[name]) + el._x_attributeCleanups[name] = []; + el._x_attributeCleanups[name].push(callback); + } + function cleanupAttributes(el, names) { + if (!el._x_attributeCleanups) + return; + Object.entries(el._x_attributeCleanups).forEach(([name, value]) => { + if (names === void 0 || names.includes(name)) { + value.forEach((i) => i()); + delete el._x_attributeCleanups[name]; + } + }); + } + var observer = new MutationObserver(onMutate); + var currentlyObserving = false; + function startObservingMutations() { + observer.observe(document, { subtree: true, childList: true, attributes: true, attributeOldValue: true }); + currentlyObserving = true; + } + function stopObservingMutations() { + flushObserver(); + observer.disconnect(); + currentlyObserving = false; + } + var recordQueue = []; + var willProcessRecordQueue = false; + function flushObserver() { + recordQueue = recordQueue.concat(observer.takeRecords()); + if (recordQueue.length && !willProcessRecordQueue) { + willProcessRecordQueue = true; + queueMicrotask(() => { + processRecordQueue(); + willProcessRecordQueue = false; + }); + } + } + function processRecordQueue() { + onMutate(recordQueue); + recordQueue.length = 0; + } + function mutateDom(callback) { + if (!currentlyObserving) + return callback(); + stopObservingMutations(); + let result = callback(); + startObservingMutations(); + return result; + } + var isCollecting = false; + var deferredMutations = []; + function deferMutations() { + isCollecting = true; + } + function flushAndStopDeferringMutations() { + isCollecting = false; + onMutate(deferredMutations); + deferredMutations = []; + } + function onMutate(mutations) { + if (isCollecting) { + deferredMutations = deferredMutations.concat(mutations); + return; + } + let addedNodes = []; + let removedNodes = []; + let addedAttributes = /* @__PURE__ */ new Map(); + let removedAttributes = /* @__PURE__ */ new Map(); + for (let i = 0; i < mutations.length; i++) { + if (mutations[i].target._x_ignoreMutationObserver) + continue; + if (mutations[i].type === "childList") { + mutations[i].addedNodes.forEach((node) => node.nodeType === 1 && addedNodes.push(node)); + mutations[i].removedNodes.forEach((node) => node.nodeType === 1 && removedNodes.push(node)); + } + if (mutations[i].type === "attributes") { + let el = mutations[i].target; + let name = mutations[i].attributeName; + let oldValue = mutations[i].oldValue; + let add2 = () => { + if (!addedAttributes.has(el)) + addedAttributes.set(el, []); + addedAttributes.get(el).push({ name, value: el.getAttribute(name) }); + }; + let remove = () => { + if (!removedAttributes.has(el)) + removedAttributes.set(el, []); + removedAttributes.get(el).push(name); + }; + if (el.hasAttribute(name) && oldValue === null) { + add2(); + } else if (el.hasAttribute(name)) { + remove(); + add2(); + } else { + remove(); + } + } + } + removedAttributes.forEach((attrs, el) => { + cleanupAttributes(el, attrs); + }); + addedAttributes.forEach((attrs, el) => { + onAttributeAddeds.forEach((i) => i(el, attrs)); + }); + for (let node of removedNodes) { + if (addedNodes.includes(node)) + continue; + onElRemoveds.forEach((i) => i(node)); + if (node._x_cleanups) { + while (node._x_cleanups.length) + node._x_cleanups.pop()(); + } + } + addedNodes.forEach((node) => { + node._x_ignoreSelf = true; + node._x_ignore = true; + }); + for (let node of addedNodes) { + if (removedNodes.includes(node)) + continue; + if (!node.isConnected) + continue; + delete node._x_ignoreSelf; + delete node._x_ignore; + onElAddeds.forEach((i) => i(node)); + node._x_ignore = true; + node._x_ignoreSelf = true; + } + addedNodes.forEach((node) => { + delete node._x_ignoreSelf; + delete node._x_ignore; + }); + addedNodes = null; + removedNodes = null; + addedAttributes = null; + removedAttributes = null; + } + function scope(node) { + return mergeProxies(closestDataStack(node)); + } + function addScopeToNode(node, data2, referenceNode) { + node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)]; + return () => { + node._x_dataStack = node._x_dataStack.filter((i) => i !== data2); + }; + } + function refreshScope(element, scope2) { + let existingScope = element._x_dataStack[0]; + Object.entries(scope2).forEach(([key, value]) => { + existingScope[key] = value; + }); + } + function closestDataStack(node) { + if (node._x_dataStack) + return node._x_dataStack; + if (typeof ShadowRoot === "function" && node instanceof ShadowRoot) { + return closestDataStack(node.host); + } + if (!node.parentNode) { + return []; + } + return closestDataStack(node.parentNode); + } + function mergeProxies(objects) { + let thisProxy = new Proxy({}, { + ownKeys: () => { + return Array.from(new Set(objects.flatMap((i) => Object.keys(i)))); + }, + has: (target, name) => { + return objects.some((obj) => obj.hasOwnProperty(name)); + }, + get: (target, name) => { + return (objects.find((obj) => { + if (obj.hasOwnProperty(name)) { + let descriptor = Object.getOwnPropertyDescriptor(obj, name); + if (descriptor.get && descriptor.get._x_alreadyBound || descriptor.set && descriptor.set._x_alreadyBound) { + return true; + } + if ((descriptor.get || descriptor.set) && descriptor.enumerable) { + let getter = descriptor.get; + let setter = descriptor.set; + let property = descriptor; + getter = getter && getter.bind(thisProxy); + setter = setter && setter.bind(thisProxy); + if (getter) + getter._x_alreadyBound = true; + if (setter) + setter._x_alreadyBound = true; + Object.defineProperty(obj, name, { + ...property, + get: getter, + set: setter + }); + } + return true; + } + return false; + }) || {})[name]; + }, + set: (target, name, value) => { + let closestObjectWithKey = objects.find((obj) => obj.hasOwnProperty(name)); + if (closestObjectWithKey) { + closestObjectWithKey[name] = value; + } else { + objects[objects.length - 1][name] = value; + } + return true; + } + }); + return thisProxy; + } + function initInterceptors(data2) { + let isObject2 = (val) => typeof val === "object" && !Array.isArray(val) && val !== null; + let recurse = (obj, basePath = "") => { + Object.entries(Object.getOwnPropertyDescriptors(obj)).forEach(([key, { value, enumerable }]) => { + if (enumerable === false || value === void 0) + return; + let path = basePath === "" ? key : `${basePath}.${key}`; + if (typeof value === "object" && value !== null && value._x_interceptor) { + obj[key] = value.initialize(data2, path, key); + } else { + if (isObject2(value) && value !== obj && !(value instanceof Element)) { + recurse(value, path); + } + } + }); + }; + return recurse(data2); + } + function interceptor(callback, mutateObj = () => { + }) { + let obj = { + initialValue: void 0, + _x_interceptor: true, + initialize(data2, path, key) { + return callback(this.initialValue, () => get(data2, path), (value) => set(data2, path, value), path, key); + } + }; + mutateObj(obj); + return (initialValue) => { + if (typeof initialValue === "object" && initialValue !== null && initialValue._x_interceptor) { + let initialize = obj.initialize.bind(obj); + obj.initialize = (data2, path, key) => { + let innerValue = initialValue.initialize(data2, path, key); + obj.initialValue = innerValue; + return initialize(data2, path, key); + }; + } else { + obj.initialValue = initialValue; + } + return obj; + }; + } + function get(obj, path) { + return path.split(".").reduce((carry, segment) => carry[segment], obj); + } + function set(obj, path, value) { + if (typeof path === "string") + path = path.split("."); + if (path.length === 1) + obj[path[0]] = value; + else if (path.length === 0) + throw error; + else { + if (obj[path[0]]) + return set(obj[path[0]], path.slice(1), value); + else { + obj[path[0]] = {}; + return set(obj[path[0]], path.slice(1), value); + } + } + } + var magics = {}; + function magic(name, callback) { + magics[name] = callback; + } + function injectMagics(obj, el) { + Object.entries(magics).forEach(([name, callback]) => { + Object.defineProperty(obj, `$${name}`, { + get() { + let [utilities, cleanup2] = getElementBoundUtilities(el); + utilities = { interceptor, ...utilities }; + onElRemoved(el, cleanup2); + return callback(el, utilities); + }, + enumerable: false + }); + }); + return obj; + } + function tryCatch(el, expression, callback, ...args) { + try { + return callback(...args); + } catch (e) { + handleError(e, el, expression); + } + } + function handleError(error2, el, expression = void 0) { + Object.assign(error2, { el, expression }); + console.warn(`Alpine Expression Error: ${error2.message} + +${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); + setTimeout(() => { + throw error2; + }, 0); + } + var shouldAutoEvaluateFunctions = true; + function dontAutoEvaluateFunctions(callback) { + let cache = shouldAutoEvaluateFunctions; + shouldAutoEvaluateFunctions = false; + callback(); + shouldAutoEvaluateFunctions = cache; + } + function evaluate(el, expression, extras = {}) { + let result; + evaluateLater(el, expression)((value) => result = value, extras); + return result; + } + function evaluateLater(...args) { + return theEvaluatorFunction(...args); + } + var theEvaluatorFunction = normalEvaluator; + function setEvaluator(newEvaluator) { + theEvaluatorFunction = newEvaluator; + } + function normalEvaluator(el, expression) { + let overriddenMagics = {}; + injectMagics(overriddenMagics, el); + let dataStack = [overriddenMagics, ...closestDataStack(el)]; + if (typeof expression === "function") { + return generateEvaluatorFromFunction(dataStack, expression); + } + let evaluator = generateEvaluatorFromString(dataStack, expression, el); + return tryCatch.bind(null, el, expression, evaluator); + } + function generateEvaluatorFromFunction(dataStack, func) { + return (receiver = () => { + }, { scope: scope2 = {}, params = [] } = {}) => { + let result = func.apply(mergeProxies([scope2, ...dataStack]), params); + runIfTypeOfFunction(receiver, result); + }; + } + var evaluatorMemo = {}; + function generateFunctionFromString(expression, el) { + if (evaluatorMemo[expression]) { + return evaluatorMemo[expression]; + } + let AsyncFunction = Object.getPrototypeOf(async function() { + }).constructor; + let rightSideSafeExpression = /^[\n\s]*if.*\(.*\)/.test(expression) || /^(let|const)\s/.test(expression) ? `(() => { ${expression} })()` : expression; + const safeAsyncFunction = () => { + try { + return new AsyncFunction(["__self", "scope"], `with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`); + } catch (error2) { + handleError(error2, el, expression); + return Promise.resolve(); + } + }; + let func = safeAsyncFunction(); + evaluatorMemo[expression] = func; + return func; + } + function generateEvaluatorFromString(dataStack, expression, el) { + let func = generateFunctionFromString(expression, el); + return (receiver = () => { + }, { scope: scope2 = {}, params = [] } = {}) => { + func.result = void 0; + func.finished = false; + let completeScope = mergeProxies([scope2, ...dataStack]); + if (typeof func === "function") { + let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression)); + if (func.finished) { + runIfTypeOfFunction(receiver, func.result, completeScope, params, el); + func.result = void 0; + } else { + promise.then((result) => { + runIfTypeOfFunction(receiver, result, completeScope, params, el); + }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0); + } + } + }; + } + function runIfTypeOfFunction(receiver, value, scope2, params, el) { + if (shouldAutoEvaluateFunctions && typeof value === "function") { + let result = value.apply(scope2, params); + if (result instanceof Promise) { + result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value)); + } else { + receiver(result); + } + } else { + receiver(value); + } + } + var prefixAsString = "x-"; + function prefix(subject = "") { + return prefixAsString + subject; + } + function setPrefix(newPrefix) { + prefixAsString = newPrefix; + } + var directiveHandlers = {}; + function directive(name, callback) { + directiveHandlers[name] = callback; + } + function directives(el, attributes, originalAttributeOverride) { + attributes = Array.from(attributes); + if (el._x_virtualDirectives) { + let vAttributes = Object.entries(el._x_virtualDirectives).map(([name, value]) => ({ name, value })); + let staticAttributes = attributesOnly(vAttributes); + vAttributes = vAttributes.map((attribute) => { + if (staticAttributes.find((attr) => attr.name === attribute.name)) { + return { + name: `x-bind:${attribute.name}`, + value: `"${attribute.value}"` + }; + } + return attribute; + }); + attributes = attributes.concat(vAttributes); + } + let transformedAttributeMap = {}; + let directives2 = attributes.map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName)).filter(outNonAlpineAttributes).map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride)).sort(byPriority); + return directives2.map((directive2) => { + return getDirectiveHandler(el, directive2); + }); + } + function attributesOnly(attributes) { + return Array.from(attributes).map(toTransformedAttributes()).filter((attr) => !outNonAlpineAttributes(attr)); + } + var isDeferringHandlers = false; + var directiveHandlerStacks = /* @__PURE__ */ new Map(); + var currentHandlerStackKey = Symbol(); + function deferHandlingDirectives(callback) { + isDeferringHandlers = true; + let key = Symbol(); + currentHandlerStackKey = key; + directiveHandlerStacks.set(key, []); + let flushHandlers = () => { + while (directiveHandlerStacks.get(key).length) + directiveHandlerStacks.get(key).shift()(); + directiveHandlerStacks.delete(key); + }; + let stopDeferring = () => { + isDeferringHandlers = false; + flushHandlers(); + }; + callback(flushHandlers); + stopDeferring(); + } + function getElementBoundUtilities(el) { + let cleanups = []; + let cleanup2 = (callback) => cleanups.push(callback); + let [effect3, cleanupEffect] = elementBoundEffect(el); + cleanups.push(cleanupEffect); + let utilities = { + Alpine: alpine_default, + effect: effect3, + cleanup: cleanup2, + evaluateLater: evaluateLater.bind(evaluateLater, el), + evaluate: evaluate.bind(evaluate, el) + }; + let doCleanup = () => cleanups.forEach((i) => i()); + return [utilities, doCleanup]; + } + function getDirectiveHandler(el, directive2) { + let noop = () => { + }; + let handler3 = directiveHandlers[directive2.type] || noop; + let [utilities, cleanup2] = getElementBoundUtilities(el); + onAttributeRemoved(el, directive2.original, cleanup2); + let fullHandler = () => { + if (el._x_ignore || el._x_ignoreSelf) + return; + handler3.inline && handler3.inline(el, directive2, utilities); + handler3 = handler3.bind(handler3, el, directive2, utilities); + isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3(); + }; + fullHandler.runCleanups = cleanup2; + return fullHandler; + } + var startingWith = (subject, replacement) => ({ name, value }) => { + if (name.startsWith(subject)) + name = name.replace(subject, replacement); + return { name, value }; + }; + var into = (i) => i; + function toTransformedAttributes(callback = () => { + }) { + return ({ name, value }) => { + let { name: newName, value: newValue } = attributeTransformers.reduce((carry, transform) => { + return transform(carry); + }, { name, value }); + if (newName !== name) + callback(newName, name); + return { name: newName, value: newValue }; + }; + } + var attributeTransformers = []; + function mapAttributes(callback) { + attributeTransformers.push(callback); + } + function outNonAlpineAttributes({ name }) { + return alpineAttributeRegex().test(name); + } + var alpineAttributeRegex = () => new RegExp(`^${prefixAsString}([^:^.]+)\\b`); + function toParsedDirectives(transformedAttributeMap, originalAttributeOverride) { + return ({ name, value }) => { + let typeMatch = name.match(alpineAttributeRegex()); + let valueMatch = name.match(/:([a-zA-Z0-9\-:]+)/); + let modifiers = name.match(/\.[^.\]]+(?=[^\]]*$)/g) || []; + let original = originalAttributeOverride || transformedAttributeMap[name] || name; + return { + type: typeMatch ? typeMatch[1] : null, + value: valueMatch ? valueMatch[1] : null, + modifiers: modifiers.map((i) => i.replace(".", "")), + expression: value, + original + }; + }; + } + var DEFAULT = "DEFAULT"; + var directiveOrder = [ + "ignore", + "ref", + "data", + "id", + "bind", + "init", + "for", + "mask", + "model", + "modelable", + "transition", + "show", + "if", + DEFAULT, + "teleport" + ]; + function byPriority(a, b) { + let typeA = directiveOrder.indexOf(a.type) === -1 ? DEFAULT : a.type; + let typeB = directiveOrder.indexOf(b.type) === -1 ? DEFAULT : b.type; + return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB); + } + function dispatch(el, name, detail = {}) { + el.dispatchEvent(new CustomEvent(name, { + detail, + bubbles: true, + composed: true, + cancelable: true + })); + } + var tickStack = []; + var isHolding = false; + function nextTick(callback = () => { + }) { + queueMicrotask(() => { + isHolding || setTimeout(() => { + releaseNextTicks(); + }); + }); + return new Promise((res) => { + tickStack.push(() => { + callback(); + res(); + }); + }); + } + function releaseNextTicks() { + isHolding = false; + while (tickStack.length) + tickStack.shift()(); + } + function holdNextTicks() { + isHolding = true; + } + function walk(el, callback) { + if (typeof ShadowRoot === "function" && el instanceof ShadowRoot) { + Array.from(el.children).forEach((el2) => walk(el2, callback)); + return; + } + let skip = false; + callback(el, () => skip = true); + if (skip) + return; + let node = el.firstElementChild; + while (node) { + walk(node, callback, false); + node = node.nextElementSibling; + } + } + function warn(message, ...args) { + console.warn(`Alpine Warning: ${message}`, ...args); + } + function start() { + if (!document.body) + warn("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's `