commit 938328cd077d40b75e0834d56ff8d43ad035fd2b
parent 2f22780800915b5d5262aea1754ecce44f752db7
Author: f0x52 <f0x@cthu.lu>
Date: Thu, 29 Sep 2022 12:02:41 +0200
[frontend] Unified panels (#812)
* settings panel restructuring
* clean up old Gin handlers
* colorscheme redesign, some other small css tweaks
* basic router layout, error boundary
* colorscheme redesign, some other small css tweaks
* kebab-case consistency
* superfluous padding on applist
* remove unused consts
* redux, whitespace changes..
* use .jsx extensions for components
* login flow up till app registration
* full redux oauth implementation, with basic error handling
* split oauth api functions
* oauth api revocation handling
* basic profile change submission
* move old dir
* profile overview
* fix keeping track of the wrong instance url (for different instance/api domains)
* use redux state for profile form
* delete old/index.js, old/basic.js, fully implemented
* implement old/user/profile.js
* implement password change
* remove debug logging
* support future api for removing files
* customize profile css
* remove unneeded wrapper components
* restructure form fields
* start on admin pages
* admin panel settings
* admin settings panel
* remove old/admin files
* add top-level redirect
* refactor/cleanup forms
* only do API checks on logged-in state
* admin-status based routing
* federation block routing
* federation blocks
* upgrade dependencies
* react 18 changes
* media cleanup
* fix useEffect hooks
* remove unused require
* custom emoji base
* emoji uploader
* delete last old panel files
* sidebar styling, remove unused page
* refactor submit functions
* fix sidebar boxshadow-border
* fix old css variables
* fix fake-toot avatar
* fix non-square emoji
* fix user settings redux keys
* properly get admin account contact from instance response
* Account.source default values
* source.status_format key
* mobile responsiveness
* mobile element tweaks
* proper redirect after removing block
* add redirects for old setting panel urls
* deletes
* fix mobile overflow
* clean up debug logging calls
Diffstat:
62 files changed, 4272 insertions(+), 3099 deletions(-)
diff --git a/internal/web/panels.go b/internal/web/panels.go
@@ -1,77 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-package web
-
-import (
- "net/http"
-
- "github.com/gin-gonic/gin"
- "github.com/superseriousbusiness/gotosocial/internal/api"
- "github.com/superseriousbusiness/gotosocial/internal/config"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
-)
-
-func (m *Module) UserPanelHandler(c *gin.Context) {
- host := config.GetHost()
- instance, err := m.processor.InstanceGet(c.Request.Context(), host)
- if err != nil {
- api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
- return
- }
-
- c.HTML(http.StatusOK, "frontend.tmpl", gin.H{
- "instance": instance,
- "stylesheets": []string{
- assetsPathPrefix + "/Fork-Awesome/css/fork-awesome.min.css",
- assetsPathPrefix + "/dist/_colors.css",
- assetsPathPrefix + "/dist/base.css",
- assetsPathPrefix + "/dist/panels-base.css",
- assetsPathPrefix + "/dist/panels-user-style.css",
- },
- "javascript": []string{
- assetsPathPrefix + "/dist/bundle.js",
- assetsPathPrefix + "/dist/user-panel.js",
- },
- })
-}
-
-// TODO: abstract the {admin, user}panel handlers in some way
-func (m *Module) AdminPanelHandler(c *gin.Context) {
- host := config.GetHost()
- instance, err := m.processor.InstanceGet(c.Request.Context(), host)
- if err != nil {
- api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
- return
- }
-
- c.HTML(http.StatusOK, "frontend.tmpl", gin.H{
- "instance": instance,
- "stylesheets": []string{
- assetsPathPrefix + "/Fork-Awesome/css/fork-awesome.min.css",
- assetsPathPrefix + "/dist/_colors.css",
- assetsPathPrefix + "/dist/base.css",
- assetsPathPrefix + "/dist/panels-base.css",
- assetsPathPrefix + "/dist/panels-admin-style.css",
- },
- "javascript": []string{
- assetsPathPrefix + "/dist/bundle.js",
- assetsPathPrefix + "/dist/admin-panel.js",
- },
- })
-}
diff --git a/internal/web/profile.go b/internal/web/profile.go
@@ -117,6 +117,7 @@ func (m *Module) profileGETHandler(c *gin.Context) {
"show_back_to_top": showBackToTop,
"stylesheets": stylesheets,
"javascript": []string{
+ "/assets/dist/bundle.js",
"/assets/dist/frontend.js",
},
})
diff --git a/internal/web/settings-panel.go b/internal/web/settings-panel.go
@@ -0,0 +1,53 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package web
+
+import (
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+ "github.com/superseriousbusiness/gotosocial/internal/api"
+ "github.com/superseriousbusiness/gotosocial/internal/config"
+ "github.com/superseriousbusiness/gotosocial/internal/gtserror"
+)
+
+func (m *Module) SettingsPanelHandler(c *gin.Context) {
+ host := config.GetHost()
+ instance, err := m.processor.InstanceGet(c.Request.Context(), host)
+ if err != nil {
+ api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet)
+ return
+ }
+
+ c.HTML(http.StatusOK, "frontend.tmpl", gin.H{
+ "instance": instance,
+ "stylesheets": []string{
+ assetsPathPrefix + "/Fork-Awesome/css/fork-awesome.min.css",
+ assetsPathPrefix + "/dist/_colors.css",
+ assetsPathPrefix + "/dist/base.css",
+ assetsPathPrefix + "/dist/profile.css",
+ assetsPathPrefix + "/dist/status.css",
+ assetsPathPrefix + "/dist/settings-panel-style.css",
+ },
+ "javascript": []string{
+ assetsPathPrefix + "/dist/bundle.js",
+ assetsPathPrefix + "/dist/settings.js",
+ },
+ })
+}
diff --git a/internal/web/thread.go b/internal/web/thread.go
@@ -119,6 +119,7 @@ func (m *Module) threadGETHandler(c *gin.Context) {
"ogMeta": ogBase(instance).withStatus(status),
"stylesheets": stylesheets,
"javascript": []string{
+ "/assets/dist/bundle.js",
"/assets/dist/frontend.js",
},
})
diff --git a/internal/web/web.go b/internal/web/web.go
@@ -37,9 +37,9 @@ const (
profilePath = "/@:" + usernameKey
customCSSPath = profilePath + "/custom.css"
statusPath = profilePath + "/statuses/:" + statusIDKey
- adminPanelPath = "/admin"
- userPanelpath = "/user"
assetsPathPrefix = "/assets"
+ userPanelPath = "/settings/user"
+ adminPanelPath = "/settings/admin"
tokenParam = "token"
usernameKey = "username"
@@ -70,20 +70,24 @@ func (m *Module) Route(s router.Router) error {
assetsGroup := s.AttachGroup(assetsPathPrefix)
m.mountAssetsFilesystem(assetsGroup)
- s.AttachHandler(http.MethodGet, adminPanelPath, m.AdminPanelHandler)
- // redirect /admin/ to /admin
- s.AttachHandler(http.MethodGet, adminPanelPath+"/", func(c *gin.Context) {
- c.Redirect(http.StatusMovedPermanently, adminPanelPath)
+ s.AttachHandler(http.MethodGet, "/settings", m.SettingsPanelHandler)
+ s.AttachHandler(http.MethodGet, "/settings/*panel", m.SettingsPanelHandler)
+
+ // User panel redirects
+ // used by clients
+ s.AttachHandler(http.MethodGet, "/auth/edit", func(c *gin.Context) {
+ c.Redirect(http.StatusMovedPermanently, userPanelPath)
})
- s.AttachHandler(http.MethodGet, userPanelpath, m.UserPanelHandler)
- // redirect /user/ to /user
- s.AttachHandler(http.MethodGet, userPanelpath+"/", func(c *gin.Context) {
- c.Redirect(http.StatusMovedPermanently, userPanelpath)
+ // old version of settings panel
+ s.AttachHandler(http.MethodGet, "/user", func(c *gin.Context) {
+ c.Redirect(http.StatusMovedPermanently, userPanelPath)
})
- // redirect /auth/edit to /user
- s.AttachHandler(http.MethodGet, "/auth/edit", func(c *gin.Context) {
- c.Redirect(http.StatusMovedPermanently, userPanelpath)
+
+ // Admin panel redirects
+ // old version of settings panel
+ s.AttachHandler(http.MethodGet, "/admin", func(c *gin.Context) {
+ c.Redirect(http.StatusMovedPermanently, adminPanelPath)
})
// serve front-page
diff --git a/web/source/css/_colors.css b/web/source/css/_colors.css
@@ -23,57 +23,85 @@
/* Color definitions */
-$near_white: #fafaff;
+/* Foreground */
+$white1: #fafaff; /* default text color, contrast >= 5.0 with all $grays */
+$white2: #b3b5c6; /* less important text, can be used with $gray1 (6.8), $gray2 (5.5), $gray3 (4.9), $gray4 (4.5) */
-$sloth_gray1: #b0b0b5;
-$sloth_gray2: #4d4e56;
+/* Background shades, contrast >= 5.0 with $white1 (#fafaff) */
+$gray1: #2a2b2f;
+$gray2: #35363b;
+$gray3: #3a3b41;
+$gray4: #45464e;
+$gray5: #4d4e56;
+$gray6: #575861;
+$gray7: #5d5e67;
+$gray8: #696a75;
-$sloth_orange1: #e78e5a;
-$sloth_orange2: #D87841;
-$blue: #63b1de; // complementary color to $sloth_orange1
+$orange1: #fd6a00; /* Used for non-text accent colors, can be used as background: $gray1 for text color (contrast 4.6)*/
+$orange2: #ff853e; /* hover/selected accent to $orange1, can be used with $gray1 (5.7), $gray2 (4.6) */
-/* derivative colors */
+$blue1: #3a9fde; /* darker blue for smaller elements (borders), can only be used with $gray1 (4.7) */
+$blue2: #66befe; /* all-round accent color, can be used with $gray1 (6.8), $gray2 (5.5), $gray3 (4.9), $gray4 (4.5) */
+$blue3: #89caff; /* hover/selected accent to $blue2, can be used with $gray1 (7.9), $gray2 (6.3), $gray3 (5.6), $gray4 (5.2), $gray5 (4.7) */
-$sloth_gray2_darker3: color-mod($sloth_gray2 lightness(-3%));
-$sloth_gray2_darker5: color-mod($sloth_gray2 lightness(-5%));
-$sloth_gray2_darker7: color-mod($sloth_gray2 lightness(-7%));
-$sloth_gray2_darker15: color-mod($sloth_gray2 lightness(-15%));
-$sloth_gray2_lighter3: color-mod($sloth_gray2 lightness(+3%));
-$sloth_gray2_lighter5: color-mod($sloth_gray2 lightness(+5%));
+$error1: #860000; /* Error border/foreground text, can be used with $error2 (5.0), $white1 (10), $white2 (5.1) */
+$error2: #ff9796; /* Error background text, can be used with $error1 (5.0), $gray1 (6.6), $gray2 (5.3), $gray3 (4.8) */
+$error-link: #185F8C; /* Error link text, can be used with $error2 (5.54) */
-$blue_lighter8: color-mod($blue lightness(+4%));
-$lightblue: color-mod($blue lightness(+16%));
+$fg: $white1;
+$bg: $gray1;
-$fg: $near_white;
-$bg: $sloth_gray2_darker7;
+$bg-trans: color-mod($gray5 alpha(62%));
-$bg_trans: color-mod($sloth_gray2 alpha(62%));
-
-$bg_accent: $sloth_gray2_lighter3;
-$fg_accent: $lightblue;
-$border_accent: $sloth_orange2;
+$bg-accent: $gray5;
+$fg-accent: $blue3;
+$fg-reduced: $white2;
+$border-accent: $orange2;
/* Color variables as used in a specific location */
-$footer_bg: $bg_accent;
+$link-fg: $fg-accent;
+
+$button-bg: $blue2;
+$button-fg: $gray1;
+$button-hover-bg: $blue3;
-$link_fg: $fg_accent;
+$button-danger-bg: $orange1;
+$button-danger-fg: $gray1;
+$button-danger-hover-bg: $orange2;
-$button_border: 0.08rem solid color-mod($sloth_orange2 lightness(-15%));
-$button_bg: $blue_lighter8;
-$button_fg: $sloth_gray2_darker15;
-$button_hover_bg: $lightblue;
+$toot-focus-bg: $gray5;
+$toot-unfocus-bg: $gray3;
-$status_focus_bg: $bg_accent;
-$status_unfocus_bg: $sloth_gray2_darker3;
-$status_info_fg: #CBCBD7;
+$toot-info-bg: $gray4;
-$bg_no_img_desc: $sloth_orange2;
-$bg_sensitive: $sloth_gray2_darker15;
+$no-img-desc-bg: $orange1;
+$no-img-desc-fg: $gray1;
+
+$bg-sensitive: $gray1;
$boxshadow: 0 0.4rem 1rem -0.1rem rgba(0,0,0,0.15);
-$boxshadow_border: 0.08rem solid $sloth_gray2_darker5;
+$boxshadow-border: 0.08rem solid $gray1;
+
+$avatar-border: $orange2;
+
+$input-bg: $gray4;
+$input-disabled-bg: $gray2;
+$input-border: $blue1;
+$input-focus-border: $blue3;
+
+$settings-nav-bg: $bg-accent;
+$settings-nav-header-fg: $gray1;
+$settings-nav-header-bg: $orange1;
+
+$settings-nav-bg-hover: $gray3;
+/* $settings-nav-fg-hover: $gray1; */
+
+$settings-nav-bg-active: $gray2;
+/* $settings-nav-fg-active: $orange2; */
-$profile_avatar_border: 0.2rem solid $border_accent;
+$error-fg: $error1;
+$error-bg: $error2;
-$input_bg: $sloth_gray2_darker3;
-\ No newline at end of file
+$settings-entry-bg: $gray3;
+$settings-entry-hover-bg: $gray4;
+\ No newline at end of file
diff --git a/web/source/css/base.css b/web/source/css/base.css
@@ -34,7 +34,7 @@
$br: 0.4rem;
// border radius for items that are framed/bordered
// inside something with $br, eg avatar, header img
-$br_inner: 0.2rem;
+$br-inner: 0.2rem;
html, body {
padding: 0;
@@ -42,7 +42,7 @@ html, body {
background: $bg;
color: $fg;
font-family: "Noto Sans", sans-serif;
- scrollbar-color: $sloth_orange1 $sloth_gray2_darker3;
+ scrollbar-color: $orange1 $gray3;
}
body {
@@ -71,7 +71,7 @@ h1 {
}
a {
- color: $link_fg;
+ color: $link-fg;
}
header, footer {
@@ -83,9 +83,13 @@ header, footer {
align-self: start;
}
+header {
+ display: flex;
+ justify-content: center;
+}
+
header a {
margin: 2rem;
- /* background: $header_bg; */
display: flex;
flex-direction: column;
flex-wrap: wrap;
@@ -109,7 +113,7 @@ header a {
}
}
-.excerpt_top {
+.excerpt-top {
margin-top: -1rem;
margin-bottom: 2rem;
font-style: italic;
@@ -119,15 +123,15 @@ header a {
.count {
font-weight: bold;
- color: $fg_accent;
+ color: $fg-accent;
}
}
main {
section {
- background: $bg_accent;
+ background: $bg-accent;
box-shadow: $boxshadow;
- border: $boxshadow_border;
+ border: $boxshadow-border;
border-radius: $br;
padding: 2rem;
margin-bottom: 2rem;
@@ -144,10 +148,10 @@ main {
.button, button {
border-radius: 0.2rem;
- color: $button_fg;
- background: $button_bg;
+ color: $button-fg;
+ background: $button-bg;
box-shadow: $boxshadow;
- border: $button_border;
+ border: $button-border;
text-decoration: none;
font-size: 1.2rem;
font-weight: bold;
@@ -157,8 +161,17 @@ main {
text-align: center;
font-family: 'Noto Sans', sans-serif;
+ &.danger {
+ color: $button-danger-fg;
+ background: $button-danger-bg;
+
+ &:hover {
+ background: $button-danger-hover-bg;
+ }
+ }
+
&:hover {
- background: $button_hover_bg;
+ background: $button-hover-bg;
}
}
@@ -191,7 +204,7 @@ section.apps {
grid-template-columns: 25% 1fr;
gap: 1.5rem;
padding: 0.5rem;
- background: $bg_accent;
+ background: $bg-accent;
border-radius: 0.5rem;
.logo {
@@ -211,7 +224,7 @@ section.apps {
}
div {
- padding: 1rem 0;
+ padding: 0;
h3 {
margin-top: 0;
}
@@ -264,26 +277,42 @@ section.error {
}
}
+.error-text {
+ color: $error1;
+ background: $error2;
+ border-radius: 0.1rem;
+ font-weight: bold;
+}
+
input, select, textarea {
box-sizing: border-box;
- border: 0.15rem solid $border_accent;
+ border: 0.15rem solid $input-border;
border-radius: 0.1rem;
color: $fg;
- /* background: $input_bg; */
- background: $bg_accent;
+ background: $input-bg;
width: 100%;
font-family: 'Noto Sans', sans-serif;
font-size: 1rem;
padding: 0.3rem;
&:focus {
- border-color: $fg_accent;
+ border-color: $input-focus-border;
+ }
+
+ &:disabled {
+ background: $input-disabled-bg;
}
}
-input, textarea {
- padding-top: 0.1rem;
- padding-bottom: 0.1rem;
+::placeholder {
+ opacity: 1;
+ color: $fg-reduced
+}
+
+hr {
+ color: transparent;
+ width: 100%;
+ border-bottom: 0.02rem solid $border-accent;
}
footer {
@@ -330,4 +359,8 @@ footer {
margin: -0.5ex 0 0;
object-fit: contain;
vertical-align: middle;
+}
+
+.monospace {
+ font-family: monospace;
}
\ No newline at end of file
diff --git a/web/source/css/profile.css b/web/source/css/profile.css
@@ -28,7 +28,7 @@ main {
}
.profile {
- background: $bg_accent;
+ background: $bg-accent;
display: grid;
grid-template-rows: auto auto auto;
grid-template-columns: auto;
@@ -38,7 +38,7 @@ main {
border-radius: $br;
box-shadow: $boxshadow;
- border: $boxshadow_border;
+ border: $boxshadow-border;
.headerimage {
width: 100%;
@@ -50,7 +50,7 @@ main {
width: 100%;
height: 100%;
object-fit: cover;
- border-radius: $br_inner $br_inner 0 0;
+ border-radius: $br-inner $br-inner 0 0;
}
}
@@ -69,7 +69,7 @@ main {
#profile-basic-filler2 {
grid-area: filler2;
- background: $bg_trans;
+ background: $bg-trans;
}
.avatar {
@@ -79,7 +79,7 @@ main {
width: 8.5rem;
grid-area: avatar;
background: $bg;
- border: $profile_avatar_border;
+ border: 0.2rem solid $avatar-border;
padding: 0;
border-radius: $br;
position: relative;
@@ -87,7 +87,7 @@ main {
box-shadow: $boxshadow;
img {
object-fit: cover;
- border-radius: $br_inner;
+ border-radius: $br-inner;
width: 100%;
height: 100%;
}
@@ -105,7 +105,7 @@ main {
font-weight: bold;
font-size: 2rem;
line-height: 2.2rem;
- background: $bg_trans;
+ background: $bg-trans;
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
@@ -120,7 +120,7 @@ main {
padding-top: 0;
margin-top: 0.25rem;
padding-bottom: 0.25rem;
- color: $fg_accent;
+ color: $fg-accent;
font-weight: bold;
word-break: break-all;
text-overflow: ellipsis;
diff --git a/web/source/css/status.css b/web/source/css/status.css
@@ -31,13 +31,13 @@ main {
}
.toot {
- background: $status_unfocus_bg;
+ background: $toot-unfocus-bg;
box-shadow: $boxshadow;
- border: $boxshadow_border;
+ border: $boxshadow-border;
position: relative;
margin-bottom: $br;
- border-radius: $br;
- padding: 1.5rem 0;
+ padding-top: 1.5rem;
+ padding-bottom: 0.7rem;
a {
position: relative;
@@ -49,27 +49,34 @@ main {
.contentgrid {
padding: 0 1.5rem;
display: grid;
- grid-template-columns: 4rem auto 1fr;
- grid-template-rows: 1.5rem auto auto;
+ grid-template-columns: 4rem 1fr auto;
+ grid-template-rows: 1.5rem auto auto auto;
column-gap: 0.5rem;
}
+ .not-expanded {
+ color: $fg-reduced;
+ grid-column: 3;
+ grid-row: 1;
+ }
+
.avatar {
- grid-row: span 2;
+ grid-row: span 3;
aspect-ratio: 1/1;
+ display: flex;
+ border: 0.2rem solid $avatar-border;
+ border-radius: 0.4rem;
+ overflow: hidden; /* hides corners from img overflowing */
img {
height: 100%;
width: 100%;
object-fit: cover;
background: $bg;
- border: 0.1rem solid $acc2;
- border-radius: calc($br / 1.5);
}
}
.displayname {
- grid-column: span 2;
font-weight: bold;
font-size: 1.2rem;
line-height: 2rem;
@@ -82,7 +89,7 @@ main {
}
.username {
- color: $link_fg;
+ color: $link-fg;
line-height: 2rem;
margin-top: -0.5rem;
align-self: start;
@@ -119,8 +126,7 @@ main {
.text {
margin: 0;
- margin-top: 0.5rem;
- grid-column: span 3;
+ grid-column: 2 / span 2;
grid-row: span 1;
overflow: hidden;
@@ -128,34 +134,33 @@ main {
z-index: 2;
a {
- color: $link_fg;
+ color: $link-fg;
text-decoration: underline;
}
.content {
- padding-top: 0.5rem;
padding-bottom: 0.5rem;
word-break: break-word;
blockquote {
padding: 0.5rem 0 0.5rem 1.5rem;
- border-left: 0.2rem solid $sloth_orange1;
+ border-left: 0.2rem solid $border-accent;
margin-left: 1rem;
font-style: italic;
}
hr {
- border: 1px dashed $sloth_orange1;
+ border: 1px dashed $border-accent;
}
pre, code {
- background-color: $sloth_gray2_darker7;
+ background-color: $gray2;
}
code {
padding: 0.25rem;
- border-radius: $br_inner;
+ border-radius: $br-inner;
}
pre {
@@ -249,7 +254,7 @@ main {
.closed {
transition: 0.3s;
- background: $bg_sensitive;
+ background: $bg-sensitive;
@supports (backdrop-filter: blur(2rem)) {
background: transparent;
backdrop-filter: blur(2rem);
@@ -263,17 +268,17 @@ main {
}
.no-image-desc {
- color: $button_fg;
+ color: $no-img-desc-fg;
+ background: $no-img-desc-bg;
display: flex;
position: absolute;
bottom: 0.1rem;
right: 0.4rem;
margin-bottom: 0.4rem;
margin-right: 0.4rem;
- background: $bg_no_img_desc;
padding: 0.1rem 0.45rem;
border-radius: 100%;
- border: 0.2rem solid $button_fg;
+ border: 0.2rem solid $button-fg;
z-index: 3;
i.fa {
@@ -302,12 +307,13 @@ main {
}
.info {
+ background: $toot-info-bg;
+ color: $fg-reduced;
display: none;
- border-top: 0.15rem solid $status_unfocus_bg;
+ border-top: 0.15rem solid $toot-info-border;
padding: 0.5rem 1.5rem;
div {
- position: relative;
padding-right: 1.3rem;
}
@@ -317,30 +323,6 @@ main {
grid-column: span 3;
flex-wrap: wrap;
-
- div.stats::after {
- display: none;
- }
-
- div::after {
- $size: 0.25rem;
- display: block;
- background: $fg_dark;
- height: $size;
- width: $size;
- content: "";
- position: absolute;
- top: calc((1.5rem - $size) / 2);
- right: 0.55rem;
- border-radius: 1rem;
- }
-
- div:last-child {
- &::after {
- display: none;
- }
- margin-right: 0;
- }
}
.toot-link {
@@ -362,7 +344,7 @@ main {
border-top-right-radius: $br;
}
- &:last-child {
+ &:last-child, &:last-child .info {
/* bottom left, bottom right */
border-bottom-left-radius: $br;
border-bottom-right-radius: $br;
@@ -370,11 +352,21 @@ main {
}
&.expanded {
- background: $status_focus_bg;
+ background: $toot-focus-bg;
padding-bottom: 0;
.contentgrid {
- padding-bottom: 1rem;
+ .displayname {
+ grid-column: span 2;
+ }
+
+ .text {
+ grid-column: 1 / span 3;
+ }
+
+ .not-expanded {
+ display: none;
+ }
}
.info {
diff --git a/web/source/dev-server.js b/web/source/dev-server.js
@@ -1,19 +1,19 @@
/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
diff --git a/web/source/frontend/index.js b/web/source/frontend/index.js
@@ -18,11 +18,6 @@
"use strict";
-
-// WARNING: currently dependencies get deduplicated with factor-bundle, but
-// our frontend templates don't load the common bundle.js since it contains React etc
-// so we can't use any dependencies that would deduplicate with the other files
-
const Photoswipe = require("photoswipe/dist/umd/photoswipe.umd.min.js");
const PhotoswipeLightbox = require("photoswipe/dist/umd/photoswipe-lightbox.umd.min.js");
const PhotoswipeCaptionPlugin = require("photoswipe-dynamic-caption-plugin").default;
diff --git a/web/source/index.js b/web/source/index.js
@@ -1,19 +1,19 @@
/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
@@ -23,7 +23,8 @@
*/
const path = require('path');
-const budoExpress = require('budo-express');
+// Forked budo-express supports EventEmitter, to write bundle.js to disk in development
+const budoExpress = require('@f0x52/budo-express');
const babelify = require('babelify');
const fs = require("fs");
const EventEmitter = require('events');
@@ -38,8 +39,9 @@ const splitCSS = require("./lib/split-css.js");
const bundles = {
"./frontend/index.js": "frontend.js",
- "./panels/admin/index.js": "admin-panel.js",
- "./panels/user/index.js": "user-panel.js",
+ "./settings-panel/index.js": "settings.js",
+ // "./panels/admin/index.js": "admin-panel.js",
+ // "./panels/user/index.js": "user-panel.js",
};
const postcssPlugins = [
@@ -50,6 +52,18 @@ const postcssPlugins = [
"postcss-color-mod-function"
].map((plugin) => require(plugin)());
+let uglifyifyInProduction;
+
+if (process.env.NODE_ENV != "development") {
+ console.log("uglifyify'ing production bundles");
+ uglifyifyInProduction = [
+ require("uglifyify"), {
+ global: true,
+ exts: ".js"
+ }
+ ];
+}
+
const browserifyConfig = {
transform: [
[
@@ -69,10 +83,7 @@ const browserifyConfig = {
exclude: /node_modules\/(?!photoswipe-dynamic-caption-plugin)/,
}
],
- [require("uglifyify"), {
- global: true,
- exts: ".js"
- }]
+ uglifyifyInProduction
],
plugin: [
[require("icssify"), {
@@ -86,7 +97,8 @@ const browserifyConfig = {
return out(file);
})
}]
- ]
+ ],
+ extensions: [".js", ".jsx", ".css"]
};
const entryFiles = Object.keys(bundles);
diff --git a/web/source/lib/split-css.js b/web/source/lib/split-css.js
@@ -1,19 +1,19 @@
/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
diff --git a/web/source/lib/submit.js b/web/source/lib/submit.js
@@ -1,30 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const React = require("react");
-
-module.exports = function Submit({onClick, label, errorMsg, statusMsg}) {
- return (
- <div className="messagebutton">
- <button type="submit" onClick={onClick}>{ label }</button>
- <div className="error accent">{errorMsg ? errorMsg : statusMsg}</div>
- </div>
- );
-};
diff --git a/web/source/package.json b/web/source/package.json
@@ -1,6 +1,6 @@
{
"name": "gotosocial-frontend",
- "version": "0.3.8",
+ "version": "0.5.0",
"description": "GoToSocial frontend sources",
"main": "index.js",
"author": "f0x",
@@ -9,18 +9,23 @@
"@babel/core": "^7.12.13",
"@babel/preset-env": "^7.12.13",
"@babel/preset-react": "^7.12.13",
+ "@f0x52/budo-express": "^1.1.0",
+ "@reduxjs/toolkit": "^1.8.5",
"autoprefixer": "^10.4.8",
"babelify": "^10.0.0",
"bluebird": "^3.7.2",
"browserify": "^17.0.0",
"browserlist": "^1.0.1",
- "budo-express": "^1.0.8",
+ "create-error": "^0.3.1",
"css-extract": "^2.0.0",
+ "default-value": "^1.0.0",
+ "dotty": "^0.1.2",
"eslint-plugin-react": "^7.24.0",
"express": "^4.18.1",
"factor-bundle": "^2.5.0",
- "from2-string": "^1.1.0",
"icssify": "^2.0.0",
+ "is-plain-object": "^5.0.0",
+ "is-valid-domain": "^0.1.6",
"js-file-download": "^0.4.12",
"modern-normalize": "^1.1.0",
"photoswipe": "^5.3.0",
@@ -31,11 +36,17 @@
"postcss-nested": "^5.0.6",
"postcss-scss": "^4.0.4",
"postcss-strip-inline-comments": "^0.1.5",
- "pretty-bytes": "^5.6.0",
- "react": "^17.0.1",
- "react-dom": "^17.0.1",
- "reactify": "^1.1.1",
- "uglifyify": "^5.0.2"
+ "prettier-bytes": "^1.0.4",
+ "pretty-bytes": "4",
+ "react": "18",
+ "react-dom": "18",
+ "react-error-boundary": "^3.1.4",
+ "react-redux": "^8.0.2",
+ "redux-devtools-extension": "^2.13.9",
+ "redux-persist": "^6.0.0",
+ "redux-thunk": "^2.4.1",
+ "uglifyify": "^5.0.2",
+ "wouter": "^2.8.0-alpha.2"
},
"devDependencies": {
"@f0x52/eslint-config-react": "^1.1.0",
diff --git a/web/source/panels/admin/README.md b/web/source/panels/admin/README.md
@@ -1,21 +0,0 @@
-# GoToSocial Admin Panel
-
-Standalone web admin panel for [GoToSocial](https://github.com/superseriousbusiness/gotosocial).
-
-A public hosted instance is also available at https://gts.superseriousbusiness.org/admin/, so you can fill your own instance URL in there.
-
-## Installation
-Build requirements: some version of Node.js with npm,
-```
-git clone https://github.com/superseriousbusiness/gotosocial-admin.git && cd gotosocial-admin
-npm install
-node index.js
-```
-All processed build output will now be in `public/`, which you can copy over to a folder in your GoToSocial installation like `web/assets/admin`, or serve elsewhere.
-No further configuration is required, authentication happens through normal OAUTH flow.
-
-## Development
-Follow the installation steps, but run `NODE_ENV=development node index.js` to start the livereloading dev server instead.
-
-## License, donations
-[AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html). If you want to support my work, you can: <a href="https://liberapay.com/f0x/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
-\ No newline at end of file
diff --git a/web/source/panels/admin/blocks.js b/web/source/panels/admin/blocks.js
@@ -1,318 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-const React = require("react");
-const fileDownload = require("js-file-download");
-
-function sortBlocks(blocks) {
- return blocks.sort((a, b) => { // alphabetical sort
- return a.domain.localeCompare(b.domain);
- });
-}
-
-function deduplicateBlocks(blocks) {
- let a = new Map();
- blocks.forEach((block) => {
- a.set(block.id, block);
- });
- return Array.from(a.values());
-}
-
-module.exports = function Blocks({oauth}) {
- const [blocks, setBlocks] = React.useState([]);
- const [info, setInfo] = React.useState("Fetching blocks");
- const [errorMsg, setError] = React.useState("");
- const [checked, setChecked] = React.useState(new Set());
-
- React.useEffect(() => {
- Promise.try(() => {
- return oauth.apiRequest("/api/v1/admin/domain_blocks", undefined, undefined, "GET");
- }).then((json) => {
- setInfo("");
- setError("");
- setBlocks(sortBlocks(json));
- }).catch((e) => {
- setError(e.message);
- setInfo("");
- });
- }, []);
-
- let blockList = blocks.map((block) => {
- function update(e) {
- let newChecked = new Set(checked.values());
- if (e.target.checked) {
- newChecked.add(block.id);
- } else {
- newChecked.delete(block.id);
- }
- setChecked(newChecked);
- }
-
- return (
- <React.Fragment key={block.id}>
- <div><input type="checkbox" onChange={update} checked={checked.has(block.id)}></input></div>
- <div>{block.domain}</div>
- <div>{(new Date(block.created_at)).toLocaleString()}</div>
- </React.Fragment>
- );
- });
-
- function clearChecked() {
- setChecked(new Set());
- }
-
- function undoChecked() {
- let amount = checked.size;
- if(confirm(`Are you sure you want to remove ${amount} block(s)?`)) {
- setInfo("");
- Promise.map(Array.from(checked.values()), (block) => {
- console.log("deleting", block);
- return oauth.apiRequest(`/api/v1/admin/domain_blocks/${block}`, "DELETE");
- }).then((res) => {
- console.log(res);
- setInfo(`Deleted ${amount} blocks: ${res.map((a) => a.domain).join(", ")}`);
- }).catch((e) => {
- setError(e);
- });
-
- let newBlocks = blocks.filter((block) => {
- if (checked.size > 0 && checked.has(block.id)) {
- checked.delete(block.id);
- return false;
- } else {
- return true;
- }
- });
- setBlocks(newBlocks);
- clearChecked();
- }
- }
-
- return (
- <section className="blocks">
- <h1>Blocks</h1>
- <div className="error accent">{errorMsg}</div>
- <div>{info}</div>
- <AddBlock oauth={oauth} blocks={blocks} setBlocks={setBlocks} />
- <h3>Blocks:</h3>
- <div style={{display: "grid", gridTemplateColumns: "1fr auto"}}>
- <span onClick={clearChecked} className="accent" style={{alignSelf: "end"}}>uncheck all</span>
- <button onClick={undoChecked}>Unblock selected</button>
- </div>
- <div className="blocklist overflow">
- {blockList}
- </div>
- <BulkBlocking oauth={oauth} blocks={blocks} setBlocks={setBlocks}/>
- </section>
- );
-};
-
-function BulkBlocking({oauth, blocks, setBlocks}) {
- const [bulk, setBulk] = React.useState("");
- const [blockMap, setBlockMap] = React.useState(new Map());
- const [output, setOutput] = React.useState();
-
- React.useEffect(() => {
- let newBlockMap = new Map();
- blocks.forEach((block) => {
- newBlockMap.set(block.domain, block);
- });
- setBlockMap(newBlockMap);
- }, [blocks]);
-
- const fileRef = React.useRef();
-
- function error(e) {
- setOutput(<div className="error accent">{e}</div>);
- throw e;
- }
-
- function fileUpload() {
- let reader = new FileReader();
- reader.addEventListener("load", (e) => {
- try {
- // TODO: use validatem?
- let json = JSON.parse(e.target.result);
- json.forEach((block) => {
- console.log("block:", block);
- });
- } catch(e) {
- error(e.message);
- }
- });
- reader.readAsText(fileRef.current.files[0]);
- }
-
- React.useEffect(() => {
- if (fileRef && fileRef.current) {
- fileRef.current.addEventListener("change", fileUpload);
- }
- return function cleanup() {
- fileRef.current.removeEventListener("change", fileUpload);
- };
- });
-
- function textImport() {
- Promise.try(() => {
- if (bulk[0] == "[") {
- // assume it's json
- return JSON.parse(bulk);
- } else {
- return bulk.split("\n").map((val) => {
- return {
- domain: val.trim()
- };
- });
- }
- }).then((domains) => {
- console.log(domains);
- let before = domains.length;
- setOutput(`Importing ${before} domain(s)`);
- domains = domains.filter(({domain}) => {
- return (domain != "" && !blockMap.has(domain));
- });
- setOutput(<span>{output}<br/>{`Deduplicated ${before - domains.length}/${before} with existing blocks, adding ${domains.length} block(s)`}</span>);
- if (domains.length > 0) {
- let data = new FormData();
- data.append("domains", new Blob([JSON.stringify(domains)], {type: "application/json"}), "import.json");
- return oauth.apiRequest("/api/v1/admin/domain_blocks?import=true", "POST", data, "form");
- }
- }).then((json) => {
- console.log("bulk import result:", json);
- setBlocks(sortBlocks(deduplicateBlocks([...json, ...blocks])));
- }).catch((e) => {
- error(e.message);
- });
- }
-
- function textExport() {
- setBulk(blocks.reduce((str, val) => {
- if (typeof str == "object") {
- return str.domain;
- } else {
- return str + "\n" + val.domain;
- }
- }));
- }
-
- function jsonExport() {
- Promise.try(() => {
- return oauth.apiRequest("/api/v1/admin/domain_blocks?export=true", "GET");
- }).then((json) => {
- fileDownload(JSON.stringify(json), "block-export.json");
- }).catch((e) => {
- error(e);
- });
- }
-
- function textAreaUpdate(e) {
- setBulk(e.target.value);
- }
-
- return (
- <React.Fragment>
- <h3>Bulk import/export</h3>
- <label htmlFor="bulk">Domains, one per line:</label>
- <textarea value={bulk} rows={20} onChange={textAreaUpdate}></textarea>
- <div className="controls">
- <button onClick={textImport}>Import All From Field</button>
- <button onClick={textExport}>Export To Field</button>
- <label className="button" htmlFor="upload">Upload .json</label>
- <button onClick={jsonExport}>Download .json</button>
- </div>
- {output}
- <input type="file" id="upload" className="hidden" ref={fileRef}></input>
- </React.Fragment>
- );
-}
-
-function AddBlock({oauth, blocks, setBlocks}) {
- const [domain, setDomain] = React.useState("");
- const [type, setType] = React.useState("suspend");
- const [obfuscated, setObfuscated] = React.useState(false);
- const [privateDescription, setPrivateDescription] = React.useState("");
- const [publicDescription, setPublicDescription] = React.useState("");
-
- function addBlock() {
- console.log(`${type}ing`, domain);
- Promise.try(() => {
- return oauth.apiRequest("/api/v1/admin/domain_blocks", "POST", {
- domain: domain,
- obfuscate: obfuscated,
- private_comment: privateDescription,
- public_comment: publicDescription
- }, "json");
- }).then((json) => {
- setDomain("");
- setPrivateDescription("");
- setPublicDescription("");
- setBlocks([json, ...blocks]);
- });
- }
-
- function onDomainChange(e) {
- setDomain(e.target.value);
- }
-
- function onTypeChange(e) {
- setType(e.target.value);
- }
-
- function onKeyDown(e) {
- if (e.key == "Enter") {
- addBlock();
- }
- }
-
- return (
- <React.Fragment>
- <h3>Add Block:</h3>
- <div className="addblock">
- <input id="domain" placeholder="instance" onChange={onDomainChange} value={domain} onKeyDown={onKeyDown} />
- <select value={type} onChange={onTypeChange}>
- <option id="suspend">Suspend</option>
- <option id="silence">Silence</option>
- </select>
- <button onClick={addBlock}>Add</button>
- <div>
- <label htmlFor="private">Private description:</label><br/>
- <textarea id="private" value={privateDescription} onChange={(e) => setPrivateDescription(e.target.value)}></textarea>
- </div>
- <div>
- <label htmlFor="public">Public description:</label><br/>
- <textarea id="public" value={publicDescription} onChange={(e) => setPublicDescription(e.target.value)}></textarea>
- </div>
- <div className="single">
- <label htmlFor="obfuscate">Obfuscate:</label>
- <input id="obfuscate" type="checkbox" value={obfuscated} onChange={(e) => setObfuscated(e.target.checked)}/>
- </div>
- </div>
- </React.Fragment>
- );
-}
-
-// function Blocklist() {
-// return (
-// <section className="blocklists">
-// <h1>Blocklists</h1>
-// </section>
-// );
-// }
-\ No newline at end of file
diff --git a/web/source/panels/admin/index.js b/web/source/panels/admin/index.js
@@ -1,64 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-const React = require("react");
-const ReactDom = require("react-dom");
-
-const createPanel = require("../lib/panel");
-
-const Settings = require("./settings");
-const Blocks = require("./blocks");
-
-require("../base.css");
-require("./style.css");
-
-function AdminPanel({oauth}) {
- /*
- Features: (issue #78)
- - [ ] Instance information updating
- GET /api/v1/instance PATCH /api/v1/instance
- - [ ] Domain block creation, viewing, and deletion
- GET /api/v1/admin/domain_blocks
- POST /api/v1/admin/domain_blocks
- GET /api/v1/admin/domain_blocks/DOMAIN_BLOCK_ID, DELETE /api/v1/admin/domain_blocks/DOMAIN_BLOCK_ID
- - [ ] Blocklist import/export
- GET /api/v1/admin/domain_blocks?export=true
- POST json file as form field domains to /api/v1/admin/domain_blocks
- */
-
- return (
- <React.Fragment>
- <Logout oauth={oauth}/>
- <Settings oauth={oauth} />
- <Blocks oauth={oauth}/>
- </React.Fragment>
- );
-}
-
-function Logout({oauth}) {
- return (
- <div>
- <button onClick={oauth.logout}>Logout</button>
- </div>
- );
-}
-
-createPanel("GoToSocial Admin Panel", ["admin"], AdminPanel);
-\ No newline at end of file
diff --git a/web/source/panels/admin/settings.js b/web/source/panels/admin/settings.js
@@ -1,182 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-const React = require("react");
-
-module.exports = function Settings({oauth}) {
- const [info, setInfo] = React.useState({});
- const [errorMsg, setError] = React.useState("");
- const [statusMsg, setStatus] = React.useState("Fetching instance info");
-
- React.useEffect(() => {
- Promise.try(() => {
- return oauth.apiRequest("/api/v1/instance", "GET");
- }).then((json) => {
- setInfo(json);
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
- }, []);
-
- function submit() {
- setStatus("PATCHing");
- setError("");
- return Promise.try(() => {
- let formDataInfo = new FormData();
- Object.entries(info).forEach(([key, val]) => {
- if (key == "contact_account") {
- key = "contact_username";
- val = val.username;
- }
- if (key == "email") {
- key = "contact_email";
- }
- if (typeof val != "object") {
- formDataInfo.append(key, val);
- }
- });
- return oauth.apiRequest("/api/v1/instance", "PATCH", formDataInfo, "form");
- }).then((json) => {
- setStatus("Config saved");
- console.log(json);
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
- }
-
- return (
- <section className="info login">
- <h1>Instance Information <button onClick={submit}>Save</button></h1>
- <div className="error accent">
- {errorMsg}
- </div>
- <div>
- {statusMsg}
- </div>
- <form onSubmit={(e) => e.preventDefault()}>
- {editableObject(info)}
- </form>
- </section>
- );
-};
-
-function editableObject(obj, path=[]) {
- const readOnlyKeys = ["uri", "version", "urls_streaming_api", "stats"];
- const hiddenKeys = ["contact_account_", "urls"];
- const explicitShownKeys = ["contact_account_username"];
- const implementedKeys = "title, contact_account_username, email, short_description, description, terms, avatar, header".split(", ");
- const textareaKeys = ["short_description", "description"]
-
- let listing = Object.entries(obj).map(([key, val]) => {
- let fullkey = [...path, key].join("_");
-
- if (
- hiddenKeys.includes(fullkey) ||
- hiddenKeys.includes(path.join("_")+"_") // also match just parent path
- ) {
- if (!explicitShownKeys.includes(fullkey)) {
- return null;
- }
- }
-
- if (Array.isArray(val)) {
- // FIXME: handle this
- } else if (typeof val == "object") {
- return (<React.Fragment key={fullkey}>
- {editableObject(val, [...path, key])}
- </React.Fragment>);
- }
-
- let isImplemented = "";
- if (!implementedKeys.includes(fullkey)) {
- isImplemented = " notImplemented";
- }
-
- let isReadOnly = (
- readOnlyKeys.includes(fullkey) ||
- readOnlyKeys.includes(path.join("_")) ||
- isImplemented != ""
- );
-
- let label = key.replace(/_/g, " ");
- if (path.length > 0) {
- label = `\u00A0`.repeat(4 * path.length) + label;
- }
-
- let inputProps;
- let changeFunc;
- if (val === true || val === false) {
- inputProps = {
- type: "checkbox",
- defaultChecked: val,
- disabled: isReadOnly
- };
- changeFunc = (e) => e.target.checked;
- } else if (val.length != 0 && !isNaN(val)) {
- inputProps = {
- type: "number",
- defaultValue: val,
- readOnly: isReadOnly
- };
- changeFunc = (e) => e.target.value;
- } else {
- inputProps = {
- type: "text",
- defaultValue: val,
- readOnly: isReadOnly
- };
- changeFunc = (e) => e.target.value;
- }
-
- function setRef(element) {
- if (element != null) {
- element.addEventListener("change", (e) => {
- obj[key] = changeFunc(e);
- });
- }
- }
-
- let field;
- if (textareaKeys.includes(fullkey)) {
- field = <textarea className={isImplemented} ref={setRef} {...inputProps}></textarea>
- } else {
- field = <input className={isImplemented} ref={setRef} {...inputProps} />
- }
- return (
- <React.Fragment key={fullkey}>
- <label htmlFor={key} className="capitalize">{label}</label>
- <div className={isImplemented}>
- {field}
- </div>
- </React.Fragment>
- );
- });
- return (
- <React.Fragment>
- {path != "" &&
- <><b>{path}:</b> <span id="filler"></span></>
- }
- {listing}
- </React.Fragment>
- );
-}
-\ No newline at end of file
diff --git a/web/source/panels/admin/style.css b/web/source/panels/admin/style.css
@@ -1,106 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-section.info {
- form {
- grid-template-columns: auto 1fr;
- width: calc(100% - 0.35rem);
-
- input {
- width: 100%;
- line-height: 1.5rem;
- }
-
- label, input {
- padding: 0.2rem 0.5rem;
- }
-
- input[type=checkbox] {
- justify-self: start;
- width: initial;
- }
-
- input:read-only {
- border: none;
- }
-
- input:invalid {
- border-color: red;
- }
- }
-
- textarea {
- width: 100%;
- height: 8rem;
- }
-
- h1 {
- display: flex;
- justify-content: space-between;
- margin-bottom: 0.5rem;
- }
-}
-
-section.blocks {
- .overflow {
- max-height: 80vh;
- overflow-y: auto;
- }
-
- .blocklist {
- display: grid;
- grid-template-columns: auto 1fr auto;
- grid-gap: 0.35rem 0;
-
- div {
- background: rgb(70, 79, 88);
- padding: 0.2rem 0.4rem;
- }
- }
-
- .addblock {
- display: grid;
- grid-template-columns: 1fr auto auto;
- grid-gap: 0.35rem;
-
- input, select {
- font-size: 1.2rem;
- }
-
- input, select, textarea {
- padding: 0.5rem;
- }
-
- div {
- grid-column: 1/4;
- }
-
- div.single input {
- width: initial;
- }
- }
-
- h3 {
- margin-bottom: 0;
- }
-
- .controls {
- display: flex;
- gap: 0.5rem;
- }
-}
diff --git a/web/source/panels/base.css b/web/source/panels/base.css
@@ -1,67 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-body {
- grid-template-rows: auto 1fr;
-}
-
-.capitalize {
- text-transform: capitalize;
-}
-
-section {
- margin-bottom: 1rem;
-}
-
-input, select, textarea {
- box-sizing: border-box;
-}
-
-.error {
- font-weight: bold;
-}
-
-.hidden {
- display: none;
-}
-
-.messagebutton {
- margin-top: 1rem;
- display: flex;
- gap: 1rem;
- align-items: center;
-
- button {
- white-space: nowrap;
- }
-}
-
-.notImplemented {
- border: 2px solid rgb(70, 79, 88);
- background: repeating-linear-gradient(
- -45deg,
- #525c66,
- #525c66 10px,
- rgb(70, 79, 88) 10px,
- rgb(70, 79, 88) 20px
- ) !important;
-}
-
-.mono {
- font-family: monospace;
-}
diff --git a/web/source/panels/lib/oauth.js b/web/source/panels/lib/oauth.js
@@ -1,227 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-
-function getCurrentUrl() {
- return window.location.origin + window.location.pathname; // strips ?query=string and #hash
-}
-
-module.exports = function oauthClient(config, initState) {
- /* config:
- instance: instance domain (https://testingtesting123.xyz)
- client_name: "GoToSocial Admin Panel"
- scope: []
- website:
- */
-
- let state = initState;
- if (initState == undefined) {
- state = localStorage.getItem("oauth");
- if (state == undefined) {
- state = {
- config
- };
- storeState();
- } else {
- state = JSON.parse(state);
- }
- }
-
- function storeState() {
- localStorage.setItem("oauth", JSON.stringify(state));
- }
-
- /* register app
- /api/v1/apps
- */
- function register() {
- if (state.client_id != undefined) {
- return true; // we already have a registration
- }
- let url = new URL(config.instance);
- url.pathname = "/api/v1/apps";
-
- return fetch(url.href, {
- method: "POST",
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- client_name: config.client_name,
- redirect_uris: getCurrentUrl(),
- scopes: config.scope.join(" "),
- website: getCurrentUrl()
- })
- }).then((res) => {
- if (res.status != 200) {
- throw res;
- }
- return res.json();
- }).then((json) => {
- state.client_id = json.client_id;
- state.client_secret = json.client_secret;
- storeState();
- });
- }
-
- /* authorize:
- /oauth/authorize
- ?client_id=CLIENT_ID
- &redirect_uri=window.location.href
- &response_type=code
- &scope=admin
- */
- function authorize() {
- let url = new URL(config.instance);
- url.pathname = "/oauth/authorize";
- url.searchParams.set("client_id", state.client_id);
- url.searchParams.set("redirect_uri", getCurrentUrl());
- url.searchParams.set("response_type", "code");
- url.searchParams.set("scope", config.scope.join(" "));
-
- window.location.assign(url.href);
- }
-
- function callback() {
- if (state.access_token != undefined) {
- return; // we're already done :)
- }
- let params = (new URL(window.location)).searchParams;
-
- let token = params.get("code");
- if (token != null) {
- console.log("got token callback:", token);
- }
-
- return authorizeToken(token)
- .catch((e) => {
- console.log("Error processing oauth callback:", e);
- logout(); // just to be sure
- });
- }
-
- function authorizeToken(token) {
- let url = new URL(config.instance);
- url.pathname = "/oauth/token";
- return fetch(url.href, {
- method: "POST",
- headers: {
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- client_id: state.client_id,
- client_secret: state.client_secret,
- redirect_uri: getCurrentUrl(),
- grant_type: "authorization_code",
- code: token
- })
- }).then((res) => {
- if (res.status != 200) {
- throw res;
- }
- return res.json();
- }).then((json) => {
- state.access_token = json.access_token;
- storeState();
- window.location = getCurrentUrl(); // clear ?token=
- });
- }
-
- function isAuthorized() {
- return (state.access_token != undefined);
- }
-
- function apiRequest(path, method, data, type="json", accept="json") {
- if (!isAuthorized()) {
- throw new Error("Not Authenticated");
- }
- let url = new URL(config.instance);
- let [p, s] = path.split("?");
- url.pathname = p;
- if (s != undefined) {
- url.search = s;
- }
- let headers = {
- "Authorization": `Bearer ${state.access_token}`,
- "Accept": accept == "json" ? "application/json" : "*/*"
- };
- let body = data;
- if (type == "json" && body != undefined) {
- headers["Content-Type"] = "application/json";
- body = JSON.stringify(data);
- }
- return fetch(url.href, {
- method,
- headers,
- body
- }).then((res) => {
- return Promise.all([res.json(), res]);
- }).then(([json, res]) => {
- if (res.status != 200) {
- if (json.error) {
- throw new Error(json.error);
- } else {
- throw new Error(`${res.status}: ${res.statusText}`);
- }
- } else {
- return json;
- }
- }).catch(e => {
- if (e instanceof SyntaxError) {
- throw new Error("Error: The GtS API returned a non-json error. This usually means a network problem, or an issue with your instance's reverse proxy configuration.", {cause: e});
- } else {
- throw e;
- }
- });
- }
-
- function logout() {
- let url = new URL(config.instance);
- url.pathname = "/oauth/revoke";
- return fetch(url.href, {
- method: "POST",
- headers: {
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- client_id: state.client_id,
- client_secret: state.client_secret,
- token: state.access_token,
- })
- }).then((res) => {
- if (res.status != 200) {
- // GoToSocial doesn't actually implement this route yet,
- // so error is to be expected
- return;
- }
- return res.json();
- }).catch(() => {
- // see above
- }).then(() => {
- localStorage.removeItem("oauth");
- window.location = getCurrentUrl();
- });
- }
-
- return {
- register, authorize, callback, isAuthorized, apiRequest, logout
- };
-};
diff --git a/web/source/panels/lib/panel.js b/web/source/panels/lib/panel.js
@@ -1,134 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-const React = require("react");
-const ReactDom = require("react-dom");
-
-const oauthLib = require("./oauth");
-
-module.exports = function createPanel(clientName, scope, Component) {
- ReactDom.render(<Panel/>, document.getElementById("root"));
-
- function Panel() {
- const [oauth, setOauth] = React.useState();
- const [hasAuth, setAuth] = React.useState(false);
- const [oauthState, setOauthState] = React.useState(localStorage.getItem("oauth"));
-
- React.useEffect(() => {
- let state = localStorage.getItem("oauth");
- if (state != undefined) {
- state = JSON.parse(state);
- let restoredOauth = oauthLib(state.config, state);
- Promise.try(() => {
- return restoredOauth.callback();
- }).then(() => {
- setAuth(true);
- });
- setOauth(restoredOauth);
- }
- }, [setAuth, setOauth]);
-
- if (!hasAuth && oauth && oauth.isAuthorized()) {
- setAuth(true);
- }
-
- if (oauth && oauth.isAuthorized()) {
- return <Component oauth={oauth} />;
- } else if (oauthState != undefined) {
- return "processing oauth...";
- } else {
- return <Auth setOauth={setOauth} />;
- }
- }
-
- function Auth({setOauth}) {
- const [ instance, setInstance ] = React.useState("");
-
- React.useEffect(() => {
- let isStillMounted = true;
- // check if current domain runs an instance
- let thisUrl = new URL(window.location.origin);
- thisUrl.pathname = "/api/v1/instance";
- Promise.try(() => {
- return fetch(thisUrl.href);
- }).then((res) => {
- if (res.status == 200) {
- return res.json();
- }
- }).then((json) => {
- if (json && json.uri && isStillMounted) {
- setInstance(json.uri);
- }
- }).catch((e) => {
- console.log("error checking instance response:", e);
- });
-
- return () => {
- // cleanup function
- isStillMounted = false;
- };
- }, []);
-
- function doAuth() {
- return Promise.try(() => {
- return new URL(instance);
- }).catch(TypeError, () => {
- return new URL(`https://${instance}`);
- }).then((parsedURL) => {
- let url = parsedURL.toString();
- let oauth = oauthLib({
- instance: url,
- client_name: clientName,
- scope: scope,
- website: window.location.href
- });
- setOauth(oauth);
- setInstance(url);
- return oauth.register().then(() => {
- return oauth;
- });
- }).then((oauth) => {
- return oauth.authorize();
- }).catch((e) => {
- console.log("error authenticating:", e);
- });
- }
-
- function updateInstance(e) {
- if (e.key == "Enter") {
- doAuth();
- } else {
- setInstance(e.target.value);
- }
- }
-
- return (
- <section className="login">
- <h1>OAUTH Login:</h1>
- <form onSubmit={(e) => e.preventDefault()}>
- <label htmlFor="instance">Instance: </label>
- <input value={instance} onChange={updateInstance} id="instance"/>
- <button onClick={doAuth}>Authenticate</button>
- </form>
- </section>
- );
- }
-};
-\ No newline at end of file
diff --git a/web/source/panels/user/basic.js b/web/source/panels/user/basic.js
@@ -1,151 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const React = require("react");
-const Promise = require("bluebird");
-
-const Submit = require("../../lib/submit");
-
-module.exports = function Basic({oauth, account, allowCustomCSS}) {
- const [errorMsg, setError] = React.useState("");
- const [statusMsg, setStatus] = React.useState("");
-
- const [headerFile, setHeaderFile] = React.useState(undefined);
- const [headerSrc, setHeaderSrc] = React.useState("");
-
- const [avatarFile, setAvatarFile] = React.useState(undefined);
- const [avatarSrc, setAvatarSrc] = React.useState("");
-
- const [displayName, setDisplayName] = React.useState("");
- const [bio, setBio] = React.useState("");
- const [locked, setLocked] = React.useState(false);
- const [customCSS, setCustomCSS] = React.useState("");
-
- React.useEffect(() => {
- setHeaderSrc(account.header);
- setAvatarSrc(account.avatar);
-
- setDisplayName(account.display_name);
- setBio(account.source ? account.source.note : "");
- setLocked(account.locked);
- setCustomCSS((allowCustomCSS && account.custom_css) ? account.custom_css : "");
- }, [account, setHeaderSrc, setAvatarSrc, setDisplayName, setBio, setLocked, setCustomCSS]);
-
- const headerOnChange = (e) => {
- setHeaderFile(e.target.files[0]);
- setHeaderSrc(URL.createObjectURL(e.target.files[0]));
- };
-
- const avatarOnChange = (e) => {
- setAvatarFile(e.target.files[0]);
- setAvatarSrc(URL.createObjectURL(e.target.files[0]));
- };
-
- const submit = (e) => {
- e.preventDefault();
-
- setStatus("PATCHing");
- setError("");
- return Promise.try(() => {
- let formDataInfo = new FormData();
-
- if (headerFile) {
- formDataInfo.set("header", headerFile);
- }
-
- if (avatarFile) {
- formDataInfo.set("avatar", avatarFile);
- }
-
- formDataInfo.set("display_name", displayName);
- formDataInfo.set("note", bio);
- formDataInfo.set("locked", locked);
-
- if (allowCustomCSS) {
- formDataInfo.set("custom_css", customCSS);
- }
-
- return oauth.apiRequest("/api/v1/accounts/update_credentials", "PATCH", formDataInfo, "form");
- }).then((json) => {
- setStatus("Saved!");
-
- setHeaderSrc(json.header);
- setAvatarSrc(json.avatar);
-
- setDisplayName(json.display_name);
- setBio(json.source.note);
- setLocked(json.locked);
- setCustomCSS(allowCustomCSS && json.custom_css ? json.custom_css : "");
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
- };
-
- return (
- <section className="basic">
- <h1>@{account.username}'s Profile Info</h1>
- <form>
- <div className="labelinput">
- <label htmlFor="header">Header</label>
- <div className="border">
- <img className="headerpreview" src={headerSrc} alt={headerSrc ? `header image for ${account.username}` : "None set"}/>
- <div>
- <label htmlFor="header" className="file-input button">Browse…</label>
- <span>{headerFile ? headerFile.name : ""}</span>
- </div>
- </div>
- <input className="hidden" id="header" type="file" accept="image/*" onChange={headerOnChange}/>
- </div>
- <div className="labelinput">
- <label htmlFor="avatar">Avatar</label>
- <div className="border">
- <img className="avatarpreview" src={avatarSrc} alt={headerSrc ? `avatar image for ${account.username}` : "None set"}/>
- <div>
- <label htmlFor="avatar" className="file-input button">Browse…</label>
- <span>{avatarFile ? avatarFile.name : ""}</span>
- </div>
- </div>
- <input className="hidden" id="avatar" type="file" accept="image/*" onChange={avatarOnChange}/>
- </div>
- <div className="labelinput">
- <label htmlFor="displayname">Display Name</label>
- <input id="displayname" type="text" value={displayName} onChange={(e) => setDisplayName(e.target.value)} placeholder="A GoToSocial user"/>
- </div>
- <div className="labelinput">
- <label htmlFor="bio">Bio</label>
- <textarea id="bio" value={bio} onChange={(e) => setBio(e.target.value)} placeholder="Just trying out GoToSocial, my pronouns are they/them and I like sloths."/>
- </div>
- { !allowCustomCSS ? null :
- <div className="labelinput">
- <label htmlFor="customcss">Custom CSS</label>
- <textarea className="mono" id="customcss" value={customCSS} onChange={(e) => setCustomCSS(e.target.value)}/>
- <a href="https://docs.gotosocial.org/en/latest/user_guide/custom_css" target="_blank" className="moreinfolink" rel="noreferrer">Learn more about custom CSS (opens in a new tab)</a>
- </div>
- }
- <div className="labelcheckbox">
- <label htmlFor="locked">Manually approve follow requests</label>
- <input id="locked" type="checkbox" checked={locked} onChange={(e) => setLocked(e.target.checked)}/>
- </div>
- <Submit onClick={submit} label="Save profile info" errorMsg={errorMsg} statusMsg={statusMsg}/>
- </form>
- </section>
- );
-};
diff --git a/web/source/panels/user/index.js b/web/source/panels/user/index.js
@@ -1,76 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const Promise = require("bluebird");
-const React = require("react");
-const ReactDom = require("react-dom");
-
-const createPanel = require("../lib/panel");
-
-const Basic = require("./basic");
-const Posts = require("./posts");
-const Security = require("./security");
-
-require("../base.css");
-require("./style.css");
-
-function UserPanel({oauth}) {
- const [account, setAccount] = React.useState({});
- const [allowCustomCSS, setAllowCustomCSS] = React.useState(false);
- const [errorMsg, setError] = React.useState("");
- const [statusMsg, setStatus] = React.useState("Fetching user info");
-
- React.useEffect(() => {
-
- }, [oauth, setAllowCustomCSS, setError, setStatus]);
-
- React.useEffect(() => {
- Promise.try(() => {
- return oauth.apiRequest("/api/v1/instance", "GET");
- }).then((json) => {
- setAllowCustomCSS(json.configuration.accounts.allow_custom_css);
- Promise.try(() => {
- return oauth.apiRequest("/api/v1/accounts/verify_credentials", "GET");
- }).then((json) => {
- setAccount(json);
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
-
- }, [oauth, setAllowCustomCSS, setAccount, setError, setStatus]);
-
- return (
- <React.Fragment>
- <div>
- <button className="logout" onClick={oauth.logout}>Log out of settings panel</button>
- </div>
- <Basic oauth={oauth} account={account} allowCustomCSS={allowCustomCSS}/>
- <Posts oauth={oauth} account={account}/>
- <Security oauth={oauth}/>
- </React.Fragment>
- );
-}
-
-createPanel("GoToSocial User Panel", ["read write"], UserPanel);
-\ No newline at end of file
diff --git a/web/source/panels/user/languages.js b/web/source/panels/user/languages.js
@@ -1,98 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const React = require("react");
-
-module.exports = function Languages() {
- return <React.Fragment>
- <option value="AF">Afrikaans</option>
- <option value="SQ">Albanian</option>
- <option value="AR">Arabic</option>
- <option value="HY">Armenian</option>
- <option value="EU">Basque</option>
- <option value="BN">Bengali</option>
- <option value="BG">Bulgarian</option>
- <option value="CA">Catalan</option>
- <option value="KM">Cambodian</option>
- <option value="ZH">Chinese (Mandarin)</option>
- <option value="HR">Croatian</option>
- <option value="CS">Czech</option>
- <option value="DA">Danish</option>
- <option value="NL">Dutch</option>
- <option value="EN">English</option>
- <option value="ET">Estonian</option>
- <option value="FJ">Fiji</option>
- <option value="FI">Finnish</option>
- <option value="FR">French</option>
- <option value="KA">Georgian</option>
- <option value="DE">German</option>
- <option value="EL">Greek</option>
- <option value="GU">Gujarati</option>
- <option value="HE">Hebrew</option>
- <option value="HI">Hindi</option>
- <option value="HU">Hungarian</option>
- <option value="IS">Icelandic</option>
- <option value="ID">Indonesian</option>
- <option value="GA">Irish</option>
- <option value="IT">Italian</option>
- <option value="JA">Japanese</option>
- <option value="JW">Javanese</option>
- <option value="KO">Korean</option>
- <option value="LA">Latin</option>
- <option value="LV">Latvian</option>
- <option value="LT">Lithuanian</option>
- <option value="MK">Macedonian</option>
- <option value="MS">Malay</option>
- <option value="ML">Malayalam</option>
- <option value="MT">Maltese</option>
- <option value="MI">Maori</option>
- <option value="MR">Marathi</option>
- <option value="MN">Mongolian</option>
- <option value="NE">Nepali</option>
- <option value="NO">Norwegian</option>
- <option value="FA">Persian</option>
- <option value="PL">Polish</option>
- <option value="PT">Portuguese</option>
- <option value="PA">Punjabi</option>
- <option value="QU">Quechua</option>
- <option value="RO">Romanian</option>
- <option value="RU">Russian</option>
- <option value="SM">Samoan</option>
- <option value="SR">Serbian</option>
- <option value="SK">Slovak</option>
- <option value="SL">Slovenian</option>
- <option value="ES">Spanish</option>
- <option value="SW">Swahili</option>
- <option value="SV">Swedish </option>
- <option value="TA">Tamil</option>
- <option value="TT">Tatar</option>
- <option value="TE">Telugu</option>
- <option value="TH">Thai</option>
- <option value="BO">Tibetan</option>
- <option value="TO">Tonga</option>
- <option value="TR">Turkish</option>
- <option value="UK">Ukrainian</option>
- <option value="UR">Urdu</option>
- <option value="UZ">Uzbek</option>
- <option value="VI">Vietnamese</option>
- <option value="CY">Welsh</option>
- <option value="XH">Xhosa</option>
- </React.Fragment>;
-};
diff --git a/web/source/panels/user/posts.js b/web/source/panels/user/posts.js
@@ -1,107 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const React = require("react");
-const Promise = require("bluebird");
-
-const Languages = require("./languages");
-const Submit = require("../../lib/submit");
-
-module.exports = function Posts({oauth, account}) {
- const [errorMsg, setError] = React.useState("");
- const [statusMsg, setStatus] = React.useState("");
-
- const [language, setLanguage] = React.useState("");
- const [privacy, setPrivacy] = React.useState("");
- const [format, setFormat] = React.useState("");
- const [sensitive, setSensitive] = React.useState(false);
-
- React.useEffect(() => {
- if (account.source) {
- setLanguage(account.source.language.toUpperCase());
- setPrivacy(account.source.privacy);
- setSensitive(account.source.sensitive ? account.source.sensitive : false);
- setFormat(account.source.status_format ? account.source.status_format : "plain");
- }
-
- }, [account, setSensitive, setPrivacy]);
-
- const submit = (e) => {
- e.preventDefault();
-
- setStatus("PATCHing");
- setError("");
- return Promise.try(() => {
- let formDataInfo = new FormData();
-
- formDataInfo.set("source[language]", language);
- formDataInfo.set("source[privacy]", privacy);
- formDataInfo.set("source[sensitive]", sensitive);
- formDataInfo.set("source[status_format]", format);
-
- return oauth.apiRequest("/api/v1/accounts/update_credentials", "PATCH", formDataInfo, "form");
- }).then((json) => {
- setStatus("Saved!");
- setLanguage(json.source.language.toUpperCase());
- setPrivacy(json.source.privacy);
- setSensitive(json.source.sensitive ? json.source.sensitive : false);
- setFormat(json.source.status_format ? json.source.status_format : "plain");
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
- };
-
- return (
- <section className="posts">
- <h1>Post Settings</h1>
- <form>
- <div className="labelselect">
- <label htmlFor="language">Default post language</label>
- <select id="language" autoComplete="language" value={language} onChange={(e) => setLanguage(e.target.value)}>
- <Languages />
- </select>
- </div>
- <div className="labelselect">
- <label htmlFor="privacy">Default post privacy</label>
- <select id="privacy" value={privacy} onChange={(e) => setPrivacy(e.target.value)}>
- <option value="private">Private / followers-only)</option>
- <option value="unlisted">Unlisted</option>
- <option value="public">Public</option>
- </select>
- <a href="https://docs.gotosocial.org/en/latest/user_guide/posts/#privacy-settings" target="_blank" className="moreinfolink" rel="noreferrer">Learn more about post privacy settings (opens in a new tab)</a>
- </div>
- <div className="labelselect">
- <label htmlFor="format">Default post format</label>
- <select id="format" value={format} onChange={(e) => setFormat(e.target.value)}>
- <option value="plain">Plain (default)</option>
- <option value="markdown">Markdown</option>
- </select>
- <a href="https://docs.gotosocial.org/en/latest/user_guide/posts/#input-types" target="_blank" className="moreinfolink" rel="noreferrer">Learn more about post format settings (opens in a new tab)</a>
- </div>
- <div className="labelcheckbox">
- <label htmlFor="sensitive">Mark my posts as sensitive by default</label>
- <input id="sensitive" type="checkbox" checked={sensitive} onChange={(e) => setSensitive(e.target.checked)}/>
- </div>
- <Submit onClick={submit} label="Save post settings" errorMsg={errorMsg} statusMsg={statusMsg}/>
- </form>
- </section>
- );
-};
diff --git a/web/source/panels/user/security.js b/web/source/panels/user/security.js
@@ -1,80 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-"use strict";
-
-const React = require("react");
-const Promise = require("bluebird");
-
-const Submit = require("../../lib/submit");
-
-module.exports = function Security({oauth}) {
- const [errorMsg, setError] = React.useState("");
- const [statusMsg, setStatus] = React.useState("");
-
- const [oldPassword, setOldPassword] = React.useState("");
- const [newPassword, setNewPassword] = React.useState("");
- const [newPasswordConfirm, setNewPasswordConfirm] = React.useState("");
-
- const submit = (e) => {
- e.preventDefault();
-
- if (newPassword !== newPasswordConfirm) {
- setError("New password and confirm new password did not match!");
- return;
- }
-
- setStatus("PATCHing");
- setError("");
- return Promise.try(() => {
- let formDataInfo = new FormData();
- formDataInfo.set("old_password", oldPassword);
- formDataInfo.set("new_password", newPassword);
- return oauth.apiRequest("/api/v1/user/password_change", "POST", formDataInfo, "form");
- }).then((json) => {
- setStatus("Saved!");
- setOldPassword("");
- setNewPassword("");
- setNewPasswordConfirm("");
- }).catch((e) => {
- setError(e.message);
- setStatus("");
- });
- };
-
- return (
- <section className="security">
- <h1>Password Change</h1>
- <form>
- <div className="labelinput">
- <label htmlFor="password">Current password</label>
- <input name="password" id="password" type="password" autoComplete="current-password" value={oldPassword} onChange={(e) => setOldPassword(e.target.value)} />
- </div>
- <div className="labelinput">
- <label htmlFor="new-password">New password</label>
- <input name="new-password" id="new-password" type="password" autoComplete="new-password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
- </div>
- <div className="labelinput">
- <label htmlFor="confirm-new-password">Confirm new password</label>
- <input name="confirm-new-password" id="confirm-new-password" type="password" autoComplete="new-password" value={newPasswordConfirm} onChange={(e) => setNewPasswordConfirm(e.target.value)} />
- </div>
- <Submit onClick={submit} label="Save new password" errorMsg={errorMsg} statusMsg={statusMsg}/>
- </form>
- </section>
- );
-};
diff --git a/web/source/panels/user/style.css b/web/source/panels/user/style.css
@@ -1,118 +0,0 @@
-/*
- GoToSocial
- Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-section.basic, section.posts, section.security {
- form {
- display: flex;
- flex-direction: column;
- gap: 1rem;
-
- input, textarea {
- width: 100%;
- line-height: 1.5rem;
- }
-
- input[type=checkbox] {
- justify-self: start;
- width: initial;
- }
-
- input:read-only {
- border: none;
- }
-
- input:invalid {
- border-color: red;
- }
- }
-
- textarea {
- width: 100%;
- height: 8rem;
- }
-
- h1 {
- margin-bottom: 0.5rem;
- }
-
- img {
- display: flex;
- justify-content: center;
- align-items: center;
- border: $boxshadow_border;
- box-shadow: $box-shadow;
- object-fit: cover;
- border-radius: 0.2rem;
- box-sizing: border-box;
- margin-bottom: 0.5rem;
- }
-
- .avatarpreview {
- height: 8.5rem;
- width: 8.5rem;
- }
-
- .headerpreview {
- width: 100%;
- aspect-ratio: 3 / 1;
- overflow: hidden;
- }
-
- .moreinfolink {
- font-size: 0.9em;
- }
-}
-
-.labelinput .border {
- border-radius: 0.2rem;
- border: 0.15rem solid $border_accent;
- padding: 0.3rem;
- display: flex;
- flex-direction: column;
-}
-
-.file-input.button {
- display: inline-block;
- font-size: 1rem;
- font-weight: normal;
- padding: 0.3rem 0.3rem;
- align-self: flex-start;
- /* background: $border_accent; */
- margin-right: 0.2rem;
-}
-
-.labelinput, .labelselect {
- display: flex;
- flex-direction: column;
- gap: 0.4rem;
-}
-
-.labelcheckbox {
- display: flex;
- gap: 0.4rem;
-}
-
-.titlesave {
- display: flex;
- flex-wrap: wrap;
- gap: 0.4rem;
-}
-
-.logout {
- margin-bottom: 2rem;
-}
diff --git a/web/source/settings-panel/admin/actions.js b/web/source/settings-panel/admin/actions.js
@@ -0,0 +1,61 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+
+const Submit = require("../components/submit");
+
+const api = require("../lib/api");
+const submit = require("../lib/submit");
+
+module.exports = function AdminActionPanel() {
+ const dispatch = Redux.useDispatch();
+
+ const [days, setDays] = React.useState(30);
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ const removeMedia = submit(
+ () => dispatch(api.admin.mediaCleanup(days)),
+ {setStatus, setError}
+ );
+
+ return (
+ <>
+ <h1>Admin Actions</h1>
+ <div>
+ <h2>Media cleanup</h2>
+ <p>
+ Clean up remote media older than the specified number of days.
+ If the remote instance is still online they will be refetched when needed.
+ Also cleans up unused headers and avatars from the media cache.
+ </p>
+ <div>
+ <label htmlFor="days">Days: </label>
+ <input id="days" type="number" value={days} onChange={(e) => setDays(e.target.value)}/>
+ </div>
+ <Submit onClick={removeMedia} label="Remove media" errorMsg={errorMsg} statusMsg={statusMsg} />
+ </div>
+ </>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/admin/emoji.js b/web/source/settings-panel/admin/emoji.js
@@ -0,0 +1,212 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+const {Switch, Route, Link, Redirect, useRoute, useLocation} = require("wouter");
+
+const Submit = require("../components/submit");
+const FakeToot = require("../components/fake-toot");
+const { formFields } = require("../components/form-fields");
+
+const api = require("../lib/api");
+const adminActions = require("../redux/reducers/admin").actions;
+const submit = require("../lib/submit");
+
+const base = "/settings/admin/custom-emoji";
+
+module.exports = function CustomEmoji() {
+ return (
+ <Switch>
+ <Route path={`${base}/:emojiId`}>
+ <EmojiDetailWrapped />
+ </Route>
+ <EmojiOverview />
+ </Switch>
+ );
+};
+
+function EmojiOverview() {
+ const dispatch = Redux.useDispatch();
+ const [loaded, setLoaded] = React.useState(false);
+
+ const [errorMsg, setError] = React.useState("");
+
+ React.useEffect(() => {
+ if (!loaded) {
+ Promise.try(() => {
+ return dispatch(api.admin.fetchCustomEmoji());
+ }).then(() => {
+ setLoaded(true);
+ }).catch((e) => {
+ setLoaded(true);
+ setError(e.message);
+ });
+ }
+ }, []);
+
+ if (!loaded) {
+ return (
+ <>
+ <h1>Custom Emoji</h1>
+ Loading...
+ </>
+ );
+ }
+
+ return (
+ <>
+ <h1>Custom Emoji</h1>
+ <EmojiList/>
+ <NewEmoji/>
+ {errorMsg.length > 0 &&
+ <div className="error accent">{errorMsg}</div>
+ }
+ </>
+ );
+}
+
+const NewEmojiForm = formFields(adminActions.updateNewEmojiVal, (state) => state.admin.newEmoji);
+function NewEmoji() {
+ const dispatch = Redux.useDispatch();
+ const newEmojiForm = Redux.useSelector((state) => state.admin.newEmoji);
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ const uploadEmoji = submit(
+ () => dispatch(api.admin.newEmoji()),
+ {
+ setStatus, setError,
+ onSuccess: function() {
+ URL.revokeObjectURL(newEmojiForm.image);
+ return Promise.all([
+ dispatch(adminActions.updateNewEmojiVal(["image", undefined])),
+ dispatch(adminActions.updateNewEmojiVal(["imageFile", undefined])),
+ dispatch(adminActions.updateNewEmojiVal(["shortcode", ""])),
+ ]);
+ }
+ }
+ );
+
+ React.useEffect(() => {
+ if (newEmojiForm.shortcode.length == 0) {
+ if (newEmojiForm.imageFile != undefined) {
+ let [name, ext] = newEmojiForm.imageFile.name.split(".");
+ dispatch(adminActions.updateNewEmojiVal(["shortcode", name]));
+ }
+ }
+ });
+
+ let emojiOrShortcode = `:${newEmojiForm.shortcode}:`;
+
+ if (newEmojiForm.image != undefined) {
+ emojiOrShortcode = <img
+ className="emoji"
+ src={newEmojiForm.image}
+ title={`:${newEmojiForm.shortcode}:`}
+ alt={newEmojiForm.shortcode}
+ />;
+ }
+
+ return (
+ <div>
+ <h2>Add new custom emoji</h2>
+
+ <FakeToot>
+ Look at this new custom emoji {emojiOrShortcode} isn't it cool?
+ </FakeToot>
+
+ <NewEmojiForm.File
+ id="image"
+ name="Image"
+ fileType="image/png,image/gif"
+ showSize={true}
+ maxSize={50 * 1000}
+ />
+
+ <NewEmojiForm.TextInput
+ id="shortcode"
+ name="Shortcode (without : :), must be unique on the instance"
+ placeHolder="blobcat"
+ />
+
+ <Submit onClick={uploadEmoji} label="Upload" errorMsg={errorMsg} statusMsg={statusMsg} />
+ </div>
+ );
+}
+
+function EmojiList() {
+ const emoji = Redux.useSelector((state) => state.admin.emoji);
+
+ return (
+ <div>
+ <h2>Overview</h2>
+ <div className="list emoji-list">
+ {Object.entries(emoji).map(([category, entries]) => {
+ return <EmojiCategory key={category} category={category} entries={entries}/>;
+ })}
+ </div>
+ </div>
+ );
+}
+
+function EmojiCategory({category, entries}) {
+ return (
+ <div className="entry">
+ <b>{category}</b>
+ <div className="emoji-group">
+ {entries.map((e) => {
+ return (
+ // <Link key={e.static_url} to={`${base}/${e.shortcode}`}>
+ <Link key={e.static_url} to={`${base}`}>
+ <a>
+ <img src={e.static_url} alt={e.shortcode} title={`:${e.shortcode}:`}/>
+ </a>
+ </Link>
+ );
+ })}
+ </div>
+ </div>
+ );
+}
+
+function EmojiDetailWrapped() {
+ /* We wrap the component to generate formFields with a setter depending on the domain
+ if formFields() is used inside the same component that is re-rendered with their state,
+ inputs get re-created on every change, causing them to lose focus, and bad performance
+ */
+ let [_match, {emojiId}] = useRoute(`${base}/:emojiId`);
+
+ function alterEmoji([key, val]) {
+ return adminActions.updateDomainBlockVal([emojiId, key, val]);
+ }
+
+ const fields = formFields(alterEmoji, (state) => state.admin.blockedInstances[emojiId]);
+
+ return <EmojiDetail id={emojiId} Form={fields} />;
+}
+
+function EmojiDetail({id, Form}) {
+ return (
+ "Not implemented yet"
+ );
+}
+\ No newline at end of file
diff --git a/web/source/settings-panel/admin/federation.js b/web/source/settings-panel/admin/federation.js
@@ -0,0 +1,382 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+const {Switch, Route, Link, Redirect, useRoute, useLocation} = require("wouter");
+const fileDownload = require("js-file-download");
+
+const { formFields } = require("../components/form-fields");
+
+const api = require("../lib/api");
+const adminActions = require("../redux/reducers/admin").actions;
+const submit = require("../lib/submit");
+
+const base = "/settings/admin/federation";
+
+// const {
+// TextInput,
+// TextArea,
+// File
+// } = require("../components/form-fields").formFields(adminActions.setAdminSettingsVal, (state) => state.instances.adminSettings);
+
+module.exports = function AdminSettings() {
+ const dispatch = Redux.useDispatch();
+ // const instance = Redux.useSelector(state => state.instances.adminSettings);
+ const loadedBlockedInstances = Redux.useSelector(state => state.admin.loadedBlockedInstances);
+
+ React.useEffect(() => {
+ if (!loadedBlockedInstances ) {
+ Promise.try(() => {
+ return dispatch(api.admin.fetchDomainBlocks());
+ });
+ }
+ }, []);
+
+ if (!loadedBlockedInstances) {
+ return (
+ <div>
+ <h1>Federation</h1>
+ Loading...
+ </div>
+ );
+ }
+
+ return (
+ <Switch>
+ <Route path={`${base}/:domain`}>
+ <InstancePageWrapped />
+ </Route>
+ <InstanceOverview />
+ </Switch>
+ );
+};
+
+function InstanceOverview() {
+ const [filter, setFilter] = React.useState("");
+ const blockedInstances = Redux.useSelector(state => state.admin.blockedInstances);
+ const [_location, setLocation] = useLocation();
+
+ function filterFormSubmit(e) {
+ e.preventDefault();
+ setLocation(`${base}/${filter}`);
+ }
+
+ return (
+ <>
+ <h1>Federation</h1>
+ Here you can see an overview of blocked instances.
+
+ <div className="instance-list">
+ <h2>Blocked instances</h2>
+ <form action={`${base}/view`} className="filter" role="search" onSubmit={filterFormSubmit}>
+ <input name="domain" value={filter} onChange={(e) => setFilter(e.target.value)}/>
+ <Link to={`${base}/${filter}`}><a className="button">Add block</a></Link>
+ </form>
+ <div className="list">
+ {Object.values(blockedInstances).filter((a) => a.domain.startsWith(filter)).map((entry) => {
+ return (
+ <Link key={entry.domain} to={`${base}/${entry.domain}`}>
+ <a className="entry nounderline">
+ <span id="domain">
+ {entry.domain}
+ </span>
+ <span id="date">
+ {new Date(entry.created_at).toLocaleString()}
+ </span>
+ </a>
+ </Link>
+ );
+ })}
+ </div>
+ </div>
+
+ <BulkBlocking/>
+ </>
+ );
+}
+
+const Bulk = formFields(adminActions.updateBulkBlockVal, (state) => state.admin.bulkBlock);
+function BulkBlocking() {
+ const dispatch = Redux.useDispatch();
+ const {bulkBlock, blockedInstances} = Redux.useSelector(state => state.admin);
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ function importBlocks() {
+ setStatus("Processing");
+ setError("");
+ return Promise.try(() => {
+ return dispatch(api.admin.bulkDomainBlock());
+ }).then(({success, invalidDomains}) => {
+ return Promise.try(() => {
+ return resetBulk();
+ }).then(() => {
+ dispatch(adminActions.updateBulkBlockVal(["list", invalidDomains.join("\n")]));
+
+ let stat = "";
+ if (success == 0) {
+ return setError("No valid domains in import");
+ } else if (success == 1) {
+ stat = "Imported 1 domain";
+ } else {
+ stat = `Imported ${success} domains`;
+ }
+
+ if (invalidDomains.length > 0) {
+ if (invalidDomains.length == 1) {
+ stat += ", input contained 1 invalid domain.";
+ } else {
+ stat += `, input contained ${invalidDomains.length} invalid domains.`;
+ }
+ } else {
+ stat += "!";
+ }
+
+ setStatus(stat);
+ });
+ }).catch((e) => {
+ console.error(e);
+ setError(e.message);
+ setStatus("");
+ });
+ }
+
+ function exportBlocks() {
+ return Promise.try(() => {
+ setStatus("Exporting");
+ setError("");
+ let asJSON = bulkBlock.exportType.startsWith("json");
+ let _asCSV = bulkBlock.exportType.startsWith("csv");
+
+ let exportList = Object.values(blockedInstances).map((entry) => {
+ if (asJSON) {
+ return {
+ domain: entry.domain,
+ public_comment: entry.public_comment
+ };
+ } else {
+ return entry.domain;
+ }
+ });
+
+ if (bulkBlock.exportType == "json") {
+ return dispatch(adminActions.updateBulkBlockVal(["list", JSON.stringify(exportList)]));
+ } else if (bulkBlock.exportType == "json-download") {
+ return fileDownload(JSON.stringify(exportList), "block-export.json");
+ } else if (bulkBlock.exportType == "plain") {
+ return dispatch(adminActions.updateBulkBlockVal(["list", exportList.join("\n")]));
+ }
+ }).then(() => {
+ setStatus("Exported!");
+ }).catch((e) => {
+ setError(e.message);
+ setStatus("");
+ });
+ }
+
+ function resetBulk(e) {
+ if (e != undefined) {
+ e.preventDefault();
+ }
+ return dispatch(adminActions.resetBulkBlockVal());
+ }
+
+ function disableInfoFields(props={}) {
+ if (bulkBlock.list[0] == "[") {
+ return {
+ ...props,
+ disabled: true,
+ placeHolder: "Domain list is a JSON import, input disabled"
+ };
+ } else {
+ return props;
+ }
+ }
+
+ return (
+ <div className="bulk">
+ <h2>Import / Export <a onClick={resetBulk}>reset</a></h2>
+ <Bulk.TextArea
+ id="list"
+ name="Domains, one per line"
+ placeHolder={`google.com\nfacebook.com`}
+ />
+
+ <Bulk.TextArea
+ id="public_comment"
+ name="Public comment"
+ inputProps={disableInfoFields({rows: 3})}
+ />
+
+ <Bulk.TextArea
+ id="private_comment"
+ name="Private comment"
+ inputProps={disableInfoFields({rows: 3})}
+ />
+
+ <Bulk.Checkbox
+ id="obfuscate"
+ name="Obfuscate domains? "
+ inputProps={disableInfoFields()}
+ />
+
+ <div className="hidden">
+ <Bulk.File
+ id="json"
+ fileType="application/json"
+ withPreview={false}
+ />
+ </div>
+
+ <div className="messagebutton">
+ <div>
+ <button type="submit" onClick={importBlocks}>Import</button>
+ </div>
+
+ <div>
+ <button type="submit" onClick={exportBlocks}>Export</button>
+
+ <Bulk.Select id="exportType" name="Export type" options={
+ <>
+ <option value="plain">One per line in text field</option>
+ <option value="json">JSON in text field</option>
+ <option value="json-download">JSON file download</option>
+ <option disabled value="csv">CSV in text field (glitch-soc)</option>
+ <option disabled value="csv-download">CSV file download (glitch-soc)</option>
+ </>
+ }/>
+ </div>
+ <br/>
+ <div>
+ {errorMsg.length > 0 &&
+ <div className="error accent">{errorMsg}</div>
+ }
+ {statusMsg.length > 0 &&
+ <div className="accent">{statusMsg}</div>
+ }
+ </div>
+ </div>
+ </div>
+ );
+}
+
+function BackButton() {
+ return (
+ <Link to={base}>
+ <a className="button">< back</a>
+ </Link>
+ );
+}
+
+function InstancePageWrapped() {
+ /* We wrap the component to generate formFields with a setter depending on the domain
+ if formFields() is used inside the same component that is re-rendered with their state,
+ inputs get re-created on every change, causing them to lose focus, and bad performance
+ */
+ let [_match, {domain}] = useRoute(`${base}/:domain`);
+
+ if (domain == "view") { // from form field submission
+ let realDomain = (new URL(document.location)).searchParams.get("domain");
+ if (realDomain == undefined) {
+ return <Redirect to={base}/>;
+ } else {
+ domain = realDomain;
+ }
+ }
+
+ function alterDomain([key, val]) {
+ return adminActions.updateDomainBlockVal([domain, key, val]);
+ }
+
+ const fields = formFields(alterDomain, (state) => state.admin.newInstanceBlocks[domain]);
+
+ return <InstancePage domain={domain} Form={fields} />;
+}
+
+function InstancePage({domain, Form}) {
+ const dispatch = Redux.useDispatch();
+ const entry = Redux.useSelector(state => state.admin.newInstanceBlocks[domain]);
+ const [_location, setLocation] = useLocation();
+
+ React.useEffect(() => {
+ if (entry == undefined) {
+ dispatch(api.admin.getEditableDomainBlock(domain));
+ }
+ }, []);
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ if (entry == undefined) {
+ return "Loading...";
+ }
+
+ const updateBlock = submit(
+ () => dispatch(api.admin.updateDomainBlock(domain)),
+ {setStatus, setError}
+ );
+
+ const removeBlock = submit(
+ () => dispatch(api.admin.removeDomainBlock(domain)),
+ {setStatus, setError, startStatus: "Removing", successStatus: "Removed!", onSuccess: () => {
+ setLocation(base);
+ }}
+ );
+
+ return (
+ <div>
+ <h1><BackButton/> Federation settings for: {domain}</h1>
+ {entry.new && "No stored block yet, you can add one below:"}
+
+ <Form.TextArea
+ id="public_comment"
+ name="Public comment"
+ />
+
+ <Form.TextArea
+ id="private_comment"
+ name="Private comment"
+ />
+
+ <Form.Checkbox
+ id="obfuscate"
+ name="Obfuscate domain? "
+ />
+
+ <div className="messagebutton">
+ <button type="submit" onClick={updateBlock}>{entry.new ? "Add block" : "Save block"}</button>
+
+ {!entry.new &&
+ <button className="danger" onClick={removeBlock}>Remove block</button>
+ }
+
+ {errorMsg.length > 0 &&
+ <div className="error accent">{errorMsg}</div>
+ }
+ {statusMsg.length > 0 &&
+ <div className="accent">{statusMsg}</div>
+ }
+ </div>
+ </div>
+ );
+}
+\ No newline at end of file
diff --git a/web/source/settings-panel/admin/settings.js b/web/source/settings-panel/admin/settings.js
@@ -0,0 +1,110 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+
+const Submit = require("../components/submit");
+
+const api = require("../lib/api");
+const submit = require("../lib/submit");
+
+const adminActions = require("../redux/reducers/instances").actions;
+
+const {
+ TextInput,
+ TextArea,
+ File
+} = require("../components/form-fields").formFields(adminActions.setAdminSettingsVal, (state) => state.instances.adminSettings);
+
+module.exports = function AdminSettings() {
+ const dispatch = Redux.useDispatch();
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ const updateSettings = submit(
+ () => dispatch(api.admin.updateInstance()),
+ {setStatus, setError}
+ );
+
+ return (
+ <div>
+ <h1>Instance Settings</h1>
+ <TextInput
+ id="title"
+ name="Title"
+ placeHolder="My GoToSocial instance"
+ />
+
+ <TextArea
+ id="short_description"
+ name="Short description"
+ placeHolder="A small testing instance for the GoToSocial alpha."
+ />
+ <TextArea
+ id="description"
+ name="Full description"
+ placeHolder="A small testing instance for the GoToSocial alpha."
+ />
+
+ <TextInput
+ id="contact_account.username"
+ name="Contact user (local account username)"
+ placeHolder="admin"
+ />
+ <TextInput
+ id="email"
+ name="Contact email"
+ placeHolder="admin@example.com"
+ />
+
+ <TextArea
+ id="terms"
+ name="Terms & Conditions"
+ placeHolder=""
+ />
+
+ {/* <div className="file-upload">
+ <h3>Instance avatar</h3>
+ <div>
+ <img className="preview avatar" src={instance.avatar} alt={instance.avatar ? `Avatar image for the instance` : "No instance avatar image set"} />
+ <File
+ id="avatar"
+ fileType="image/*"
+ />
+ </div>
+ </div>
+
+ <div className="file-upload">
+ <h3>Instance header</h3>
+ <div>
+ <img className="preview header" src={instance.header} alt={instance.header ? `Header image for the instance` : "No instance header image set"} />
+ <File
+ id="header"
+ fileType="image/*"
+ />
+ </div>
+ </div> */}
+ <Submit onClick={updateSettings} label="Save" errorMsg={errorMsg} statusMsg={statusMsg} />
+ </div>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/components/error.jsx b/web/source/settings-panel/components/error.jsx
@@ -0,0 +1,45 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+
+module.exports = function ErrorFallback({error, resetErrorBoundary}) {
+ return (
+ <div className="error">
+ <p>
+ {"An error occured, please report this on the "}
+ <a href="https://github.com/superseriousbusiness/gotosocial/issues">GoToSocial issue tracker</a>
+ {" or "}
+ <a href="https://matrix.to/#/#gotosocial-help:superseriousbusiness.org">Matrix support room</a>.
+ <br/>Include the details below:
+ </p>
+ <pre>
+ {error.name}: {error.message}
+ </pre>
+ <pre>
+ {error.stack}
+ </pre>
+ <p>
+ <button onClick={resetErrorBoundary}>Try again</button> or <a href="">refresh the page</a>
+ </p>
+ </div>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/components/fake-toot.jsx b/web/source/settings-panel/components/fake-toot.jsx
@@ -0,0 +1,43 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const React = require("react");
+const Redux = require("react-redux");
+
+module.exports = function FakeToot({children}) {
+ const account = Redux.useSelector((state) => state.user.profile);
+
+ return (
+ <div className="toot expanded">
+ <div className="contentgrid">
+ <span className="avatar">
+ <img src={account.avatar} alt=""/>
+ </span>
+ <span className="displayname">{account.display_name.trim().length > 0 ? account.display_name : account.username}</span>
+ <span className="username">@{account.username}</span>
+ <div className="text">
+ <div className="content">
+ {children}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/components/form-fields.jsx b/web/source/settings-panel/components/form-fields.jsx
@@ -0,0 +1,167 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const React = require("react");
+const Redux = require("react-redux");
+const d = require("dotty");
+const prettierBytes = require("prettier-bytes");
+
+function eventListeners(dispatch, setter, obj) {
+ return {
+ onTextChange: function (key) {
+ return function (e) {
+ dispatch(setter([key, e.target.value]));
+ };
+ },
+
+ onCheckChange: function (key) {
+ return function (e) {
+ dispatch(setter([key, e.target.checked]));
+ };
+ },
+
+ onFileChange: function (key, withPreview) {
+ return function (e) {
+ let file = e.target.files[0];
+ if (withPreview) {
+ let old = d.get(obj, key);
+ if (old != undefined) {
+ URL.revokeObjectURL(old); // no error revoking a non-Object URL as provided by instance
+ }
+ let objectURL = URL.createObjectURL(file);
+ dispatch(setter([key, objectURL]));
+ }
+ dispatch(setter([`${key}File`, file]));
+ };
+ }
+ };
+}
+
+function get(state, id, defaultVal) {
+ let value;
+ if (id.includes(".")) {
+ value = d.get(state, id);
+ } else {
+ value = state[id];
+ }
+ if (value == undefined) {
+ value = defaultVal;
+ }
+ return value;
+}
+
+// function removeFile(name) {
+// return function(e) {
+// e.preventDefault();
+// dispatch(user.setProfileVal([name, ""]));
+// dispatch(user.setProfileVal([`${name}File`, ""]));
+// };
+// }
+
+module.exports = {
+ formFields: function formFields(setter, selector) {
+ function FormField({
+ type, id, name, className="", placeHolder="", fileType="", children=null,
+ options=null, inputProps={}, withPreview=true, showSize=false, maxSize=Infinity
+ }) {
+ const dispatch = Redux.useDispatch();
+ let state = Redux.useSelector(selector);
+ let {
+ onTextChange,
+ onCheckChange,
+ onFileChange
+ } = eventListeners(dispatch, setter, state);
+
+ let field;
+ let defaultLabel = true;
+ if (type == "text") {
+ field = <input type="text" id={id} value={get(state, id, "")} placeholder={placeHolder} className={className} onChange={onTextChange(id)} {...inputProps}/>;
+ } else if (type == "textarea") {
+ field = <textarea type="text" id={id} value={get(state, id, "")} placeholder={placeHolder} className={className} onChange={onTextChange(id)} rows={8} {...inputProps}/>;
+ } else if (type == "checkbox") {
+ field = <input type="checkbox" id={id} checked={get(state, id, false)} className={className} onChange={onCheckChange(id)} {...inputProps}/>;
+ } else if (type == "select") {
+ field = (
+ <select id={id} value={get(state, id, "")} className={className} onChange={onTextChange(id)} {...inputProps}>
+ {options}
+ </select>
+ );
+ } else if (type == "file") {
+ defaultLabel = false;
+ let file = get(state, `${id}File`);
+
+ let size = null;
+ if (showSize && file) {
+ size = `(${prettierBytes(file.size)})`;
+
+ if (file.size > maxSize) {
+ size = <span className="error-text">{size}</span>;
+ }
+ }
+
+ field = (
+ <>
+ <label htmlFor={id} className="file-input button">Browse</label>
+ <span>
+ {file ? file.name : "no file selected"} {size}
+ </span>
+ {/* <a onClick={removeFile("header")}>remove</a> */}
+ <input className="hidden" id={id} type="file" accept={fileType} onChange={onFileChange(id, withPreview)} {...inputProps}/>
+ </>
+ );
+ } else {
+ defaultLabel = false;
+ field = `unsupported FormField ${type}, this is a developer error`;
+ }
+
+ let label = <label htmlFor={id}>{name}</label>;
+ return (
+ <div className={`form-field ${type}`}>
+ {defaultLabel ? label : null} {field}
+ {children}
+ </div>
+ );
+ }
+
+ return {
+ TextInput: function(props) {
+ return <FormField type="text" {...props} />;
+ },
+
+ TextArea: function(props) {
+ return <FormField type="textarea" {...props} />;
+ },
+
+ Checkbox: function(props) {
+ return <FormField type="checkbox" {...props} />;
+ },
+
+ Select: function(props) {
+ return <FormField type="select" {...props} />;
+ },
+
+ File: function(props) {
+ return <FormField type="file" {...props} />;
+ },
+ };
+ },
+
+ eventListeners
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/components/languages.jsx b/web/source/settings-panel/components/languages.jsx
@@ -0,0 +1,98 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const React = require("react");
+
+module.exports = function Languages() {
+ return <React.Fragment>
+ <option value="AF">Afrikaans</option>
+ <option value="SQ">Albanian</option>
+ <option value="AR">Arabic</option>
+ <option value="HY">Armenian</option>
+ <option value="EU">Basque</option>
+ <option value="BN">Bengali</option>
+ <option value="BG">Bulgarian</option>
+ <option value="CA">Catalan</option>
+ <option value="KM">Cambodian</option>
+ <option value="ZH">Chinese (Mandarin)</option>
+ <option value="HR">Croatian</option>
+ <option value="CS">Czech</option>
+ <option value="DA">Danish</option>
+ <option value="NL">Dutch</option>
+ <option value="EN">English</option>
+ <option value="ET">Estonian</option>
+ <option value="FJ">Fiji</option>
+ <option value="FI">Finnish</option>
+ <option value="FR">French</option>
+ <option value="KA">Georgian</option>
+ <option value="DE">German</option>
+ <option value="EL">Greek</option>
+ <option value="GU">Gujarati</option>
+ <option value="HE">Hebrew</option>
+ <option value="HI">Hindi</option>
+ <option value="HU">Hungarian</option>
+ <option value="IS">Icelandic</option>
+ <option value="ID">Indonesian</option>
+ <option value="GA">Irish</option>
+ <option value="IT">Italian</option>
+ <option value="JA">Japanese</option>
+ <option value="JW">Javanese</option>
+ <option value="KO">Korean</option>
+ <option value="LA">Latin</option>
+ <option value="LV">Latvian</option>
+ <option value="LT">Lithuanian</option>
+ <option value="MK">Macedonian</option>
+ <option value="MS">Malay</option>
+ <option value="ML">Malayalam</option>
+ <option value="MT">Maltese</option>
+ <option value="MI">Maori</option>
+ <option value="MR">Marathi</option>
+ <option value="MN">Mongolian</option>
+ <option value="NE">Nepali</option>
+ <option value="NO">Norwegian</option>
+ <option value="FA">Persian</option>
+ <option value="PL">Polish</option>
+ <option value="PT">Portuguese</option>
+ <option value="PA">Punjabi</option>
+ <option value="QU">Quechua</option>
+ <option value="RO">Romanian</option>
+ <option value="RU">Russian</option>
+ <option value="SM">Samoan</option>
+ <option value="SR">Serbian</option>
+ <option value="SK">Slovak</option>
+ <option value="SL">Slovenian</option>
+ <option value="ES">Spanish</option>
+ <option value="SW">Swahili</option>
+ <option value="SV">Swedish </option>
+ <option value="TA">Tamil</option>
+ <option value="TT">Tatar</option>
+ <option value="TE">Telugu</option>
+ <option value="TH">Thai</option>
+ <option value="BO">Tibetan</option>
+ <option value="TO">Tonga</option>
+ <option value="TR">Turkish</option>
+ <option value="UK">Ukrainian</option>
+ <option value="UR">Urdu</option>
+ <option value="UZ">Uzbek</option>
+ <option value="VI">Vietnamese</option>
+ <option value="CY">Welsh</option>
+ <option value="XH">Xhosa</option>
+ </React.Fragment>;
+};
diff --git a/web/source/settings-panel/components/login.jsx b/web/source/settings-panel/components/login.jsx
@@ -0,0 +1,102 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+
+const { setInstance } = require("../redux/reducers/oauth").actions;
+const api = require("../lib/api");
+
+module.exports = function Login({error}) {
+ const dispatch = Redux.useDispatch();
+ const [ instanceField, setInstanceField ] = React.useState("");
+ const [ errorMsg, setErrorMsg ] = React.useState();
+ const instanceFieldRef = React.useRef("");
+
+ React.useEffect(() => {
+ // check if current domain runs an instance
+ let currentDomain = window.location.origin;
+ Promise.try(() => {
+ return dispatch(api.instance.fetchWithoutStore(currentDomain));
+ }).then(() => {
+ if (instanceFieldRef.current.length == 0) { // user hasn't started typing yet
+ dispatch(setInstance(currentDomain));
+ instanceFieldRef.current = currentDomain;
+ setInstanceField(currentDomain);
+ }
+ }).catch((e) => {
+ console.log("Current domain does not host a valid instance: ", e);
+ });
+ }, []);
+
+ function tryInstance() {
+ let domain = instanceFieldRef.current;
+ Promise.try(() => {
+ return dispatch(api.instance.fetchWithoutStore(domain)).catch((e) => {
+ // TODO: clearer error messages for common errors
+ console.log(e);
+ throw e;
+ });
+ }).then(() => {
+ dispatch(setInstance(domain));
+
+ return dispatch(api.oauth.register()).catch((e) => {
+ console.log(e);
+ throw e;
+ });
+ }).then(() => {
+ return dispatch(api.oauth.authorize()); // will send user off-page
+ }).catch((e) => {
+ setErrorMsg(
+ <>
+ <b>{e.type}</b>
+ <span>{e.message}</span>
+ </>
+ );
+ });
+ }
+
+ function updateInstanceField(e) {
+ if (e.key == "Enter") {
+ tryInstance(instanceField);
+ } else {
+ setInstanceField(e.target.value);
+ instanceFieldRef.current = e.target.value;
+ }
+ }
+
+ return (
+ <section className="login">
+ <h1>OAUTH Login:</h1>
+ {error}
+ <form onSubmit={(e) => e.preventDefault()}>
+ <label htmlFor="instance">Instance: </label>
+ <input value={instanceField} onChange={updateInstanceField} id="instance"/>
+ {errorMsg &&
+ <div className="error">
+ {errorMsg}
+ </div>
+ }
+ <button onClick={tryInstance}>Authenticate</button>
+ </form>
+ </section>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/components/nav-button.jsx b/web/source/settings-panel/components/nav-button.jsx
@@ -0,0 +1,33 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const React = require("react");
+const { Link, useRoute } = require("wouter");
+
+module.exports = function NavButton({href, name}) {
+ const [isActive] = useRoute(`${href}/:anything?`);
+ return (
+ <Link href={href}>
+ <a className={isActive ? "active" : ""} data-content={name}>
+ {name}
+ </a>
+ </Link>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/components/submit.jsx b/web/source/settings-panel/components/submit.jsx
@@ -0,0 +1,35 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const React = require("react");
+
+module.exports = function Submit({onClick, label, errorMsg, statusMsg}) {
+ return (
+ <div className="messagebutton">
+ <button type="submit" onClick={onClick}>{ label }</button>
+ {errorMsg.length > 0 &&
+ <div className="error accent">{errorMsg}</div>
+ }
+ {statusMsg.length > 0 &&
+ <div className="accent">{statusMsg}</div>
+ }
+ </div>
+ );
+};
diff --git a/web/source/settings-panel/index.js b/web/source/settings-panel/index.js
@@ -0,0 +1,178 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const ReactDom = require("react-dom/client");
+const Redux = require("react-redux");
+const { Switch, Route, Redirect } = require("wouter");
+const { Provider } = require("react-redux");
+const { PersistGate } = require("redux-persist/integration/react");
+
+const { store, persistor } = require("./redux");
+const api = require("./lib/api");
+const oauth = require("./redux/reducers/oauth").actions;
+const { AuthenticationError } = require("./lib/errors");
+
+const Login = require("./components/login");
+
+require("./style.css");
+
+// TODO: nested categories?
+const nav = {
+ "User": {
+ "Profile": require("./user/profile.js"),
+ "Settings": require("./user/settings.js"),
+ },
+ "Admin": {
+ adminOnly: true,
+ "Instance Settings": require("./admin/settings.js"),
+ "Actions": require("./admin/actions"),
+ "Federation": require("./admin/federation.js"),
+ "Custom Emoji": require("./admin/emoji.js"),
+ }
+};
+
+const { sidebar, panelRouter } = require("./lib/get-views")(nav);
+
+function App() {
+ const dispatch = Redux.useDispatch();
+
+ const { loginState, isAdmin } = Redux.useSelector((state) => state.oauth);
+ const reduxTempStatus = Redux.useSelector((state) => state.temporary.status);
+
+ const [errorMsg, setErrorMsg] = React.useState();
+ const [tokenChecked, setTokenChecked] = React.useState(false);
+
+ React.useEffect(() => {
+ if (loginState == "login" || loginState == "callback") {
+ Promise.try(() => {
+ // Process OAUTH authorization token from URL if available
+ if (loginState == "callback") {
+ let urlParams = new URLSearchParams(window.location.search);
+ let code = urlParams.get("code");
+
+ if (code == undefined) {
+ setErrorMsg(new Error("Waiting for OAUTH callback but no ?code= provided. You can try logging in again:"));
+ } else {
+ return dispatch(api.oauth.tokenize(code));
+ }
+ }
+ }).then(() => {
+ // Fetch current instance info
+ return dispatch(api.instance.fetch());
+ }).then(() => {
+ // Check currently stored auth token for validity if available
+ return dispatch(api.user.fetchAccount());
+ }).then(() => {
+ setTokenChecked(true);
+
+ return dispatch(api.oauth.checkIfAdmin());
+ }).catch((e) => {
+ if (e instanceof AuthenticationError) {
+ dispatch(oauth.remove());
+ e.message = "Stored OAUTH token no longer valid, please log in again.";
+ }
+ setErrorMsg(e);
+ console.error(e);
+ });
+ }
+ }, []);
+
+ let ErrorElement = null;
+ if (errorMsg != undefined) {
+ ErrorElement = (
+ <div className="error">
+ <b>{errorMsg.type}</b>
+ <span>{errorMsg.message}</span>
+ </div>
+ );
+ }
+
+ const LogoutElement = (
+ <button className="logout" onClick={() => { dispatch(api.oauth.logout()); }}>
+ Log out
+ </button>
+ );
+
+ if (reduxTempStatus != undefined) {
+ return (
+ <section>
+ {reduxTempStatus}
+ </section>
+ );
+ } else if (tokenChecked && loginState == "login") {
+ return (
+ <>
+ <div className="sidebar">
+ {sidebar.all}
+ {isAdmin && sidebar.admin}
+ {LogoutElement}
+ </div>
+ <section className="with-sidebar">
+ {ErrorElement}
+ <Switch>
+ {panelRouter.all}
+ {isAdmin && panelRouter.admin}
+ <Route> {/* default route */}
+ <Redirect to="/settings/user" />
+ </Route>
+ </Switch>
+ </section>
+ </>
+ );
+ } else if (loginState == "none") {
+ return (
+ <Login error={ErrorElement} />
+ );
+ } else {
+ let status;
+
+ if (loginState == "login") {
+ status = "Verifying stored login...";
+ } else if (loginState == "callback") {
+ status = "Processing OAUTH callback...";
+ }
+
+ return (
+ <section>
+ <div>
+ {status}
+ </div>
+ {ErrorElement}
+ {LogoutElement}
+ </section>
+ );
+ }
+
+}
+
+function Main() {
+ return (
+ <Provider store={store}>
+ <PersistGate loading={"loading..."} persistor={persistor}>
+ <App />
+ </PersistGate>
+ </Provider>
+ );
+}
+
+const root = ReactDom.createRoot(document.getElementById("root"));
+root.render(<React.StrictMode><Main /></React.StrictMode>);
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/api/admin.js b/web/source/settings-panel/lib/api/admin.js
@@ -0,0 +1,192 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const isValidDomain = require("is-valid-domain");
+
+const instance = require("../../redux/reducers/instances").actions;
+const admin = require("../../redux/reducers/admin").actions;
+
+module.exports = function ({ apiCall, getChanges }) {
+ const adminAPI = {
+ updateInstance: function updateInstance() {
+ return function (dispatch, getState) {
+ return Promise.try(() => {
+ const state = getState().instances.adminSettings;
+
+ const update = getChanges(state, {
+ formKeys: ["title", "short_description", "description", "contact_account.username", "email", "terms"],
+ renamedKeys: {"contact_account.username": "contact_username"},
+ // fileKeys: ["avatar", "header"]
+ });
+
+ return dispatch(apiCall("PATCH", "/api/v1/instance", update, "form"));
+ }).then((data) => {
+ return dispatch(instance.setInstanceInfo(data));
+ });
+ };
+ },
+
+ fetchDomainBlocks: function fetchDomainBlocks() {
+ return function (dispatch, _getState) {
+ return Promise.try(() => {
+ return dispatch(apiCall("GET", "/api/v1/admin/domain_blocks"));
+ }).then((data) => {
+ return dispatch(admin.setBlockedInstances(data));
+ });
+ };
+ },
+
+ updateDomainBlock: function updateDomainBlock(domain) {
+ return function (dispatch, getState) {
+ return Promise.try(() => {
+ const state = getState().admin.newInstanceBlocks[domain];
+ const update = getChanges(state, {
+ formKeys: ["domain", "obfuscate", "public_comment", "private_comment"],
+ });
+
+ return dispatch(apiCall("POST", "/api/v1/admin/domain_blocks", update, "form"));
+ }).then((block) => {
+ return Promise.all([
+ dispatch(admin.newDomainBlock([domain, block])),
+ dispatch(admin.setDomainBlock([domain, block]))
+ ]);
+ });
+ };
+ },
+
+ getEditableDomainBlock: function getEditableDomainBlock(domain) {
+ return function (dispatch, getState) {
+ let data = getState().admin.blockedInstances[domain];
+ return dispatch(admin.newDomainBlock([domain, data]));
+ };
+ },
+
+ bulkDomainBlock: function bulkDomainBlock() {
+ return function (dispatch, getState) {
+ let invalidDomains = [];
+ let success = 0;
+
+ return Promise.try(() => {
+ const state = getState().admin.bulkBlock;
+ let list = state.list;
+ let domains;
+
+ let fields = getChanges(state, {
+ formKeys: ["obfuscate", "public_comment", "private_comment"]
+ });
+
+ let defaultDate = new Date().toUTCString();
+
+ if (list[0] == "[") {
+ domains = JSON.parse(state.list);
+ } else {
+ domains = list.split("\n").map((line_) => {
+ let line = line_.trim();
+ if (line.length == 0) {
+ return null;
+ }
+
+ if (!isValidDomain(line, {wildcard: true, allowUnicode: true})) {
+ invalidDomains.push(line);
+ return null;
+ }
+
+ return {
+ domain: line,
+ created_at: defaultDate,
+ ...fields
+ };
+ }).filter((a) => a != null);
+ }
+
+ if (domains.length == 0) {
+ return;
+ }
+
+ const update = {
+ domains: new Blob([JSON.stringify(domains)], {type: "application/json"})
+ };
+
+ return dispatch(apiCall("POST", "/api/v1/admin/domain_blocks?import=true", update, "form"));
+ }).then((blocks) => {
+ if (blocks != undefined) {
+ return Promise.each(blocks, (block) => {
+ success += 1;
+ return dispatch(admin.setDomainBlock([block.domain, block]));
+ });
+ }
+ }).then(() => {
+ return {
+ success,
+ invalidDomains
+ };
+ });
+ };
+ },
+
+ removeDomainBlock: function removeDomainBlock(domain) {
+ return function (dispatch, getState) {
+ return Promise.try(() => {
+ const id = getState().admin.blockedInstances[domain].id;
+ return dispatch(apiCall("DELETE", `/api/v1/admin/domain_blocks/${id}`));
+ }).then((removed) => {
+ return dispatch(admin.removeDomainBlock(removed.domain));
+ });
+ };
+ },
+
+ mediaCleanup: function mediaCleanup(days) {
+ return function (dispatch, _getState) {
+ return Promise.try(() => {
+ return dispatch(apiCall("POST", `/api/v1/admin/media_cleanup?remote_cache_days=${days}`));
+ });
+ };
+ },
+
+ fetchCustomEmoji: function fetchCustomEmoji() {
+ return function (dispatch, _getState) {
+ return Promise.try(() => {
+ return dispatch(apiCall("GET", "/api/v1/custom_emojis"));
+ }).then((emoji) => {
+ return dispatch(admin.setEmoji(emoji));
+ });
+ };
+ },
+
+ newEmoji: function newEmoji() {
+ return function (dispatch, getState) {
+ return Promise.try(() => {
+ const state = getState().admin.newEmoji;
+
+ const update = getChanges(state, {
+ formKeys: ["shortcode"],
+ fileKeys: ["image"]
+ });
+
+ return dispatch(apiCall("POST", "/api/v1/admin/custom_emojis", update, "form"));
+ }).then((emoji) => {
+ return dispatch(admin.addEmoji(emoji));
+ });
+ };
+ }
+ };
+ return adminAPI;
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/api/index.js b/web/source/settings-panel/lib/api/index.js
@@ -0,0 +1,185 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const { isPlainObject } = require("is-plain-object");
+const d = require("dotty");
+
+const { APIError, AuthenticationError } = require("../errors");
+const { setInstanceInfo, setNamedInstanceInfo } = require("../../redux/reducers/instances").actions;
+const oauth = require("../../redux/reducers/oauth").actions;
+
+function apiCall(method, route, payload, type = "json") {
+ return function (dispatch, getState) {
+ const state = getState();
+ let base = state.oauth.instance;
+ let auth = state.oauth.token;
+ console.log(method, base, route, "auth:", auth != undefined);
+
+ return Promise.try(() => {
+ let url = new URL(base);
+ let [path, query] = route.split("?");
+ url.pathname = path;
+ if (query != undefined) {
+ url.search = query;
+ }
+ let body;
+
+ let headers = {
+ "Accept": "application/json",
+ };
+
+ if (payload != undefined) {
+ if (type == "json") {
+ headers["Content-Type"] = "application/json";
+ body = JSON.stringify(payload);
+ } else if (type == "form") {
+ const formData = new FormData();
+ Object.entries(payload).forEach(([key, val]) => {
+ if (isPlainObject(val)) {
+ Object.entries(val).forEach(([key2, val2]) => {
+ if (val2 != undefined) {
+ formData.set(`${key}[${key2}]`, val2);
+ }
+ });
+ } else {
+ if (val != undefined) {
+ formData.set(key, val);
+ }
+ }
+ });
+ body = formData;
+ }
+ }
+
+ if (auth != undefined) {
+ headers["Authorization"] = auth;
+ }
+
+ return fetch(url.toString(), {
+ method,
+ headers,
+ body
+ });
+ }).then((res) => {
+ // try parse json even with error
+ let json = res.json().catch((e) => {
+ throw new APIError(`JSON parsing error: ${e.message}`);
+ });
+
+ return Promise.all([res, json]);
+ }).then(([res, json]) => {
+ if (!res.ok) {
+ if (auth != undefined && (res.status == 401 || res.status == 403)) {
+ // stored access token is invalid
+ throw new AuthenticationError("401: Authentication error", {json, status: res.status});
+ } else {
+ throw new APIError(json.error, { json });
+ }
+ } else {
+ return json;
+ }
+ });
+ };
+}
+
+function getChanges(state, keys) {
+ const { formKeys = [], fileKeys = [], renamedKeys = {} } = keys;
+ const update = {};
+
+ formKeys.forEach((key) => {
+ let value = d.get(state, key);
+ if (value == undefined) {
+ return;
+ }
+ if (renamedKeys[key]) {
+ key = renamedKeys[key];
+ }
+ d.put(update, key, value);
+ });
+
+ fileKeys.forEach((key) => {
+ let file = d.get(state, `${key}File`);
+ if (file != undefined) {
+ if (renamedKeys[key]) {
+ key = renamedKeys[key];
+ }
+ d.put(update, key, file);
+ }
+ });
+
+ return update;
+}
+
+function getCurrentUrl() {
+ return `${window.location.origin}${window.location.pathname}`;
+}
+
+function fetchInstanceWithoutStore(domain) {
+ return function (dispatch, getState) {
+ return Promise.try(() => {
+ let lookup = getState().instances.info[domain];
+ if (lookup != undefined) {
+ return lookup;
+ }
+
+ // apiCall expects to pull the domain from state,
+ // but we don't want to store it there yet
+ // so we mock the API here with our function argument
+ let fakeState = {
+ oauth: { instance: domain }
+ };
+
+ return apiCall("GET", "/api/v1/instance")(dispatch, () => fakeState);
+ }).then((json) => {
+ if (json && json.uri) { // TODO: validate instance json more?
+ dispatch(setNamedInstanceInfo([domain, json]));
+ return json;
+ }
+ });
+ };
+}
+
+function fetchInstance() {
+ return function (dispatch, _getState) {
+ return Promise.try(() => {
+ return dispatch(apiCall("GET", "/api/v1/instance"));
+ }).then((json) => {
+ if (json && json.uri) {
+ dispatch(setInstanceInfo(json));
+ return json;
+ }
+ });
+ };
+}
+
+let submoduleArgs = { apiCall, getCurrentUrl, getChanges };
+
+module.exports = {
+ instance: {
+ fetchWithoutStore: fetchInstanceWithoutStore,
+ fetch: fetchInstance
+ },
+ oauth: require("./oauth")(submoduleArgs),
+ user: require("./user")(submoduleArgs),
+ admin: require("./admin")(submoduleArgs),
+ apiCall,
+ getChanges
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/api/oauth.js b/web/source/settings-panel/lib/api/oauth.js
@@ -0,0 +1,124 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+
+const { OAUTHError, AuthenticationError } = require("../errors");
+
+const oauth = require("../../redux/reducers/oauth").actions;
+const temporary = require("../../redux/reducers/temporary").actions;
+const admin = require("../../redux/reducers/admin").actions;
+
+module.exports = function oauthAPI({ apiCall, getCurrentUrl }) {
+ return {
+
+ register: function register(scopes = []) {
+ return function (dispatch, _getState) {
+ return Promise.try(() => {
+ return dispatch(apiCall("POST", "/api/v1/apps", {
+ client_name: "GoToSocial Settings",
+ scopes: scopes.join(" "),
+ redirect_uris: getCurrentUrl(),
+ website: getCurrentUrl()
+ }));
+ }).then((json) => {
+ json.scopes = scopes;
+ dispatch(oauth.setRegistration(json));
+ });
+ };
+ },
+
+ authorize: function authorize() {
+ return function (dispatch, getState) {
+ let state = getState();
+ let reg = state.oauth.registration;
+ let base = new URL(state.oauth.instance);
+
+ base.pathname = "/oauth/authorize";
+ base.searchParams.set("client_id", reg.client_id);
+ base.searchParams.set("redirect_uri", getCurrentUrl());
+ base.searchParams.set("response_type", "code");
+ base.searchParams.set("scope", reg.scopes.join(" "));
+
+ dispatch(oauth.setLoginState("callback"));
+ dispatch(temporary.setStatus("Redirecting to instance login..."));
+
+ // send user to instance's login flow
+ window.location.assign(base.href);
+ };
+ },
+
+ tokenize: function tokenize(code) {
+ return function (dispatch, getState) {
+ let reg = getState().oauth.registration;
+
+ return Promise.try(() => {
+ if (reg == undefined || reg.client_id == undefined) {
+ throw new OAUTHError("Callback code present, but no client registration is available from localStorage. \nNote: localStorage is unavailable in Private Browsing.");
+ }
+
+ return dispatch(apiCall("POST", "/oauth/token", {
+ client_id: reg.client_id,
+ client_secret: reg.client_secret,
+ redirect_uri: getCurrentUrl(),
+ grant_type: "authorization_code",
+ code: code
+ }));
+ }).then((json) => {
+ window.history.replaceState({}, document.title, window.location.pathname);
+ return dispatch(oauth.login(json));
+ });
+ };
+ },
+
+ checkIfAdmin: function checkIfAdmin() {
+ return function (dispatch, getState) {
+ const state = getState();
+ let stored = state.oauth.isAdmin;
+ if (stored != undefined) {
+ return stored;
+ }
+
+ // newer GoToSocial version will include a `role` in the Account data, check that first
+ // TODO: check account data for admin status
+
+ // no role info, try fetching an admin-only route and see if we get an error
+ return Promise.try(() => {
+ return dispatch(apiCall("GET", "/api/v1/admin/domain_blocks"));
+ }).then((data) => {
+ return Promise.all([
+ dispatch(oauth.setAdmin(true)),
+ dispatch(admin.setBlockedInstances(data))
+ ]);
+ }).catch(AuthenticationError, () => {
+ return dispatch(oauth.setAdmin(false));
+ });
+ };
+ },
+
+ logout: function logout() {
+ return function (dispatch, _getState) {
+ // TODO: GoToSocial does not have a logout API route yet
+
+ return dispatch(oauth.remove());
+ };
+ }
+ };
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/api/user.js b/web/source/settings-panel/lib/api/user.js
@@ -0,0 +1,67 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+
+const user = require("../../redux/reducers/user").actions;
+
+module.exports = function ({ apiCall, getChanges }) {
+ function updateCredentials(selector, keys) {
+ return function (dispatch, getState) {
+ return Promise.try(() => {
+ const state = selector(getState());
+
+ const update = getChanges(state, keys);
+
+ return dispatch(apiCall("PATCH", "/api/v1/accounts/update_credentials", update, "form"));
+ }).then((account) => {
+ return dispatch(user.setAccount(account));
+ });
+ };
+ }
+
+ return {
+ fetchAccount: function fetchAccount() {
+ return function (dispatch, _getState) {
+ return Promise.try(() => {
+ return dispatch(apiCall("GET", "/api/v1/accounts/verify_credentials"));
+ }).then((account) => {
+ return dispatch(user.setAccount(account));
+ });
+ };
+ },
+
+ updateProfile: function updateProfile() {
+ const formKeys = ["display_name", "locked", "source", "custom_css", "source.note"];
+ const renamedKeys = {
+ "source.note": "note"
+ };
+ const fileKeys = ["header", "avatar"];
+
+ return updateCredentials((state) => state.user.profile, {formKeys, renamedKeys, fileKeys});
+ },
+
+ updateSettings: function updateProfile() {
+ const formKeys = ["source"];
+
+ return updateCredentials((state) => state.user.settings, {formKeys});
+ }
+ };
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/errors.js b/web/source/settings-panel/lib/errors.js
@@ -0,0 +1,27 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const createError = require("create-error");
+
+module.exports = {
+ APIError: createError("APIError"),
+ OAUTHError: createError("OAUTHError"),
+ AuthenticationError: createError("AuthenticationError"),
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/get-views.js b/web/source/settings-panel/lib/get-views.js
@@ -0,0 +1,102 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const React = require("react");
+const Redux = require("react-redux");
+const { Link, Route, Switch, Redirect } = require("wouter");
+const { ErrorBoundary } = require("react-error-boundary");
+
+const ErrorFallback = require("../components/error");
+const NavButton = require("../components/nav-button");
+
+function urlSafe(str) {
+ return str.toLowerCase().replace(/\s+/g, "-");
+}
+
+module.exports = function getViews(struct) {
+ const sidebar = {
+ all: [],
+ admin: [],
+ };
+
+ const panelRouter = {
+ all: [],
+ admin: [],
+ };
+
+ Object.entries(struct).forEach(([name, entries]) => {
+ let sidebarEl = sidebar.all;
+ let panelRouterEl = panelRouter.all;
+
+ if (entries.adminOnly) {
+ sidebarEl = sidebar.admin;
+ panelRouterEl = panelRouter.admin;
+ delete entries.adminOnly;
+ }
+
+ let base = `/settings/${urlSafe(name)}`;
+
+ let links = [];
+
+ let firstRoute;
+
+ Object.entries(entries).forEach(([name, ViewComponent]) => {
+ let url = `${base}/${urlSafe(name)}`;
+
+ if (firstRoute == undefined) {
+ firstRoute = url;
+ }
+
+ panelRouterEl.push((
+ <Route path={`${url}/:page?`} key={url}>
+ <ErrorBoundary FallbackComponent={ErrorFallback} onReset={() => { }}>
+ {/* FIXME: implement onReset */}
+ <ViewComponent />
+ </ErrorBoundary>
+ </Route>
+ ));
+
+ links.push(
+ <NavButton key={url} href={url} name={name} />
+ );
+ });
+
+ panelRouterEl.push(
+ <Route key={base} path={base}>
+ <Redirect to={firstRoute} />
+ </Route>
+ );
+
+ sidebarEl.push(
+ <React.Fragment key={name}>
+ <Link href={firstRoute}>
+ <a>
+ <h2>{name}</h2>
+ </a>
+ </Link>
+ <nav>
+ {links}
+ </nav>
+ </React.Fragment>
+ );
+ });
+
+ return { sidebar, panelRouter };
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/panel.js b/web/source/settings-panel/lib/panel.js
@@ -0,0 +1,134 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const ReactDom = require("react-dom");
+
+const oauthLib = require("./oauth");
+
+module.exports = function createPanel(clientName, scope, Component) {
+ ReactDom.render(<Panel/>, document.getElementById("root"));
+
+ function Panel() {
+ const [oauth, setOauth] = React.useState();
+ const [hasAuth, setAuth] = React.useState(false);
+ const [oauthState, setOauthState] = React.useState(localStorage.getItem("oauth"));
+
+ React.useEffect(() => {
+ let state = localStorage.getItem("oauth");
+ if (state != undefined) {
+ state = JSON.parse(state);
+ let restoredOauth = oauthLib(state.config, state);
+ Promise.try(() => {
+ return restoredOauth.callback();
+ }).then(() => {
+ setAuth(true);
+ });
+ setOauth(restoredOauth);
+ }
+ }, [setAuth, setOauth]);
+
+ if (!hasAuth && oauth && oauth.isAuthorized()) {
+ setAuth(true);
+ }
+
+ if (oauth && oauth.isAuthorized()) {
+ return <Component oauth={oauth} />;
+ } else if (oauthState != undefined) {
+ return "processing oauth...";
+ } else {
+ return <Auth setOauth={setOauth} />;
+ }
+ }
+
+ function Auth({setOauth}) {
+ const [ instance, setInstance ] = React.useState("");
+
+ React.useEffect(() => {
+ let isStillMounted = true;
+ // check if current domain runs an instance
+ let thisUrl = new URL(window.location.origin);
+ thisUrl.pathname = "/api/v1/instance";
+ Promise.try(() => {
+ return fetch(thisUrl.href);
+ }).then((res) => {
+ if (res.status == 200) {
+ return res.json();
+ }
+ }).then((json) => {
+ if (json && json.uri && isStillMounted) {
+ setInstance(json.uri);
+ }
+ }).catch((e) => {
+ console.log("error checking instance response:", e);
+ });
+
+ return () => {
+ // cleanup function
+ isStillMounted = false;
+ };
+ }, []);
+
+ function doAuth() {
+ return Promise.try(() => {
+ return new URL(instance);
+ }).catch(TypeError, () => {
+ return new URL(`https://${instance}`);
+ }).then((parsedURL) => {
+ let url = parsedURL.toString();
+ let oauth = oauthLib({
+ instance: url,
+ client_name: clientName,
+ scope: scope,
+ website: window.location.href
+ });
+ setOauth(oauth);
+ setInstance(url);
+ return oauth.register().then(() => {
+ return oauth;
+ });
+ }).then((oauth) => {
+ return oauth.authorize();
+ }).catch((e) => {
+ console.log("error authenticating:", e);
+ });
+ }
+
+ function updateInstance(e) {
+ if (e.key == "Enter") {
+ doAuth();
+ } else {
+ setInstance(e.target.value);
+ }
+ }
+
+ return (
+ <section className="login">
+ <h1>OAUTH Login:</h1>
+ <form onSubmit={(e) => e.preventDefault()}>
+ <label htmlFor="instance">Instance: </label>
+ <input value={instance} onChange={updateInstance} id="instance"/>
+ <button onClick={doAuth}>Authenticate</button>
+ </form>
+ </section>
+ );
+ }
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/lib/submit.js b/web/source/settings-panel/lib/submit.js
@@ -0,0 +1,48 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+
+module.exports = function submit(func, {
+ setStatus, setError,
+ startStatus="PATCHing", successStatus="Saved!",
+ onSuccess,
+ onError
+}) {
+ return function() {
+ setStatus(startStatus);
+ setError("");
+ return Promise.try(() => {
+ return func();
+ }).then(() => {
+ setStatus(successStatus);
+ if (onSuccess != undefined) {
+ return onSuccess();
+ }
+ }).catch((e) => {
+ setError(e.message);
+ setStatus("");
+ console.error(e);
+ if (onError != undefined) {
+ onError(e);
+ }
+ });
+ };
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/redux/index.js b/web/source/settings-panel/redux/index.js
@@ -0,0 +1,48 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const { createStore, combineReducers, applyMiddleware } = require("redux");
+const { persistStore, persistReducer } = require("redux-persist");
+const thunk = require("redux-thunk").default;
+const { composeWithDevTools } = require("redux-devtools-extension");
+
+const persistConfig = {
+ key: "gotosocial-settings",
+ storage: require("redux-persist/lib/storage").default,
+ stateReconciler: require("redux-persist/lib/stateReconciler/autoMergeLevel2").default,
+ whitelist: ["oauth"],
+ blacklist: ["temporary"]
+};
+
+const combinedReducers = combineReducers({
+ oauth: require("./reducers/oauth").reducer,
+ instances: require("./reducers/instances").reducer,
+ temporary: require("./reducers/temporary").reducer,
+ user: require("./reducers/user").reducer,
+ admin: require("./reducers/admin").reducer,
+});
+
+const persistedReducer = persistReducer(persistConfig, combinedReducers);
+const composedEnhancer = composeWithDevTools(applyMiddleware(thunk));
+
+const store = createStore(persistedReducer, composedEnhancer);
+const persistor = persistStore(store);
+
+module.exports = { store, persistor };
+\ No newline at end of file
diff --git a/web/source/settings-panel/redux/reducers/admin.js b/web/source/settings-panel/redux/reducers/admin.js
@@ -0,0 +1,131 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const { createSlice } = require("@reduxjs/toolkit");
+const defaultValue = require("default-value");
+
+function sortBlocks(blocks) {
+ return blocks.sort((a, b) => { // alphabetical sort
+ return a.domain.localeCompare(b.domain);
+ });
+}
+
+function emptyBlock() {
+ return {
+ public_comment: "",
+ private_comment: "",
+ obfuscate: false
+ };
+}
+
+function emptyEmojiForm() {
+ return {
+ shortcode: ""
+ };
+}
+
+module.exports = createSlice({
+ name: "admin",
+ initialState: {
+ loadedBlockedInstances: false,
+ blockedInstances: undefined,
+ bulkBlock: {
+ list: "",
+ exportType: "plain",
+ ...emptyBlock()
+ },
+ newInstanceBlocks: {},
+ emoji: {},
+ newEmoji: emptyEmojiForm()
+ },
+ reducers: {
+ setBlockedInstances: (state, { payload }) => {
+ state.blockedInstances = {};
+ sortBlocks(payload).forEach((entry) => {
+ state.blockedInstances[entry.domain] = entry;
+ });
+ state.loadedBlockedInstances = true;
+ },
+
+ newDomainBlock: (state, { payload: [domain, data] }) => {
+ if (data == undefined) {
+ data = {
+ new: true,
+ domain,
+ ...emptyBlock()
+ };
+ }
+ state.newInstanceBlocks[domain] = data;
+ },
+
+ setDomainBlock: (state, { payload: [domain, data = {}] }) => {
+ state.blockedInstances[domain] = data;
+ },
+
+ removeDomainBlock: (state, {payload: domain}) => {
+ delete state.blockedInstances[domain];
+ },
+
+ updateDomainBlockVal: (state, { payload: [domain, key, val] }) => {
+ state.newInstanceBlocks[domain][key] = val;
+ },
+
+ updateBulkBlockVal: (state, { payload: [key, val] }) => {
+ state.bulkBlock[key] = val;
+ },
+
+ resetBulkBlockVal: (state, { _payload }) => {
+ state.bulkBlock = {
+ list: "",
+ exportType: "plain",
+ ...emptyBlock()
+ };
+ },
+
+ exportToField: (state, { _payload }) => {
+ state.bulkBlock.list = Object.values(state.blockedInstances).map((entry) => {
+ return entry.domain;
+ }).join("\n");
+ },
+
+ setEmoji: (state, {payload}) => {
+ state.emoji = {};
+ payload.forEach((emoji) => {
+ if (emoji.category == undefined) {
+ emoji.category = "Unsorted";
+ }
+ state.emoji[emoji.category] = defaultValue(state.emoji[emoji.category], []);
+ state.emoji[emoji.category].push(emoji);
+ });
+ },
+
+ updateNewEmojiVal: (state, { payload: [key, val] }) => {
+ state.newEmoji[key] = val;
+ },
+
+ addEmoji: (state, {payload: emoji}) => {
+ if (emoji.category == undefined) {
+ emoji.category = "Unsorted";
+ }
+ state.emoji[emoji.category] = defaultValue(state.emoji[emoji.category], []);
+ state.emoji[emoji.category].push(emoji);
+ },
+ }
+});
+\ No newline at end of file
diff --git a/web/source/settings-panel/redux/reducers/instances.js b/web/source/settings-panel/redux/reducers/instances.js
@@ -0,0 +1,42 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const {createSlice} = require("@reduxjs/toolkit");
+const d = require("dotty");
+
+module.exports = createSlice({
+ name: "instances",
+ initialState: {
+ info: {},
+ },
+ reducers: {
+ setNamedInstanceInfo: (state, {payload}) => {
+ let [key, info] = payload;
+ state.info[key] = info;
+ },
+ setInstanceInfo: (state, {payload}) => {
+ state.current = payload;
+ state.adminSettings = payload;
+ },
+ setAdminSettingsVal: (state, {payload: [key, val]}) => {
+ d.put(state.adminSettings, key, val);
+ }
+ }
+});
+\ No newline at end of file
diff --git a/web/source/settings-panel/redux/reducers/oauth.js b/web/source/settings-panel/redux/reducers/oauth.js
@@ -0,0 +1,52 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const {createSlice} = require("@reduxjs/toolkit");
+
+module.exports = createSlice({
+ name: "oauth",
+ initialState: {
+ loginState: 'none',
+ },
+ reducers: {
+ setInstance: (state, {payload}) => {
+ state.instance = payload;
+ },
+ setRegistration: (state, {payload}) => {
+ state.registration = payload;
+ },
+ setLoginState: (state, {payload}) => {
+ state.loginState = payload;
+ },
+ login: (state, {payload}) => {
+ state.token = `${payload.token_type} ${payload.access_token}`;
+ state.loginState = "login";
+ },
+ remove: (state, {_payload}) => {
+ delete state.token;
+ delete state.registration;
+ delete state.isAdmin;
+ state.loginState = "none";
+ },
+ setAdmin: (state, {payload}) => {
+ state.isAdmin = payload;
+ }
+ }
+});
+\ No newline at end of file
diff --git a/web/source/settings-panel/redux/reducers/temporary.js b/web/source/settings-panel/redux/reducers/temporary.js
@@ -0,0 +1,32 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const {createSlice} = require("@reduxjs/toolkit");
+
+module.exports = createSlice({
+ name: "temporary",
+ initialState: {
+ },
+ reducers: {
+ setStatus: function(state, {payload}) {
+ state.status = payload;
+ }
+ }
+});
+\ No newline at end of file
diff --git a/web/source/settings-panel/redux/reducers/user.js b/web/source/settings-panel/redux/reducers/user.js
@@ -0,0 +1,51 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const { createSlice } = require("@reduxjs/toolkit");
+const d = require("dotty");
+const defaultValue = require("default-value");
+
+module.exports = createSlice({
+ name: "user",
+ initialState: {
+ profile: {},
+ settings: {}
+ },
+ reducers: {
+ setAccount: (state, { payload }) => {
+ payload.source = defaultValue(payload.source, {});
+ payload.source.language = defaultValue(payload.source.language.toUpperCase(), "EN");
+ payload.source.status_format = defaultValue(payload.source.status_format, "plain");
+ payload.source.sensitive = defaultValue(payload.source.sensitive, false);
+
+ state.profile = payload;
+ // /user/settings only needs a copy of the 'source' obj
+ state.settings = {
+ source: payload.source
+ };
+ },
+ setProfileVal: (state, { payload: [key, val] }) => {
+ d.put(state.profile, key, val);
+ },
+ setSettingsVal: (state, { payload: [key, val] }) => {
+ d.put(state.settings, key, val);
+ }
+ }
+});
+\ No newline at end of file
diff --git a/web/source/settings-panel/style.css b/web/source/settings-panel/style.css
@@ -0,0 +1,498 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+body {
+ grid-template-rows: auto 1fr;
+}
+
+.content {
+ grid-column: 1 / span 3; /* stretch entire width, to fit panel + sidebar nav */
+}
+
+section {
+ grid-column: 2;
+}
+
+#root {
+ display: grid;
+ grid-template-columns: 1fr 90ch 1fr;
+ width: 100vw;
+ max-width: 100vw;
+ box-sizing: border-box;
+
+ section.with-sidebar {
+ border-left: none;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+
+ & > div {
+ border-left: 0.2rem solid $border-accent;
+ padding-left: 0.4rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ margin: 2rem 0;
+
+ h2 {
+ margin: 0;
+ margin-bottom: 0.5rem;
+ }
+
+ &:only-child {
+ border-left: none;
+ }
+
+ &:first-child {
+ margin-top: 0;
+ }
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ .sidebar {
+ align-self: start;
+ justify-self: end;
+ background: $settings-nav-bg;
+ border: $boxshadow-border;
+ box-shadow: $boxshadow;
+ border-radius: $br;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ display: flex;
+ flex-direction: column;
+ min-width: 12rem;
+
+ a {
+ text-decoration: none;
+ }
+
+ a:first-child h2 {
+ border-top-left-radius: $br;
+ }
+
+ h2 {
+ margin: 0;
+ padding: 0.5rem;
+ font-size: 0.9rem;
+ font-weight: bold;
+ text-transform: uppercase;
+ color: $settings-nav-header-fg;
+ background: $settings-nav-header-bg;
+ }
+
+ nav {
+ display: flex;
+ flex-direction: column;
+
+ a {
+ padding: 1rem;
+ text-decoration: none;
+ transition: 0.1s;
+ color: $fg;
+
+ &:hover {
+ color: $settings-nav-fg-hover;
+ background: $settings-nav-bg-hover;
+ }
+
+ &.active {
+ color: $settings-nav-fg-active;
+ background: $settings-nav-bg-active;
+ font-weight: bold;
+ text-decoration: underline;
+ }
+
+ /* reserve space for bold version of the element, so .active doesn't
+ change container size */
+ &::after {
+ font-weight: bold;
+ text-decoration: underline;
+ display: block;
+ content: attr(data-content);
+ height: 1px;
+ color: transparent;
+ overflow: hidden;
+ visibility: hidden;
+ }
+ }
+ }
+
+
+ nav:last-child a:last-child {
+ border-bottom-left-radius: $br;
+ border-bottom: none;
+ }
+ }
+}
+
+.capitalize {
+ text-transform: capitalize;
+}
+
+section {
+ margin-bottom: 1rem;
+}
+
+input, select, textarea {
+ box-sizing: border-box;
+}
+
+.error {
+ color: $error-fg;
+ background: $error-bg;
+ border: 0.02rem solid $error-fg;
+ border-radius: $br;
+ font-weight: bold;
+ padding: 0.5rem;
+ white-space: pre-wrap;
+
+ a {
+ color: $error-link;
+ }
+
+ pre {
+ background: $bg;
+ color: $fg;
+ padding: 1rem;
+ overflow: auto;
+ margin: 0;
+ }
+}
+
+.hidden {
+ display: none;
+}
+
+.messagebutton, .messagebutton > div {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+
+ div.padded {
+ margin-left: 1rem;
+ }
+
+ button, .button {
+ white-space: nowrap;
+ margin-right: 1rem;
+ }
+}
+
+.messagebutton > div {
+ button, .button {
+ margin-top: 1rem;
+ }
+}
+
+.notImplemented {
+ border: 2px solid rgb(70, 79, 88);
+ background: repeating-linear-gradient(
+ -45deg,
+ #525c66,
+ #525c66 10px,
+ rgb(70, 79, 88) 10px,
+ rgb(70, 79, 88) 20px
+ ) !important;
+}
+
+section.with-sidebar > div {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+
+ input, textarea {
+ width: 100%;
+ line-height: 1.5rem;
+ }
+
+ input[type=checkbox] {
+ justify-self: start;
+ width: initial;
+ }
+
+ input:read-only {
+ border: none;
+ }
+
+ input:invalid {
+ border-color: red;
+ }
+
+ textarea {
+ width: 100%;
+ }
+
+ h1 {
+ margin-bottom: 0.5rem;
+ }
+
+ .moreinfolink {
+ font-size: 0.9em;
+ }
+
+ .labelinput .border {
+ border-radius: 0.2rem;
+ border: 0.15rem solid $border_accent;
+ padding: 0.3rem;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .file-input.button {
+ display: inline-block;
+ font-size: 1rem;
+ font-weight: normal;
+ padding: 0.3rem 0.3rem;
+ align-self: flex-start;
+ margin-right: 0.2rem;
+ }
+
+ .labelinput, .labelselect {
+ display: flex;
+ flex-direction: column;
+ gap: 0.4rem;
+ }
+
+ .labelcheckbox {
+ display: flex;
+ gap: 0.4rem;
+ }
+
+ .titlesave {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.4rem;
+ }
+}
+
+.file-upload > div {
+ display: flex;
+ gap: 1rem;
+
+ img {
+ height: 8rem;
+ border: 0.2rem solid $border-accent;
+ }
+
+ img.avatar {
+ width: 8rem;
+ }
+
+ img.header {
+ width: 24rem;
+ }
+}
+
+.user-profile {
+ .overview {
+ display: grid;
+ grid-template-columns: 70% 30%;
+
+ .basic {
+ margin-top: -4.5rem;
+
+ .avatar {
+ height: 5rem;
+ width: 5rem;
+ }
+
+ .displayname {
+ font-size: 1.3rem;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin-top: 0.7rem;
+ }
+ }
+
+ .files {
+ width: 100%;
+ margin: 1rem;
+ margin-right: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+
+ div.form-field {
+ width: 100%;
+ display: flex;
+
+ span {
+ flex: 1 1 auto;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 0.3rem 0;
+ }
+ }
+
+ h3 {
+ margin-top: 0;
+ margin-bottom: 0.5rem;
+ }
+
+ div:first-child {
+ margin-bottom: 1rem;
+ }
+
+ span {
+ font-style: italic;
+ }
+ }
+ }
+}
+
+.form-field label {
+ font-weight: bold;
+}
+
+.list {
+ display: flex;
+ flex-direction: column;
+ margin-top: 0.5rem;
+ max-height: 40rem;
+ overflow: auto;
+
+ .entry {
+ display: flex;
+ flex-wrap: wrap;
+ background: $settings-entry-bg;
+
+ &:hover {
+ background: $settings-entry-hover-bg;
+ }
+ }
+}
+
+.instance-list {
+ .filter {
+ display: flex;
+ gap: 0.5rem;
+
+ input {
+ width: auto;
+ flex: 1 1 auto;
+ }
+ }
+
+ .entry {
+ padding: 0.3rem;
+ margin: 0.2rem 0;
+
+ #domain {
+ flex: 1 1 auto;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+ }
+}
+
+.bulk h2 {
+ display: flex;
+ justify-content: space-between;
+}
+
+.emoji-list {
+ background: $settings-entry-bg;
+
+ .entry {
+ padding: 0.5rem;
+ flex-direction: column;
+
+ .emoji-group {
+ display: flex;
+
+ a {
+ border-radius: $br;
+ padding: 0.4rem;
+ line-height: 0;
+
+ img {
+ height: 2rem;
+ width: 2rem;
+ object-fit: contain;
+ vertical-align: middle;
+ }
+
+ &:hover {
+ background: $settings-entry-hover-bg;
+ }
+ }
+ }
+
+ &:hover {
+ background: inherit;
+ }
+ }
+}
+
+.toot {
+ padding-top: 0.5rem;
+ .contentgrid {
+ padding: 0 0.5rem;
+ }
+}
+
+@media screen and (max-width: 100ch) {
+ #root {
+ padding: 1rem;
+ grid-template-columns: 100%;
+ grid-template-rows: auto auto;
+
+ .sidebar {
+ justify-self: auto;
+ margin-bottom: 2rem;
+ }
+
+ .sidebar, section.with-sidebar {
+ border-top-left-radius: $br;
+ border-top-right-radius: $br;
+ border-bottom-left-radius: $br;
+ border-bottom-right-radius: $br;
+ }
+
+ .sidebar a:first-child h2 {
+ border-top-right-radius: $br;
+ }
+ }
+
+ section {
+ grid-column: 1;
+ }
+
+ .user-profile .overview {
+ grid-template-columns: 100%;
+ grid-template-rows: auto auto;
+
+ .files {
+ margin: 0;
+ margin-top: 1rem;
+ }
+ }
+
+ main section {
+ padding: 0.75rem;
+ }
+
+ .instance-list .filter {
+ flex-direction: column;
+ }
+}
+\ No newline at end of file
diff --git a/web/source/settings-panel/user/profile.js b/web/source/settings-panel/user/profile.js
@@ -0,0 +1,113 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+
+const Submit = require("../components/submit");
+
+const api = require("../lib/api");
+const user = require("../redux/reducers/user").actions;
+const submit = require("../lib/submit");
+
+const { formFields } = require("../components/form-fields");
+
+const {
+ TextInput,
+ TextArea,
+ Checkbox,
+ File
+} = formFields(user.setProfileVal, (state) => state.user.profile);
+
+module.exports = function UserProfile() {
+ const dispatch = Redux.useDispatch();
+ const account = Redux.useSelector(state => state.user.profile);
+ const instance = Redux.useSelector(state => state.instances.current);
+
+ const allowCustomCSS = instance.configuration.accounts.allow_custom_css;
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ const saveProfile = submit(
+ () => dispatch(api.user.updateProfile()),
+ {setStatus, setError}
+ );
+
+ return (
+ <div className="user-profile">
+ <h1>Profile</h1>
+ <div className="overview">
+ <div className="profile">
+ <div className="headerimage">
+ <img className="headerpreview" src={account.header} alt={account.header ? `header image for ${account.username}` : "None set"} />
+ </div>
+ <div className="basic">
+ <div id="profile-basic-filler2"></div>
+ <span className="avatar"><img className="avatarpreview" src={account.avatar} alt={account.avatar ? `avatar image for ${account.username}` : "None set"} /></span>
+ <div className="displayname">{account.display_name.trim().length > 0 ? account.display_name : account.username}</div>
+ <div className="username"><span>@{account.username}</span></div>
+ </div>
+ </div>
+ <div className="files">
+ <div>
+ <h3>Header</h3>
+ <File
+ id="header"
+ fileType="image/*"
+ />
+ </div>
+ <div>
+ <h3>Avatar</h3>
+ <File
+ id="avatar"
+ fileType="image/*"
+ />
+ </div>
+ </div>
+ </div>
+ <TextInput
+ id="display_name"
+ name="Name"
+ placeHolder="A GoToSocial user"
+ />
+ <TextArea
+ id="source.note"
+ name="Bio"
+ placeHolder="Just trying out GoToSocial, my pronouns are they/them and I like sloths."
+ />
+ <Checkbox
+ id="locked"
+ name="Manually approve follow requests? "
+ />
+ { !allowCustomCSS ? null :
+ <TextArea
+ id="custom_css"
+ name="Custom CSS"
+ className="monospace"
+ >
+ <a href="https://docs.gotosocial.org/en/latest/user_guide/custom_css" target="_blank" className="moreinfolink" rel="noreferrer">Learn more about custom profile CSS (opens in a new tab)</a>
+ </TextArea>
+ }
+ <Submit onClick={saveProfile} label="Save profile info" errorMsg={errorMsg} statusMsg={statusMsg} />
+ </div>
+ );
+};
+\ No newline at end of file
diff --git a/web/source/settings-panel/user/settings.js b/web/source/settings-panel/user/settings.js
@@ -0,0 +1,140 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+"use strict";
+
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+
+const api = require("../lib/api");
+const user = require("../redux/reducers/user").actions;
+const submit = require("../lib/submit");
+
+const Languages = require("../components/languages");
+const Submit = require("../components/submit");
+
+const {
+ Checkbox,
+ Select,
+} = require("../components/form-fields").formFields(user.setSettingsVal, (state) => state.user.settings);
+
+module.exports = function UserSettings() {
+ const dispatch = Redux.useDispatch();
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ const updateSettings = submit(
+ () => dispatch(api.user.updateSettings()),
+ {setStatus, setError}
+ );
+
+ return (
+ <>
+ <div className="user-settings">
+ <h1>Post settings</h1>
+ <Select id="source.language" name="Default post language" options={
+ <Languages/>
+ }>
+ </Select>
+ <Select id="source.privacy" name="Default post privacy" options={
+ <>
+ <option value="private">Private / followers-only</option>
+ <option value="unlisted">Unlisted</option>
+ <option value="public">Public</option>
+ </>
+ }>
+ <a href="https://docs.gotosocial.org/en/latest/user_guide/posts/#privacy-settings" target="_blank" className="moreinfolink" rel="noreferrer">Learn more about post privacy settings (opens in a new tab)</a>
+ </Select>
+ <Select id="source.status_format" name="Default post format" options={
+ <>
+ <option value="plain">Plain (default)</option>
+ <option value="markdown">Markdown</option>
+ </>
+ }>
+ <a href="https://docs.gotosocial.org/en/latest/user_guide/posts/#input-types" target="_blank" className="moreinfolink" rel="noreferrer">Learn more about post format settings (opens in a new tab)</a>
+ </Select>
+ <Checkbox
+ id="source.sensitive"
+ name="Mark my posts as sensitive by default"
+ />
+
+ <Submit onClick={updateSettings} label="Save post settings" errorMsg={errorMsg} statusMsg={statusMsg}/>
+ </div>
+ <div>
+ <PasswordChange/>
+ </div>
+ </>
+ );
+};
+
+function PasswordChange() {
+ const dispatch = Redux.useDispatch();
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ const [oldPassword, setOldPassword] = React.useState("");
+ const [newPassword, setNewPassword] = React.useState("");
+ const [newPasswordConfirm, setNewPasswordConfirm] = React.useState("");
+
+ function changePassword() {
+ if (newPassword !== newPasswordConfirm) {
+ setError("New password and confirm new password did not match!");
+ return;
+ }
+
+ setStatus("PATCHing");
+ setError("");
+ return Promise.try(() => {
+ let data = {
+ old_password: oldPassword,
+ new_password: newPassword
+ };
+ return dispatch(api.apiCall("POST", "/api/v1/user/password_change", data, "form"));
+ }).then(() => {
+ setStatus("Saved!");
+ setOldPassword("");
+ setNewPassword("");
+ setNewPasswordConfirm("");
+ }).catch((e) => {
+ setError(e.message);
+ setStatus("");
+ });
+ }
+
+ return (
+ <>
+ <h1>Change password</h1>
+ <div className="labelinput">
+ <label htmlFor="password">Current password</label>
+ <input name="password" id="password" type="password" autoComplete="current-password" value={oldPassword} onChange={(e) => setOldPassword(e.target.value)} />
+ </div>
+ <div className="labelinput">
+ <label htmlFor="new-password">New password</label>
+ <input name="new-password" id="new-password" type="password" autoComplete="new-password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} />
+ </div>
+ <div className="labelinput">
+ <label htmlFor="confirm-new-password">Confirm new password</label>
+ <input name="confirm-new-password" id="confirm-new-password" type="password" autoComplete="new-password" value={newPasswordConfirm} onChange={(e) => setNewPasswordConfirm(e.target.value)} />
+ </div>
+ <Submit onClick={changePassword} label="Save new password" errorMsg={errorMsg} statusMsg={statusMsg}/>
+ </>
+ );
+}
+\ No newline at end of file
diff --git a/web/source/yarn.lock b/web/source/yarn.lock
@@ -24,38 +24,38 @@
dependencies:
"@babel/highlight" "^7.18.6"
-"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8":
- version "7.18.8"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
- integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==
+"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9"
+ integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==
"@babel/core@^7.12.13":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.10.tgz#39ad504991d77f1f3da91be0b8b949a5bc466fb8"
- integrity sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b"
+ integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==
dependencies:
"@ampproject/remapping" "^2.1.0"
"@babel/code-frame" "^7.18.6"
- "@babel/generator" "^7.18.10"
- "@babel/helper-compilation-targets" "^7.18.9"
- "@babel/helper-module-transforms" "^7.18.9"
- "@babel/helpers" "^7.18.9"
- "@babel/parser" "^7.18.10"
+ "@babel/generator" "^7.19.0"
+ "@babel/helper-compilation-targets" "^7.19.1"
+ "@babel/helper-module-transforms" "^7.19.0"
+ "@babel/helpers" "^7.19.0"
+ "@babel/parser" "^7.19.1"
"@babel/template" "^7.18.10"
- "@babel/traverse" "^7.18.10"
- "@babel/types" "^7.18.10"
+ "@babel/traverse" "^7.19.1"
+ "@babel/types" "^7.19.0"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
json5 "^2.2.1"
semver "^6.3.0"
-"@babel/generator@^7.18.10":
- version "7.18.12"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.12.tgz#fa58daa303757bd6f5e4bbca91b342040463d9f4"
- integrity sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==
+"@babel/generator@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a"
+ integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==
dependencies:
- "@babel/types" "^7.18.10"
+ "@babel/types" "^7.19.0"
"@jridgewell/gen-mapping" "^0.3.2"
jsesc "^2.5.1"
@@ -74,41 +74,41 @@
"@babel/helper-explode-assignable-expression" "^7.18.6"
"@babel/types" "^7.18.9"
-"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf"
- integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==
+"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c"
+ integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==
dependencies:
- "@babel/compat-data" "^7.18.8"
+ "@babel/compat-data" "^7.19.1"
"@babel/helper-validator-option" "^7.18.6"
- browserslist "^4.20.2"
+ browserslist "^4.21.3"
semver "^6.3.0"
"@babel/helper-create-class-features-plugin@^7.18.6":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz#d802ee16a64a9e824fcbf0a2ffc92f19d58550ce"
- integrity sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b"
+ integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
"@babel/helper-member-expression-to-functions" "^7.18.9"
"@babel/helper-optimise-call-expression" "^7.18.6"
"@babel/helper-replace-supers" "^7.18.9"
"@babel/helper-split-export-declaration" "^7.18.6"
-"@babel/helper-create-regexp-features-plugin@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz#3e35f4e04acbbf25f1b3534a657610a000543d3c"
- integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==
+"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b"
+ integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
regexpu-core "^5.1.0"
-"@babel/helper-define-polyfill-provider@^0.3.2":
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz#bd10d0aca18e8ce012755395b05a79f45eca5073"
- integrity sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==
+"@babel/helper-define-polyfill-provider@^0.3.3":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a"
+ integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==
dependencies:
"@babel/helper-compilation-targets" "^7.17.7"
"@babel/helper-plugin-utils" "^7.16.7"
@@ -129,13 +129,13 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-function-name@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0"
- integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==
+"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c"
+ integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==
dependencies:
- "@babel/template" "^7.18.6"
- "@babel/types" "^7.18.9"
+ "@babel/template" "^7.18.10"
+ "@babel/types" "^7.19.0"
"@babel/helper-hoist-variables@^7.18.6":
version "7.18.6"
@@ -158,19 +158,19 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712"
- integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==
+"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30"
+ integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==
dependencies:
"@babel/helper-environment-visitor" "^7.18.9"
"@babel/helper-module-imports" "^7.18.6"
"@babel/helper-simple-access" "^7.18.6"
"@babel/helper-split-export-declaration" "^7.18.6"
"@babel/helper-validator-identifier" "^7.18.6"
- "@babel/template" "^7.18.6"
- "@babel/traverse" "^7.18.9"
- "@babel/types" "^7.18.9"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
"@babel/helper-optimise-call-expression@^7.18.6":
version "7.18.6"
@@ -179,10 +179,10 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f"
- integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf"
+ integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==
"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9":
version "7.18.9"
@@ -195,15 +195,15 @@
"@babel/types" "^7.18.9"
"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz#1092e002feca980fbbb0bd4d51b74a65c6a500e6"
- integrity sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78"
+ integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==
dependencies:
"@babel/helper-environment-visitor" "^7.18.9"
"@babel/helper-member-expression-to-functions" "^7.18.9"
"@babel/helper-optimise-call-expression" "^7.18.6"
- "@babel/traverse" "^7.18.9"
- "@babel/types" "^7.18.9"
+ "@babel/traverse" "^7.19.1"
+ "@babel/types" "^7.19.0"
"@babel/helper-simple-access@^7.18.6":
version "7.18.6"
@@ -232,9 +232,9 @@
integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==
"@babel/helper-validator-identifier@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
- integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
+ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
"@babel/helper-validator-option@^7.18.6":
version "7.18.6"
@@ -242,23 +242,23 @@
integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
"@babel/helper-wrap-function@^7.18.9":
- version "7.18.11"
- resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz#bff23ace436e3f6aefb61f85ffae2291c80ed1fb"
- integrity sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1"
+ integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==
dependencies:
- "@babel/helper-function-name" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
"@babel/template" "^7.18.10"
- "@babel/traverse" "^7.18.11"
- "@babel/types" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
-"@babel/helpers@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9"
- integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==
+"@babel/helpers@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18"
+ integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==
dependencies:
- "@babel/template" "^7.18.6"
- "@babel/traverse" "^7.18.9"
- "@babel/types" "^7.18.9"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6":
version "7.18.6"
@@ -269,10 +269,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.18.10", "@babel/parser@^7.18.11":
- version "7.18.11"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.11.tgz#68bb07ab3d380affa9a3f96728df07969645d2d9"
- integrity sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==
+"@babel/parser@^7.18.10", "@babel/parser@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c"
+ integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
version "7.18.6"
@@ -290,13 +290,13 @@
"@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
"@babel/plugin-proposal-optional-chaining" "^7.18.9"
-"@babel/plugin-proposal-async-generator-functions@^7.18.10":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz#85ea478c98b0095c3e4102bff3b67d306ed24952"
- integrity sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==
+"@babel/plugin-proposal-async-generator-functions@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7"
+ integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q==
dependencies:
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/helper-remap-async-to-generator" "^7.18.9"
"@babel/plugin-syntax-async-generators" "^7.8.4"
@@ -561,16 +561,17 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.9"
-"@babel/plugin-transform-classes@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz#90818efc5b9746879b869d5ce83eb2aa48bbc3da"
- integrity sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==
+"@babel/plugin-transform-classes@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20"
+ integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
+ "@babel/helper-compilation-targets" "^7.19.0"
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
"@babel/helper-optimise-call-expression" "^7.18.6"
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/helper-replace-supers" "^7.18.9"
"@babel/helper-split-export-declaration" "^7.18.6"
globals "^11.1.0"
@@ -582,10 +583,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.9"
-"@babel/plugin-transform-destructuring@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz#68906549c021cb231bee1db21d3b5b095f8ee292"
- integrity sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==
+"@babel/plugin-transform-destructuring@^7.18.13":
+ version "7.18.13"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5"
+ integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==
dependencies:
"@babel/helper-plugin-utils" "^7.18.9"
@@ -661,14 +662,14 @@
"@babel/helper-simple-access" "^7.18.6"
babel-plugin-dynamic-import-node "^2.3.3"
-"@babel/plugin-transform-modules-systemjs@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz#545df284a7ac6a05125e3e405e536c5853099a06"
- integrity sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==
+"@babel/plugin-transform-modules-systemjs@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f"
+ integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==
dependencies:
"@babel/helper-hoist-variables" "^7.18.6"
- "@babel/helper-module-transforms" "^7.18.9"
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-module-transforms" "^7.19.0"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/helper-validator-identifier" "^7.18.6"
babel-plugin-dynamic-import-node "^2.3.3"
@@ -680,13 +681,13 @@
"@babel/helper-module-transforms" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz#c89bfbc7cc6805d692f3a49bc5fc1b630007246d"
- integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==
+"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888"
+ integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==
dependencies:
- "@babel/helper-create-regexp-features-plugin" "^7.18.6"
- "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-create-regexp-features-plugin" "^7.19.0"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/plugin-transform-new-target@^7.18.6":
version "7.18.6"
@@ -732,15 +733,15 @@
"@babel/plugin-transform-react-jsx" "^7.18.6"
"@babel/plugin-transform-react-jsx@^7.18.6":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz#ea47b2c4197102c196cbd10db9b3bb20daa820f1"
- integrity sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9"
+ integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
"@babel/helper-module-imports" "^7.18.6"
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/plugin-syntax-jsx" "^7.18.6"
- "@babel/types" "^7.18.10"
+ "@babel/types" "^7.19.0"
"@babel/plugin-transform-react-pure-annotations@^7.18.6":
version "7.18.6"
@@ -772,12 +773,12 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-spread@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz#6ea7a6297740f381c540ac56caf75b05b74fb664"
- integrity sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==
+"@babel/plugin-transform-spread@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6"
+ integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
"@babel/plugin-transform-sticky-regex@^7.18.6":
@@ -817,17 +818,17 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/preset-env@^7.12.13":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.10.tgz#83b8dfe70d7eea1aae5a10635ab0a5fe60dfc0f4"
- integrity sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.1.tgz#9f04c916f9c0205a48ebe5cc1be7768eb1983f67"
+ integrity sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA==
dependencies:
- "@babel/compat-data" "^7.18.8"
- "@babel/helper-compilation-targets" "^7.18.9"
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/compat-data" "^7.19.1"
+ "@babel/helper-compilation-targets" "^7.19.1"
+ "@babel/helper-plugin-utils" "^7.19.0"
"@babel/helper-validator-option" "^7.18.6"
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6"
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9"
- "@babel/plugin-proposal-async-generator-functions" "^7.18.10"
+ "@babel/plugin-proposal-async-generator-functions" "^7.19.1"
"@babel/plugin-proposal-class-properties" "^7.18.6"
"@babel/plugin-proposal-class-static-block" "^7.18.6"
"@babel/plugin-proposal-dynamic-import" "^7.18.6"
@@ -861,9 +862,9 @@
"@babel/plugin-transform-async-to-generator" "^7.18.6"
"@babel/plugin-transform-block-scoped-functions" "^7.18.6"
"@babel/plugin-transform-block-scoping" "^7.18.9"
- "@babel/plugin-transform-classes" "^7.18.9"
+ "@babel/plugin-transform-classes" "^7.19.0"
"@babel/plugin-transform-computed-properties" "^7.18.9"
- "@babel/plugin-transform-destructuring" "^7.18.9"
+ "@babel/plugin-transform-destructuring" "^7.18.13"
"@babel/plugin-transform-dotall-regex" "^7.18.6"
"@babel/plugin-transform-duplicate-keys" "^7.18.9"
"@babel/plugin-transform-exponentiation-operator" "^7.18.6"
@@ -873,9 +874,9 @@
"@babel/plugin-transform-member-expression-literals" "^7.18.6"
"@babel/plugin-transform-modules-amd" "^7.18.6"
"@babel/plugin-transform-modules-commonjs" "^7.18.6"
- "@babel/plugin-transform-modules-systemjs" "^7.18.9"
+ "@babel/plugin-transform-modules-systemjs" "^7.19.0"
"@babel/plugin-transform-modules-umd" "^7.18.6"
- "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1"
"@babel/plugin-transform-new-target" "^7.18.6"
"@babel/plugin-transform-object-super" "^7.18.6"
"@babel/plugin-transform-parameters" "^7.18.8"
@@ -883,18 +884,18 @@
"@babel/plugin-transform-regenerator" "^7.18.6"
"@babel/plugin-transform-reserved-words" "^7.18.6"
"@babel/plugin-transform-shorthand-properties" "^7.18.6"
- "@babel/plugin-transform-spread" "^7.18.9"
+ "@babel/plugin-transform-spread" "^7.19.0"
"@babel/plugin-transform-sticky-regex" "^7.18.6"
"@babel/plugin-transform-template-literals" "^7.18.9"
"@babel/plugin-transform-typeof-symbol" "^7.18.9"
"@babel/plugin-transform-unicode-escapes" "^7.18.10"
"@babel/plugin-transform-unicode-regex" "^7.18.6"
"@babel/preset-modules" "^0.1.5"
- "@babel/types" "^7.18.10"
- babel-plugin-polyfill-corejs2 "^0.3.2"
- babel-plugin-polyfill-corejs3 "^0.5.3"
- babel-plugin-polyfill-regenerator "^0.4.0"
- core-js-compat "^3.22.1"
+ "@babel/types" "^7.19.0"
+ babel-plugin-polyfill-corejs2 "^0.3.3"
+ babel-plugin-polyfill-corejs3 "^0.6.0"
+ babel-plugin-polyfill-regenerator "^0.4.1"
+ core-js-compat "^3.25.1"
semver "^6.3.0"
"@babel/preset-modules@^0.1.5":
@@ -920,14 +921,14 @@
"@babel/plugin-transform-react-jsx-development" "^7.18.6"
"@babel/plugin-transform-react-pure-annotations" "^7.18.6"
-"@babel/runtime@^7.8.4":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
- integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
+"@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
+ integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/template@^7.18.10", "@babel/template@^7.18.6":
+"@babel/template@^7.18.10":
version "7.18.10"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==
@@ -936,26 +937,26 @@
"@babel/parser" "^7.18.10"
"@babel/types" "^7.18.10"
-"@babel/traverse@^7.18.10", "@babel/traverse@^7.18.11", "@babel/traverse@^7.18.9":
- version "7.18.11"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.11.tgz#3d51f2afbd83ecf9912bcbb5c4d94e3d2ddaa16f"
- integrity sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==
+"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1":
+ version "7.19.1"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347"
+ integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==
dependencies:
"@babel/code-frame" "^7.18.6"
- "@babel/generator" "^7.18.10"
+ "@babel/generator" "^7.19.0"
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
"@babel/helper-hoist-variables" "^7.18.6"
"@babel/helper-split-export-declaration" "^7.18.6"
- "@babel/parser" "^7.18.11"
- "@babel/types" "^7.18.10"
+ "@babel/parser" "^7.19.1"
+ "@babel/types" "^7.19.0"
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.4.4":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.10.tgz#4908e81b6b339ca7c6b7a555a5fc29446f26dde6"
- integrity sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==
+"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600"
+ integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==
dependencies:
"@babel/helper-string-parser" "^7.18.10"
"@babel/helper-validator-identifier" "^7.18.6"
@@ -981,6 +982,23 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
+"@f0x52/budo-express@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@f0x52/budo-express/-/budo-express-1.1.0.tgz#dbda0eab9da0c186fbb12471d14a64331e474b57"
+ integrity sha512-BKZOCJW32fIGehD7n7uCBlm8j5BDYQIE/xDFW86QabnnEHir4Q4/jC/XWyXfrgTHI6RjyySUZGp/kBT+tCBzsA==
+ dependencies:
+ assure-array "^1.0.0"
+ bluebird "^3.7.2"
+ browserify "^16.5.0"
+ budo "^11.5.0"
+ chalk "^3.0.0"
+ default-value "^1.0.0"
+ entities "^2.0.0"
+ inject-lr-script "^2.2.0"
+ is-stream "^2.0.0"
+ stacked "^1.1.1"
+ validatem "^0.2.0"
+
"@f0x52/eslint-config-react@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@f0x52/eslint-config-react/-/eslint-config-react-1.1.0.tgz#734973a7627603b19e3cec2620658a25d405b110"
@@ -1012,9 +1030,9 @@
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@joepie91/eslint-config@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@joepie91/eslint-config/-/eslint-config-1.1.0.tgz#9397e6ce0a010cb57dcf8aef8754d3a5ce0ae36a"
- integrity sha512-XliasRSUfOz1/bAvTBaUlCjWDbceCW4y1DnvFfW7Yw9p2FbNRR0w8WoPdTxTCjKuoZ7/OQMeBxIe2y9Qy6rbYw==
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@joepie91/eslint-config/-/eslint-config-1.1.1.tgz#cb276dec6dd25b5777daefbef561850c9717180d"
+ integrity sha512-q8l83tdpL0YGC24ftlpeHgmQIIRmcpiVhwwEUFPcJ1YXWaee/JjoUs6e5tLKMTNNk+fvDKtq2YPSXkmLQU7h5Q==
"@jridgewell/gen-mapping@^0.1.0":
version "0.1.1"
@@ -1049,13 +1067,55 @@
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
"@jridgewell/trace-mapping@^0.3.9":
- version "0.3.14"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
- integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
+ version "0.3.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774"
+ integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==
dependencies:
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
+"@reduxjs/toolkit@^1.8.5":
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.5.tgz#c14bece03ee08be88467f22dc0ecf9cf875527cd"
+ integrity sha512-f4D5EXO7A7Xq35T0zRbWq5kJQyXzzscnHKmjnu2+37B3rwHU6mX9PYlbfXdnxcY6P/7zfmjhgan0Z+yuOfeBmA==
+ dependencies:
+ immer "^9.0.7"
+ redux "^4.1.2"
+ redux-thunk "^2.4.1"
+ reselect "^4.1.5"
+
+"@types/hoist-non-react-statics@^3.3.1":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
+"@types/prop-types@*":
+ version "15.7.5"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+ integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/react@*":
+ version "18.0.20"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.20.tgz#e4c36be3a55eb5b456ecf501bd4a00fd4fd0c9ab"
+ integrity sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
+"@types/use-sync-external-store@^0.0.3":
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
+ integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
+
"@validatem/allow-extra-properties@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/allow-extra-properties/-/allow-extra-properties-0.1.0.tgz#e8c434818d6fd74b8cb237cfaa4d548295de13c1"
@@ -1345,11 +1405,6 @@ acorn-walk@^7.0.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn@^5.2.1:
- version "5.7.4"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
- integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
-
acorn@^7.0.0, acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
@@ -1444,21 +1499,6 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
-arr-diff@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
- integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==
-
-arr-flatten@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
- integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
-
-arr-union@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
- integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==
-
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@@ -1485,11 +1525,6 @@ array-union@^2.1.0:
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
-array-unique@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
- integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==
-
array.prototype.flatmap@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f"
@@ -1523,21 +1558,11 @@ assert@^1.4.0:
object-assign "^4.1.1"
util "0.10.3"
-assign-symbols@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
- integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==
-
assure-array@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assure-array/-/assure-array-1.0.0.tgz#4f4ad16a87659d6200a4fb7103462033d216ec1f"
integrity sha512-igvOvGYidAcJKr6YQIHzLivUpAdqUfi7MN0QfrEnFtifQvuw6D0W4oInrIVgTaefJ+QBVWAj8ZYuUGNnwq6Ydw==
-ast-types@0.9.6:
- version "0.9.6"
- resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
- integrity sha512-qEdtR2UH78yyHX/AUNfXmJTlM48XoFZKBdwi1nzkI1mJL21cmbu0cvjxjpkXJ5NENMq42H+hNs8VLJcqXLerBQ==
-
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
@@ -1548,18 +1573,13 @@ async-limiter@~1.0.0:
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
-atob@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
- integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
-
autoprefixer@^10.4.8:
- version "10.4.8"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.8.tgz#92c7a0199e1cfb2ad5d9427bd585a3d75895b9e5"
- integrity sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==
+ version "10.4.11"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.11.tgz#835136aff1d9cd43640151e0d2dba00f8eac7c1c"
+ integrity sha512-5lHp6DgRodxlBLSkzHOTcufWFflH1ewfy2hvFQyjrblBFlP/0Yh4O/Wrg4ow8WRlN3AAUFFLAQwX8hTptzqVHg==
dependencies:
browserslist "^4.21.3"
- caniuse-lite "^1.0.30001373"
+ caniuse-lite "^1.0.30001399"
fraction.js "^4.2.0"
normalize-range "^0.1.2"
picocolors "^1.0.0"
@@ -1577,29 +1597,29 @@ babel-plugin-dynamic-import-node@^2.3.3:
dependencies:
object.assign "^4.1.0"
-babel-plugin-polyfill-corejs2@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz#e4c31d4c89b56f3cf85b92558954c66b54bd972d"
- integrity sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==
+babel-plugin-polyfill-corejs2@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122"
+ integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==
dependencies:
"@babel/compat-data" "^7.17.7"
- "@babel/helper-define-polyfill-provider" "^0.3.2"
+ "@babel/helper-define-polyfill-provider" "^0.3.3"
semver "^6.1.1"
-babel-plugin-polyfill-corejs3@^0.5.3:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz#d7e09c9a899079d71a8b670c6181af56ec19c5c7"
- integrity sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==
+babel-plugin-polyfill-corejs3@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a"
+ integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==
dependencies:
- "@babel/helper-define-polyfill-provider" "^0.3.2"
- core-js-compat "^3.21.0"
+ "@babel/helper-define-polyfill-provider" "^0.3.3"
+ core-js-compat "^3.25.1"
-babel-plugin-polyfill-regenerator@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz#8f51809b6d5883e07e71548d75966ff7635527fe"
- integrity sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==
+babel-plugin-polyfill-regenerator@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747"
+ integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==
dependencies:
- "@babel/helper-define-polyfill-provider" "^0.3.2"
+ "@babel/helper-define-polyfill-provider" "^0.3.3"
babelify@^10.0.0:
version "10.0.0"
@@ -1611,29 +1631,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-base62@0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/base62/-/base62-0.1.1.tgz#7b4174c2f94449753b11c2651c083da841a7b084"
- integrity sha512-QtExujIOq/F672OkHmDi3CdkphOA1kSQ38gv03Ro3cplYQk831dq9GM3Q1oXAxpR5HNJjGjjjT2pHtBGAJu1jw==
-
base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-base@^0.11.1:
- version "0.11.2"
- resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
- integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
- dependencies:
- cache-base "^1.0.1"
- class-utils "^0.3.5"
- component-emitter "^1.2.1"
- define-property "^1.0.0"
- isobject "^3.0.1"
- mixin-deep "^1.2.0"
- pascalcase "^0.1.1"
-
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -1703,23 +1705,7 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
-braces@^2.3.1:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
- integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
- dependencies:
- arr-flatten "^1.1.0"
- array-unique "^0.3.2"
- extend-shallow "^2.0.1"
- fill-range "^4.0.0"
- isobject "^3.0.1"
- repeat-element "^1.1.2"
- snapdragon "^0.8.1"
- snapdragon-node "^2.0.1"
- split-string "^3.0.2"
- to-regex "^3.0.1"
-
-braces@~3.0.2:
+braces@^3.0.2, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@@ -1822,7 +1808,7 @@ browserify-zlib@~0.2.0:
dependencies:
pako "~1.0.5"
-browserify@^16.2.3, browserify@^16.5.0:
+browserify@^16.5.0:
version "16.5.2"
resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.2.tgz#d926835e9280fa5fd57f5bc301f2ef24a972ddfe"
integrity sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g==
@@ -1937,40 +1923,23 @@ browserlist@^1.0.1:
dependencies:
chalk "^2.4.1"
-browserslist@^4.20.2, browserslist@^4.21.3:
- version "4.21.3"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a"
- integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==
+browserslist@^4.21.3:
+ version "4.21.4"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
+ integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
dependencies:
- caniuse-lite "^1.0.30001370"
- electron-to-chromium "^1.4.202"
+ caniuse-lite "^1.0.30001400"
+ electron-to-chromium "^1.4.251"
node-releases "^2.0.6"
- update-browserslist-db "^1.0.5"
-
-budo-express@^1.0.8:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/budo-express/-/budo-express-1.0.8.tgz#f1b325579453a1cd8ae510c25071bda89d594c08"
- integrity sha512-l7UXna1XB1jsH4dBPSv7AOWN9gekrUKDtwc+JrdiFhUNKsCPBWA+x62/rXqyzlcnthFgtfYhNnxtI9uh/FTpjQ==
- dependencies:
- assure-array "^1.0.0"
- bluebird "^3.7.2"
- browserify "^16.5.0"
- budo "^11.5.0"
- chalk "^3.0.0"
- default-value "^1.0.0"
- entities "^2.0.0"
- inject-lr-script "^2.2.0"
- is-stream "^2.0.0"
- stacked "^1.1.1"
- validatem "^0.2.0"
+ update-browserslist-db "^1.0.9"
budo@^11.5.0:
- version "11.7.0"
- resolved "https://registry.yarnpkg.com/budo/-/budo-11.7.0.tgz#544a11e424972de9bdcf28102c0f0675f7176648"
- integrity sha512-nkulzTNOulJR7PBL+obojWvkSmblxlpSWz6dVsAG2QWyEJmCmtdIUYMpqIEzpFBvR9I/2sW2S0Q1xkDBIQ4pgA==
+ version "11.8.4"
+ resolved "https://registry.yarnpkg.com/budo/-/budo-11.8.4.tgz#75d732958e6b7caff7cdeeab65d98991f1325b65"
+ integrity sha512-drUnbk6nAuzQ4xmyWjajvUb85ZhGduXpblY9guD776HmPqWoShlEE8XiYX145v7+ZoqznnShI3QHAObK9YSWnQ==
dependencies:
bole "^2.0.0"
- browserify "^16.2.3"
+ browserify "^17.0.0"
chokidar "^3.5.2"
connect-pushstate "^1.1.0"
escape-html "^1.0.3"
@@ -1979,7 +1948,7 @@ budo@^11.5.0:
get-ports "^1.0.2"
inject-lr-script "^2.1.0"
internal-ip "^3.0.1"
- micromatch "^3.1.10"
+ micromatch "^4.0.5"
on-finished "^2.3.0"
on-headers "^1.0.1"
once "^1.3.2"
@@ -1996,7 +1965,7 @@ budo@^11.5.0:
subarg "^1.0.0"
term-color "^1.0.1"
url-trim "^1.0.0"
- watchify-middleware "^1.8.2"
+ watchify-middleware "^1.9.1"
ws "^6.2.2"
xtend "^4.0.0"
@@ -2036,21 +2005,6 @@ bytes@3.1.2:
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
-cache-base@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
- integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
- dependencies:
- collection-visit "^1.0.0"
- component-emitter "^1.2.1"
- get-value "^2.0.6"
- has-value "^1.0.0"
- isobject "^3.0.1"
- set-value "^2.0.0"
- to-object-path "^0.3.0"
- union-value "^1.0.0"
- unset-value "^1.0.0"
-
cached-path-relative@^1.0.0, cached-path-relative@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.1.0.tgz#865576dfef39c0d6a7defde794d078f5308e3ef3"
@@ -2069,10 +2023,10 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-caniuse-lite@^1.0.30001370, caniuse-lite@^1.0.30001373:
- version "1.0.30001374"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz#3dab138e3f5485ba2e74bd13eca7fe1037ce6f57"
- integrity sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==
+caniuse-lite@^1.0.30001399, caniuse-lite@^1.0.30001400:
+ version "1.0.30001402"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001402.tgz#aa29e1f47f5055b0d0c07696a67b8b08023d14c8"
+ integrity sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==
chalk@^0.5.1:
version "0.5.1"
@@ -2149,16 +2103,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
inherits "^2.0.1"
safe-buffer "^5.0.1"
-class-utils@^0.3.5:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
- integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
- dependencies:
- arr-union "^3.1.0"
- define-property "^0.2.5"
- isobject "^3.0.0"
- static-extend "^0.1.1"
-
clone-regexp@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f"
@@ -2166,14 +2110,6 @@ clone-regexp@^2.1.0:
dependencies:
is-regexp "^2.0.0"
-collection-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
- integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==
- dependencies:
- map-visit "^1.0.0"
- object-visit "^1.0.0"
-
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -2218,31 +2154,11 @@ combine-source-map@~0.6.1:
lodash.memoize "~3.0.3"
source-map "~0.4.2"
-commander@^2.19.0, commander@^2.5.0:
+commander@^2.19.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-commoner@^0.10.0:
- version "0.10.8"
- resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5"
- integrity sha512-3/qHkNMM6o/KGXHITA14y78PcfmXh4+AOCJpSoF73h4VY1JpdGv3CHMS5+JW6SwLhfJt4RhNmLAa7+RRX/62EQ==
- dependencies:
- commander "^2.5.0"
- detective "^4.3.1"
- glob "^5.0.15"
- graceful-fs "^4.1.2"
- iconv-lite "^0.4.5"
- mkdirp "^0.5.0"
- private "^0.1.6"
- q "^1.1.2"
- recast "^0.11.17"
-
-component-emitter@^1.2.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
- integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
-
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2307,18 +2223,12 @@ cookie@0.5.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
-copy-descriptor@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
- integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==
-
-core-js-compat@^3.21.0, core-js-compat@^3.22.1:
- version "3.24.1"
- resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.24.1.tgz#d1af84a17e18dfdd401ee39da9996f9a7ba887de"
- integrity sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==
+core-js-compat@^3.25.1:
+ version "3.25.1"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.1.tgz#6f13a90de52f89bbe6267e5620a412c7f7ff7e42"
+ integrity sha512-pOHS7O0i8Qt4zlPW/eIFjwp+NrTPx+wTL0ctgI2fHn31sZOq89rDsmtc/A2vAX7r6shl+bmVI+678He46jgBlw==
dependencies:
browserslist "^4.21.3"
- semver "7.0.0"
"core-util-is@>=1.0.1 <1.1.0-0", core-util-is@~1.0.0:
version "1.0.3"
@@ -2419,6 +2329,11 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+csstype@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
+ integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+
d@1, d@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
@@ -2442,7 +2357,7 @@ debounce@^1.0.0:
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5"
integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==
-debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
+debug@2.6.9, debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
@@ -2456,11 +2371,6 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "2.1.2"
-decode-uri-component@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
- integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==
-
deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
@@ -2489,28 +2399,6 @@ define-properties@^1.1.3, define-properties@^1.1.4:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
-define-property@^0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
- integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==
- dependencies:
- is-descriptor "^0.1.0"
-
-define-property@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
- integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==
- dependencies:
- is-descriptor "^1.0.0"
-
-define-property@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
- integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
- dependencies:
- is-descriptor "^1.0.2"
- isobject "^3.0.1"
-
defined@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-0.0.0.tgz#f35eea7d705e933baf13b2f03b3f83d921403b3e"
@@ -2558,14 +2446,6 @@ destroy@1.2.0:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
-detective@^4.3.1:
- version "4.7.1"
- resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e"
- integrity sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==
- dependencies:
- acorn "^5.2.1"
- defined "^1.0.0"
-
detective@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
@@ -2603,6 +2483,11 @@ domain-browser@^1.2.0:
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
+dotty@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/dotty/-/dotty-0.1.2.tgz#512d44cc4111a724931226259297f235e8484f6f"
+ integrity sha512-V0EWmKeH3DEhMwAZ+8ZB2Ao4OK6p++Z0hsDtZq3N0+0ZMVqkzrcEGROvOnZpLnvBg5PTNG23JEDLAm64gPaotQ==
+
duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
@@ -2620,10 +2505,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
-electron-to-chromium@^1.4.202:
- version "1.4.211"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.211.tgz#afaa8b58313807501312d598d99b953568d60f91"
- integrity sha512-BZSbMpyFQU0KBJ1JG26XGeFI3i4op+qOYGxftmZXFZoHkhLgsSv4DHDJfl8ogII3hIuzGt51PaZ195OVu0yJ9A==
+electron-to-chromium@^1.4.251:
+ version "1.4.253"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.253.tgz#3402fd2159530fc6d94237f1b9535fa7bebaf399"
+ integrity sha512-1pezJ2E1UyBTGbA7fUlHdPSXQw1k+82VhTFLG5G0AUqLGvsZqFzleOblceqegZzxYX4kC7hGEEdzIQI9RZ1Cuw==
elliptic@^6.5.3:
version "6.5.4"
@@ -2666,15 +2551,15 @@ entities@^2.0.0:
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.0:
- version "1.20.1"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
- integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
+ version "1.20.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3"
+ integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==
dependencies:
call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
function.prototype.name "^1.1.5"
- get-intrinsic "^1.1.1"
+ get-intrinsic "^1.1.2"
get-symbol-description "^1.0.0"
has "^1.0.3"
has-property-descriptors "^1.0.0"
@@ -2686,9 +2571,9 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19
is-shared-array-buffer "^1.0.2"
is-string "^1.0.7"
is-weakref "^1.0.2"
- object-inspect "^1.12.0"
+ object-inspect "^1.12.2"
object-keys "^1.1.1"
- object.assign "^4.1.2"
+ object.assign "^4.1.4"
regexp.prototype.flags "^1.4.3"
string.prototype.trimend "^1.0.5"
string.prototype.trimstart "^1.0.5"
@@ -2710,7 +2595,7 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
-es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14:
+es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.62, es5-ext@~0.10.14:
version "0.10.62"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5"
integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==
@@ -2719,7 +2604,7 @@ es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14:
es6-symbol "^3.1.3"
next-tick "^1.1.0"
-es6-iterator@^2.0.3, es6-iterator@~2.0.1:
+es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==
@@ -2751,23 +2636,16 @@ es6-promisify@^6.0.0:
integrity sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==
es6-set@^0.1.5, es6-set@~0.1.5:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
- integrity sha512-7S8YXIcUfPMOr3rqJBVMePAbRsD1nWeSMQ86K/lDI76S3WKXz+KWILvTIPbTroubOkZTGh+b+7/xIIphZXNYbA==
- dependencies:
- d "1"
- es5-ext "~0.10.14"
- es6-iterator "~2.0.1"
- es6-symbol "3.1.1"
- event-emitter "~0.3.5"
-
-es6-symbol@3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
- integrity sha512-exfuQY8UGtn/N+gL1iKkH8fpNd5sJ760nJq6mmZAHldfxMD5kX07lbQuYlspoXsuknXNv9Fb7y2GsPOnQIbxHg==
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.6.tgz#5669e3b2aa01d61a50ba79964f733673574983b8"
+ integrity sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==
dependencies:
- d "1"
- es5-ext "~0.10.14"
+ d "^1.0.1"
+ es5-ext "^0.10.62"
+ es6-iterator "~2.0.3"
+ es6-symbol "^3.1.3"
+ event-emitter "^0.3.5"
+ type "^2.7.2"
es6-symbol@^3.1.1, es6-symbol@^3.1.3, es6-symbol@~3.1.1:
version "3.1.3"
@@ -2820,9 +2698,9 @@ eslint-plugin-react-hooks@^4.2.0:
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
eslint-plugin-react@^7.14.3, eslint-plugin-react@^7.24.0:
- version "7.30.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22"
- integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==
+ version "7.31.8"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz#3a4f80c10be1bcbc8197be9e8b641b2a3ef219bf"
+ integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==
dependencies:
array-includes "^3.1.5"
array.prototype.flatmap "^1.3.0"
@@ -2919,21 +2797,11 @@ espree@^7.3.0, espree@^7.3.1:
acorn-jsx "^5.3.1"
eslint-visitor-keys "^1.3.0"
-esprima-fb@13001.1001.0-dev-harmony-fb:
- version "13001.1001.0-dev-harmony-fb"
- resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz#633acdb40d9bd4db8a1c1d68c06a942959fad2b0"
- integrity sha512-u0PLCs9J36198vK7lFdvzfOiMT2v2K9/9d+J2M4d1ZEfTsXzvrzRHh95D+/sIziSabl4b6QKJOTn8+VaWc/B4A==
-
esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esprima@~3.1.0:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
- integrity sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==
-
esquery@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
@@ -2973,7 +2841,7 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
-event-emitter@~0.3.5:
+event-emitter@^0.3.5, event-emitter@~0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==
@@ -3024,19 +2892,6 @@ execall@^2.0.0:
dependencies:
clone-regexp "^2.1.0"
-expand-brackets@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
- integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==
- dependencies:
- debug "^2.3.3"
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- posix-character-classes "^0.1.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
express@^4.18.1:
version "4.18.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
@@ -3075,40 +2930,11 @@ express@^4.18.1:
vary "~1.1.2"
ext@^1.1.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52"
- integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==
- dependencies:
- type "^2.5.0"
-
-extend-shallow@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
- integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==
- dependencies:
- is-extendable "^0.1.0"
-
-extend-shallow@^3.0.0, extend-shallow@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
- integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f"
+ integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==
dependencies:
- assign-symbols "^1.0.0"
- is-extendable "^1.0.1"
-
-extglob@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
- integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
- dependencies:
- array-unique "^0.3.2"
- define-property "^1.0.0"
- expand-brackets "^2.1.4"
- extend-shallow "^2.0.1"
- fragment-cache "^0.2.1"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
+ type "^2.7.2"
factor-bundle@^2.5.0:
version "2.5.0"
@@ -3157,16 +2983,6 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"
-fill-range@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
- integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==
- dependencies:
- extend-shallow "^2.0.1"
- is-number "^3.0.0"
- repeat-string "^1.6.1"
- to-regex-range "^2.1.0"
-
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
@@ -3201,9 +3017,9 @@ flat-cache@^3.0.4:
rimraf "^3.0.2"
flatted@^3.1.0:
- version "3.2.6"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2"
- integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
+ integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
flatten@^1.0.2, flatten@^1.0.3:
version "1.0.3"
@@ -3217,11 +3033,6 @@ for-each@^0.3.3:
dependencies:
is-callable "^1.1.3"
-for-in@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
- integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==
-
forwarded@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
@@ -3232,13 +3043,6 @@ fraction.js@^4.2.0:
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
-fragment-cache@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
- integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==
- dependencies:
- map-cache "^0.2.2"
-
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -3327,10 +3131,10 @@ get-assigned-identifiers@^1.1.0, get-assigned-identifiers@^1.2.0:
resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1"
integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==
-get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
- integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
+ integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
@@ -3356,11 +3160,6 @@ get-symbol-description@^1.0.0:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
-get-value@^2.0.3, get-value@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
- integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==
-
glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
@@ -3368,17 +3167,6 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
dependencies:
is-glob "^4.0.1"
-glob@^5.0.15:
- version "5.0.15"
- resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
- integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==
- dependencies:
- inflight "^1.0.4"
- inherits "2"
- minimatch "2 || 3"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
glob@^7.1.0, glob@^7.1.3:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@@ -3403,11 +3191,6 @@ globals@^13.6.0, globals@^13.9.0:
dependencies:
type-fest "^0.20.2"
-graceful-fs@^4.1.2:
- version "4.2.10"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
- integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
-
has-ansi@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e"
@@ -3461,37 +3244,6 @@ has-tostringtag@^1.0.0:
dependencies:
has-symbols "^1.0.2"
-has-value@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
- integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==
- dependencies:
- get-value "^2.0.3"
- has-values "^0.1.4"
- isobject "^2.0.0"
-
-has-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
- integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==
- dependencies:
- get-value "^2.0.6"
- has-values "^1.0.0"
- isobject "^3.0.0"
-
-has-values@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
- integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==
-
-has-values@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
- integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==
- dependencies:
- is-number "^3.0.0"
- kind-of "^4.0.0"
-
has@^1.0.0, has@^1.0.1, has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
@@ -3525,6 +3277,13 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
htmlescape@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351"
@@ -3546,7 +3305,7 @@ https-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==
-iconv-lite@0.4.24, iconv-lite@^0.4.5:
+iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -3598,6 +3357,11 @@ ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
+immer@^9.0.7:
+ version "9.0.15"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc"
+ integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==
+
import-fresh@^3.0.0, import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@@ -3723,20 +3487,6 @@ ipaddr.js@1.9.1, ipaddr.js@^1.5.2:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
-is-accessor-descriptor@^0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
- integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==
- dependencies:
- kind-of "^3.0.2"
-
-is-accessor-descriptor@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
- integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
- dependencies:
- kind-of "^6.0.0"
-
is-arguments@^1.0.4:
version "1.1.1"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
@@ -3767,15 +3517,15 @@ is-boolean-object@^1.0.1, is-boolean-object@^1.1.0:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
-is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.6:
+is-buffer@^1.1.0, is-buffer@~1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
- integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.6.tgz#fd6170b0b8c7e2cc73de342ef8284a2202023c44"
+ integrity sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==
is-core-module@^2.9.0:
version "2.10.0"
@@ -3784,20 +3534,6 @@ is-core-module@^2.9.0:
dependencies:
has "^1.0.3"
-is-data-descriptor@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
- integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==
- dependencies:
- kind-of "^3.0.2"
-
-is-data-descriptor@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
- integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
- dependencies:
- kind-of "^6.0.0"
-
is-date-object@^1.0.1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
@@ -3805,36 +3541,6 @@ is-date-object@^1.0.1:
dependencies:
has-tostringtag "^1.0.0"
-is-descriptor@^0.1.0:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
- integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
- dependencies:
- is-accessor-descriptor "^0.1.6"
- is-data-descriptor "^0.1.4"
- kind-of "^5.0.0"
-
-is-descriptor@^1.0.0, is-descriptor@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
- integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
- dependencies:
- is-accessor-descriptor "^1.0.0"
- is-data-descriptor "^1.0.0"
- kind-of "^6.0.2"
-
-is-extendable@^0.1.0, is-extendable@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
- integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==
-
-is-extendable@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
- integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
- dependencies:
- is-plain-object "^2.0.4"
-
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@@ -3876,13 +3582,6 @@ is-number-object@^1.0.4:
dependencies:
has-tostringtag "^1.0.0"
-is-number@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
- integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==
- dependencies:
- kind-of "^3.0.2"
-
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
@@ -3893,12 +3592,10 @@ is-plain-obj@^2.0.0, is-plain-obj@^2.1.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
-is-plain-object@^2.0.3, is-plain-object@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
- integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
- dependencies:
- isobject "^3.0.1"
+is-plain-object@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
+ integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
is-regex@^1.1.4:
version "1.1.4"
@@ -3955,6 +3652,13 @@ is-typed-array@^1.1.3, is-typed-array@^1.1.9:
for-each "^0.3.3"
has-tostringtag "^1.0.0"
+is-valid-domain@^0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/is-valid-domain/-/is-valid-domain-0.1.6.tgz#3c85469d2938f170c8f82ce6e52df8ad9fca8105"
+ integrity sha512-ZKtq737eFkZr71At8NxOFcP9O1K89gW3DkdrGMpp1upr/ueWjj+Weh4l9AI4rN0Gt8W2M1w7jrG2b/Yv83Ljpg==
+ dependencies:
+ punycode "^2.1.1"
+
is-weakref@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
@@ -3962,17 +3666,12 @@ is-weakref@^1.0.2:
dependencies:
call-bind "^1.0.2"
-is-windows@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
- integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
-
isarray@0.0.1, isarray@~0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
-isarray@1.0.0, isarray@~1.0.0:
+isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
@@ -3982,18 +3681,6 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-isobject@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
- integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==
- dependencies:
- isarray "1.0.0"
-
-isobject@^3.0.0, isobject@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
- integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
-
js-base64@^2.1.9:
version "2.6.4"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
@@ -4081,46 +3768,13 @@ jsonparse@^1.2.0:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
-jstransform@^10.1.0:
- version "10.1.0"
- resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-10.1.0.tgz#b4c49bf63f162c108b0348399a8737c713b0a83a"
- integrity sha512-hzsCrPlH8ASlARV/sjsjbnvg0AXz9DxMHry44wXF3GTvletHT8UhsmqUzSGaImlney40E1gw4D6izUzifD15IQ==
- dependencies:
- base62 "0.1.1"
- esprima-fb "13001.1001.0-dev-harmony-fb"
- source-map "0.1.31"
-
"jsx-ast-utils@^2.4.1 || ^3.0.0":
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz#afe5efe4332cd3515c065072bd4d6b0aa22152bd"
- integrity sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
+ integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
dependencies:
array-includes "^3.1.5"
- object.assign "^4.1.2"
-
-kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
- integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
- integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
- integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
-
-kind-of@^6.0.0, kind-of@^6.0.2:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
- integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+ object.assign "^4.1.3"
labeled-stream-splicer@^1.0.0:
version "1.0.2"
@@ -4205,11 +3859,6 @@ magic-string@0.25.1:
dependencies:
sourcemap-codec "^1.4.1"
-map-cache@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
- integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==
-
map-limit@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/map-limit/-/map-limit-0.0.1.tgz#eb7961031c0f0e8d001bf2d56fab685d58822f38"
@@ -4222,13 +3871,6 @@ map-obj@^4.1.0:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
-map-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
- integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==
- dependencies:
- object-visit "^1.0.0"
-
md5.js@^1.3.4:
version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -4269,24 +3911,13 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
-micromatch@^3.1.10:
- version "3.1.10"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
- integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
- dependencies:
- arr-diff "^4.0.0"
- array-unique "^0.3.2"
- braces "^2.3.1"
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- extglob "^2.0.4"
- fragment-cache "^0.2.1"
- kind-of "^6.0.2"
- nanomatch "^1.2.9"
- object.pick "^1.3.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.2"
+micromatch@^4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
miller-rabin@^4.0.0:
version "4.0.1"
@@ -4323,7 +3954,7 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
-"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
+minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -4345,26 +3976,11 @@ minimist@~0.2.0:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.1.tgz#827ba4e7593464e7c221e8c5bed930904ee2c455"
integrity sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==
-mixin-deep@^1.2.0:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
- integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
- dependencies:
- for-in "^1.0.2"
- is-extendable "^1.0.1"
-
mkdirp-classic@^0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
-mkdirp@^0.5.0:
- version "0.5.6"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
- integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
- dependencies:
- minimist "^1.2.6"
-
modern-normalize@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7"
@@ -4411,23 +4027,6 @@ nanoid@^3.3.4:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
-nanomatch@^1.2.9:
- version "1.2.13"
- resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
- integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
- dependencies:
- arr-diff "^4.0.0"
- array-unique "^0.3.2"
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- fragment-cache "^0.2.1"
- is-windows "^1.0.2"
- kind-of "^6.0.2"
- object.pick "^1.3.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -4480,16 +4079,7 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
-object-copy@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
- integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==
- dependencies:
- copy-descriptor "^0.1.0"
- define-property "^0.2.5"
- kind-of "^3.0.3"
-
-object-inspect@^1.12.0, object-inspect@^1.6.0, object-inspect@^1.9.0:
+object-inspect@^1.12.2, object-inspect@^1.6.0, object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
@@ -4499,17 +4089,10 @@ object-keys@^1.1.1:
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
-object-visit@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
- integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==
- dependencies:
- isobject "^3.0.0"
-
-object.assign@^4.1.0, object.assign@^4.1.2:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.3.tgz#d36b7700ddf0019abb6b1df1bb13f6445f79051f"
- integrity sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==
+object.assign@^4.1.0, object.assign@^4.1.3, object.assign@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
+ integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
@@ -4542,13 +4125,6 @@ object.hasown@^1.1.1:
define-properties "^1.1.4"
es-abstract "^1.19.5"
-object.pick@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
- integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==
- dependencies:
- isobject "^3.0.1"
-
object.values@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac"
@@ -4691,11 +4267,6 @@ parseurl@~1.3.3:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-pascalcase@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
- integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==
-
path-browserify@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
@@ -4763,9 +4334,9 @@ photoswipe-dynamic-caption-plugin@^1.2.4:
integrity sha512-7gPO8BHnOGZ0nXVhziltDqe7cAhDmaolGaU6LC3vggi4dcTHJBsGnxuqpk2EXw6vJ/JOeS0MqyGGUXupYbZk5w==
photoswipe@^5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-5.3.0.tgz#fe118b147dddaf58ccc17c9403c7d7148805f8d2"
- integrity sha512-vZMwziQorjiagzX7EvWimVT0YHO0DWNtR9UT6cv3yW1FA199LgsTpj4ziB2oJ/X/197gKmi56Oux5PudWUAmuw==
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-5.3.2.tgz#814d26197ba59076828ddefd41b7f9ed5eb355a8"
+ integrity sha512-QJrf0kGa3tYX3sUascZymkT+ZIkgw8YNcwL+hGqoLTyphcn9vSTEab7tmCnA1tthgVzWQRgPjX9psuk7yFrTcA==
picocolors@^0.2.1:
version "0.2.1"
@@ -4777,7 +4348,7 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-picomatch@^2.0.4, picomatch@^2.2.1:
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -4792,11 +4363,6 @@ plur@^1.0.0:
resolved "https://registry.yarnpkg.com/plur/-/plur-1.0.0.tgz#db85c6814f5e5e5a3b49efc28d604fec62975156"
integrity sha512-qSnKBSZeDY8ApxwhfVIwKwF36KVJqb1/9nzYYq3j3vdwocULCXT8f8fQGkiw1Nk9BGfxiDagEe/pwakA+bOBqw==
-posix-character-classes@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
- integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==
-
postcss-color-mod-function@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d"
@@ -4856,9 +4422,9 @@ postcss-nested@^5.0.6:
postcss-selector-parser "^6.0.6"
postcss-scss@^4.0.4:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.4.tgz#aa8f60e19ee18259bc193db9e4b96edfce3f3b1f"
- integrity sha512-aBBbVyzA8b3hUL0MGrpydxxXKXFZc5Eqva0Q3V9qsBOLEMsjb6w49WfpsoWzpEgcqJGW4t7Rio8WXVU9Gd8vWg==
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.5.tgz#8ee33c1dda8d9d4753b565ec79014803dc6edabf"
+ integrity sha512-F7xpB6TrXyqUh3GKdyB4Gkp3QL3DDW1+uI+gxx/oJnUt/qXI4trj5OGlp9rOKdoABGULuqtqeG+3HEVQk4DjmA==
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.6:
version "6.0.10"
@@ -4926,15 +4492,15 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
-prettier-bytes@^1.0.3:
+prettier-bytes@^1.0.3, prettier-bytes@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prettier-bytes/-/prettier-bytes-1.0.4.tgz#994b02aa46f699c50b6257b5faaa7fe2557e62d6"
integrity sha512-dLbWOa4xBn+qeWeIF60qRoB6Pk2jX5P3DIVgOQyMyvBpu931Q+8dXz8X0snJiFkQdohDDLnZQECjzsAj75hgZQ==
-pretty-bytes@^5.6.0:
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
- integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
+pretty-bytes@4:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
+ integrity sha512-yJAF+AjbHKlxQ8eezMd/34Mnj/YTQ3i6kLzvVsH4l/BfIFtp444n0wVbnsn66JimZ9uBofv815aRp1zCppxlWw==
pretty-ms@^2.1.0:
version "2.1.0"
@@ -4945,11 +4511,6 @@ pretty-ms@^2.1.0:
parse-ms "^1.0.0"
plur "^1.0.0"
-private@^0.1.6, private@~0.1.5:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
- integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
-
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -5004,16 +4565,11 @@ punycode@^1.3.2:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
-punycode@^2.1.0:
+punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-q@^1.1.2:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
- integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
-
qs@6.10.3:
version "6.10.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
@@ -5069,43 +4625,49 @@ raw-body@2.5.1:
iconv-lite "0.4.24"
unpipe "1.0.0"
-react-dom@^17.0.1:
- version "17.0.2"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
- integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+react-dom@18:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
- scheduler "^0.20.2"
+ scheduler "^0.23.0"
+
+react-error-boundary@^3.1.4:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
+ integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
-react-is@^16.13.1:
+react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
-react-tools@~0.13.0:
- version "0.13.3"
- resolved "https://registry.yarnpkg.com/react-tools/-/react-tools-0.13.3.tgz#da6ac7d4d7777a59a5e951cf46e72fd4b6b40a2c"
- integrity sha512-lmdjIRNk2cVUdlF/dyy6oP0nG2qrlX5qKFYRtiC5zK5Sg5QqgUEOrcS7Jz+kPNeOj9OWT7NfrR/cDvbGGSjCyg==
- dependencies:
- commoner "^0.10.0"
- jstransform "^10.1.0"
+react-is@^18.0.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
-react@^17.0.1:
- version "17.0.2"
- resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
- integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+react-redux@^8.0.2:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.2.tgz#bc2a304bb21e79c6808e3e47c50fe1caf62f7aad"
+ integrity sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==
dependencies:
- loose-envify "^1.1.0"
- object-assign "^4.1.1"
+ "@babel/runtime" "^7.12.1"
+ "@types/hoist-non-react-statics" "^3.3.1"
+ "@types/use-sync-external-store" "^0.0.3"
+ hoist-non-react-statics "^3.3.2"
+ react-is "^18.0.0"
+ use-sync-external-store "^1.0.0"
-reactify@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/reactify/-/reactify-1.1.1.tgz#a8f119596273c0d4bfb1abea0c14c2601ea03bba"
- integrity sha512-pWjYX2sqGD5ojOeSJMgkZngDFzCsp4gyIPJmkUfaKnCg4yHA9SGGtI3VZSSc4jD8R5WcPWXSC8qGszOE5uj6gQ==
+react@18:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
- react-tools "~0.13.0"
- through "~2.3.4"
+ loose-envify "^1.1.0"
read-cache@^1.0.0:
version "1.0.0"
@@ -5177,20 +4739,32 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
-recast@^0.11.17:
- version "0.11.23"
- resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
- integrity sha512-+nixG+3NugceyR8O1bLU45qs84JgI3+8EauyRZafLgC9XbdAOIVgwV1Pe2da0YzGo62KzWoZwUpVEQf6qNAXWA==
+redux-devtools-extension@^2.13.9:
+ version "2.13.9"
+ resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz#6b764e8028b507adcb75a1cae790f71e6be08ae7"
+ integrity sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==
+
+redux-persist@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8"
+ integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==
+
+redux-thunk@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714"
+ integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==
+
+redux@^4.1.2:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13"
+ integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==
dependencies:
- ast-types "0.9.6"
- esprima "~3.1.0"
- private "~0.1.5"
- source-map "~0.5.0"
+ "@babel/runtime" "^7.9.2"
-regenerate-unicode-properties@^10.0.1:
- version "10.0.1"
- resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
- integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==
+regenerate-unicode-properties@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
+ integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==
dependencies:
regenerate "^1.4.2"
@@ -5211,14 +4785,6 @@ regenerator-transform@^0.15.0:
dependencies:
"@babel/runtime" "^7.8.4"
-regex-not@^1.0.0, regex-not@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
- integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
- dependencies:
- extend-shallow "^3.0.2"
- safe-regex "^1.1.0"
-
regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
@@ -5234,26 +4800,26 @@ regexpp@^3.1.0:
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
regexpu-core@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.1.0.tgz#2f8504c3fd0ebe11215783a41541e21c79942c6d"
- integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139"
+ integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==
dependencies:
regenerate "^1.4.2"
- regenerate-unicode-properties "^10.0.1"
- regjsgen "^0.6.0"
- regjsparser "^0.8.2"
+ regenerate-unicode-properties "^10.1.0"
+ regjsgen "^0.7.1"
+ regjsparser "^0.9.1"
unicode-match-property-ecmascript "^2.0.0"
unicode-match-property-value-ecmascript "^2.0.0"
-regjsgen@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d"
- integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==
+regjsgen@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6"
+ integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==
-regjsparser@^0.8.2:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f"
- integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==
+regjsparser@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709"
+ integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==
dependencies:
jsesc "~0.5.0"
@@ -5264,12 +4830,7 @@ reload-css@^1.0.0:
dependencies:
query-string "^4.2.3"
-repeat-element@^1.1.2:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9"
- integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==
-
-repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1:
+repeat-string@^1.5.2, repeat-string@^1.5.4:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
@@ -5279,16 +4840,16 @@ require-from-string@^2.0.2:
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+reselect@^4.1.5:
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.6.tgz#19ca2d3d0b35373a74dc1c98692cdaffb6602656"
+ integrity sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==
+
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-resolve-url@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
- integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==
-
resolve@^1.1.4, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.4.0:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
@@ -5315,11 +4876,6 @@ resp-modifier@^6.0.0:
debug "^2.2.0"
minimatch "^3.0.2"
-ret@~0.1.10:
- version "0.1.15"
- resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
- integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
-
reversepoint@~0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/reversepoint/-/reversepoint-0.2.1.tgz#d2ac3ff4d665cf0ff72296b7a78ee7237f6593f5"
@@ -5355,25 +4911,17 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-regex@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
- integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==
- dependencies:
- ret "~0.1.10"
-
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-scheduler@^0.20.2:
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
- integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+scheduler@^0.23.0:
+ version "0.23.0"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
+ integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
- object-assign "^4.1.1"
scope-analyzer@^2.0.1:
version "2.1.2"
@@ -5388,11 +4936,6 @@ scope-analyzer@^2.0.1:
estree-is-function "^1.0.0"
get-assigned-identifiers "^1.1.0"
-semver@7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
- integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
-
semver@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
@@ -5439,16 +4982,6 @@ serve-static@1.15.0, serve-static@^1.10.0:
parseurl "~1.3.3"
send "0.18.0"
-set-value@^2.0.0, set-value@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
- integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
- dependencies:
- extend-shallow "^2.0.1"
- is-extendable "^0.1.1"
- is-plain-object "^2.0.3"
- split-string "^3.0.1"
-
setprototypeof@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
@@ -5546,52 +5079,11 @@ slice-ansi@^4.0.0:
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
-snapdragon-node@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
- integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
- dependencies:
- define-property "^1.0.0"
- isobject "^3.0.0"
- snapdragon-util "^3.0.1"
-
-snapdragon-util@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
- integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
- dependencies:
- kind-of "^3.2.0"
-
-snapdragon@^0.8.1:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
- integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
- dependencies:
- base "^0.11.1"
- debug "^2.2.0"
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- map-cache "^0.2.2"
- source-map "^0.5.6"
- source-map-resolve "^0.5.0"
- use "^3.1.0"
-
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
-source-map-resolve@^0.5.0:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
- integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
- dependencies:
- atob "^2.1.2"
- decode-uri-component "^0.2.0"
- resolve-url "^0.2.1"
- source-map-url "^0.4.0"
- urix "^0.1.0"
-
source-map-support@~0.5.10:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@@ -5600,19 +5092,7 @@ source-map-support@~0.5.10:
buffer-from "^1.0.0"
source-map "^0.6.0"
-source-map-url@^0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
- integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
-
-source-map@0.1.31:
- version "0.1.31"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.31.tgz#9f704d0d69d9e138a81badf6ebb4fde33d151c61"
- integrity sha512-qFALUiKHo35Duky0Ubmb5YKj9b3c6CcgGNGeI60sd6Nn3KaY7h9fclEOcCVk0hwszwYYP6+X2/jpS5hHqqVuig==
- dependencies:
- amdefine ">=0.0.4"
-
-source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.3:
+source-map@^0.5.6, source-map@~0.5.3:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
@@ -5639,13 +5119,6 @@ split-filter-n@^1.1.2:
resolved "https://registry.yarnpkg.com/split-filter-n/-/split-filter-n-1.1.3.tgz#c983ae1e52402e70071f711a7af767a91f09f740"
integrity sha512-EU0EjvBI/mYBQMSAHq+ua/YNCuThuDjbU5h036k01+xieFW1aNvLNKb90xLihXIz5xJQX4VkEKan4LjSIyv7lg==
-split-string@^3.0.1, split-string@^3.0.2:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
- integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
- dependencies:
- extend-shallow "^3.0.0"
-
split2@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/split2/-/split2-0.2.1.tgz#02ddac9adc03ec0bb78c1282ec079ca6e85ae900"
@@ -5670,14 +5143,6 @@ static-eval@^2.0.5:
dependencies:
escodegen "^1.11.1"
-static-extend@^0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
- integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==
- dependencies:
- define-property "^0.2.5"
- object-copy "^0.1.0"
-
static-module@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/static-module/-/static-module-3.0.4.tgz#bfbd1d1c38dd1fbbf0bb4af0c1b3ae18a93a2b68"
@@ -6019,21 +5484,6 @@ to-fast-properties@^2.0.0:
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
-to-object-path@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
- integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==
- dependencies:
- kind-of "^3.0.2"
-
-to-regex-range@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
- integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==
- dependencies:
- is-number "^3.0.0"
- repeat-string "^1.6.1"
-
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
@@ -6041,16 +5491,6 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
-to-regex@^3.0.1, to-regex@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
- integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
- dependencies:
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- regex-not "^1.0.2"
- safe-regex "^1.1.0"
-
toidentifier@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
@@ -6093,7 +5533,7 @@ type@^1.0.1:
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
-type@^2.5.0:
+type@^2.7.2:
version "2.7.2"
resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0"
integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==
@@ -6159,19 +5599,9 @@ unicode-match-property-value-ecmascript@^2.0.0:
integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==
unicode-property-aliases-ecmascript@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8"
- integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==
-
-union-value@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
- integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
- dependencies:
- arr-union "^3.1.0"
- get-value "^2.0.6"
- is-extendable "^0.1.1"
- set-value "^2.0.1"
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
+ integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
uniq@^1.0.1:
version "1.0.1"
@@ -6183,18 +5613,10 @@ unpipe@1.0.0, unpipe@~1.0.0:
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
-unset-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
- integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==
- dependencies:
- has-value "^0.3.1"
- isobject "^3.0.0"
-
-update-browserslist-db@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38"
- integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==
+update-browserslist-db@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18"
+ integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==
dependencies:
escalade "^3.1.1"
picocolors "^1.0.0"
@@ -6206,11 +5628,6 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
-urix@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
- integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==
-
url-trim@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/url-trim/-/url-trim-1.0.0.tgz#40057e2f164b88e5daca7269da47e6d1dd837adc"
@@ -6224,10 +5641,10 @@ url@~0.11.0:
punycode "1.3.2"
querystring "0.2.0"
-use@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
- integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
+use-sync-external-store@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
+ integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
@@ -6290,10 +5707,10 @@ vm-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
-watchify-middleware@^1.8.2:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/watchify-middleware/-/watchify-middleware-1.9.0.tgz#27d1964687bbd9385a4e57a39fef0d06d32a1267"
- integrity sha512-KI+MJlzbgl/FgnjY+9VTn3uZMhZKv6SXTBXcN3pxbA1KUt67IMOx4WANng5RUoZ2y9+496guR8CMxDsfSyM2KA==
+watchify-middleware@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/watchify-middleware/-/watchify-middleware-1.9.1.tgz#3c6b9b18507a54a86c58b6eb5629f94cf9a116d4"
+ integrity sha512-vjD5S1cTJC99ZLvq61AGiR+Es+4Oloo3mTzPvAPArlBlq8w2IJ1qtQheRgf26ihqjZ3qW/IfgLeqxWOyHorHbw==
dependencies:
concat-stream "^1.5.0"
debounce "^1.0.0"
@@ -6357,6 +5774,11 @@ word-wrap@^1.2.3, word-wrap@~1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+wouter@^2.8.0-alpha.2:
+ version "2.8.0-alpha.2"
+ resolved "https://registry.yarnpkg.com/wouter/-/wouter-2.8.0-alpha.2.tgz#d57dfbd23b964b8bd848f2ed3eb2b38cf3c00e00"
+ integrity sha512-aPsL5m5rW9RiceClOmGj6t5gn9Ut2TJVr98UDi1u9MIRNYiYVflg6vFIjdDYJ4IAyH0JdnkSgGwfo0LQS3k2zg==
+
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
diff --git a/web/template/frontend.tmpl b/web/template/frontend.tmpl
@@ -1,5 +1,6 @@
{{ template "header.tmpl" .}}
<main class="lightgray">
- <div id="root"></div>
+ <div id="root">
+ </div>
</main>
{{ template "footer.tmpl" .}}
\ No newline at end of file
diff --git a/web/template/index.tmpl b/web/template/index.tmpl
@@ -1,5 +1,5 @@
{{ template "header.tmpl" .}}
-<section class="excerpt_top">
+<section class="excerpt-top">
home to <span class="count">{{.instance.Stats.user_count}}</span> users
who posted <span class="count">{{.instance.Stats.status_count}}</span> statuses,
federating with <span class="count">{{.instance.Stats.domain_count}}</span> other instances.
diff --git a/web/template/status.tmpl b/web/template/status.tmpl
@@ -2,6 +2,10 @@
<a href="{{.Account.URL}}" class="avatar"><img src="{{.Account.Avatar}}" alt=""></a>
<a href="{{.Account.URL}}" class="displayname">{{if .Account.DisplayName}}{{emojify .Account.Emojis (escape .Account.DisplayName)}}{{else}}{{.Account.Username}}{{end}}</a>
<a href="{{.Account.URL}}" class="username">@{{.Account.Acct}}</a>
+ <div class="not-expanded">
+ <span class="visibility">{{.Visibility | visibilityIcon}}</span>
+ <span class="date">{{.CreatedAt | timestamp}}</span>
+ </div>
<div class="text">
{{if .SpoilerText}}
<input class="spoiler" id="hideSpoiler-{{.ID}}" type="checkbox" style="display: none" aria-hidden="true" checked="true" />
@@ -43,7 +47,6 @@
<div class="info">
<div id="date">{{.CreatedAt | timestamp}}</div>
<div class="stats">
- <div id="visibility">{{.Visibility | visibilityIcon}}</div>
<div id="replies"><i aria-label="Replies" class="fa fa-reply-all"></i> {{.RepliesCount}}</div>
<div id="boosts"><i aria-label="Boosts" class="fa fa-retweet"></i> {{.ReblogsCount}}</div>
<div id="favorites"><i aria-label="Favorites" class="fa fa-star"></i> {{.FavouritesCount}}</div>