use google user avatar as profile phone

This commit is contained in:
João Geonizeli
2022-07-22 12:53:57 -03:00
parent 20781746e6
commit 9db59c071f
18 changed files with 72 additions and 252 deletions

View File

@@ -2,15 +2,20 @@ module Users
class OmniauthCallbacksController < Devise::OmniauthCallbacksController class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2 def google_oauth2
# You need to implement the method below in your model (e.g. app/models/user.rb) # You need to implement the method below in your model (e.g. app/models/user.rb)
@user = User.find_by!(email: request.env['omniauth.auth'].info['email']) @user = User.from_omniauth(
request.env['omniauth.auth'].info['email'],
request.env['omniauth.auth'].info['image']
)
if @user
flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google' flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect @user, event: :authentication sign_in_and_redirect @user, event: :authentication
rescue ActiveRecord::RecordNotFound => e else
# Removing extra as it can overflow some session stores
session['devise.google_data'] = request.env['omniauth.auth'].except('extra') session['devise.google_data'] = request.env['omniauth.auth'].except('extra')
redirect_to new_user_registration_url, alert: e.message redirect_to new_user_registration_url, alert: 'User not found.'
end
end end
end end
end end

View File

@@ -8,6 +8,7 @@ module Types
field :name, String, null: false field :name, String, null: false
field :email, String, null: false field :email, String, null: false
field :roles, [Enums::RoleEnum], null: false field :roles, [Enums::RoleEnum], null: false
field :avatar_url, String, null: true
def roles def roles
object.roles.map(&:name) object.roles.map(&:name)

View File

@@ -454,6 +454,7 @@ export type UpdateQuestionPayload = {
export type User = { export type User = {
__typename?: 'User'; __typename?: 'User';
avatarUrl?: Maybe<Scalars['String']>;
email: Scalars['String']; email: Scalars['String'];
id: Scalars['ID']; id: Scalars['ID'];
name: Scalars['String']; name: Scalars['String'];

View File

@@ -614,6 +614,7 @@ type UpdateQuestionPayload {
} }
type User { type User {
avatarUrl: String
email: String! email: String!
id: ID! id: ID!
name: String! name: String!

View File

@@ -1,63 +0,0 @@
import React, { FC, useState } from "react";
import axios from "axios";
import { Alert } from "../Alert";
import { Button } from "../Button";
import { PhotoCrop } from "./PhotoCrop";
import { useCurrentUser } from "../../contexts";
import { Modal } from "../Modal";
type Props = {
isOpen: boolean
setIsOpen: (value: boolean) => void;
};
export const AvatarEditor: FC<Props> = ({ isOpen, setIsOpen }) => {
const [croppedImage, setCroppedImage] = useState<any>()
const [alert, setAlert] = useState<boolean>()
const { refetch, authToken } = useCurrentUser()
const instance = axios.create({
});
instance.defaults.headers.common.Authorization = `Bearer ${authToken}`;
const onSubmit = () => {
instance
.post("/update_avatar", {
upload: croppedImage,
})
.then((res) => {
if (res.status === 200) {
setIsOpen(false)
refetch()
} else {
setAlert(true);
}
})
.catch(() => {
setAlert(true);
});
};
return (
<Modal
title="Alterar Imagem de Perfil"
isOpen={isOpen}
setIsOpen={setIsOpen}
buttons={
<>
<Button onClick={() => setIsOpen(false)}>
Cancelar
</Button>
<Button type="primary" onClick={() => onSubmit()}>
Salvar
</Button>
</>
}
>
{alert && <Alert>Algo deu errado, tente novamente mais tarde.</Alert>}
<PhotoCrop callback={setCroppedImage} />
</Modal>
);
};

View File

@@ -1,49 +0,0 @@
import React, { FC, useState } from "react";
import PhotoCropper from "react-avatar-edit";
type Props = {
callback: (value: any) => void
}
const borderStyle: React.CSSProperties = {
textAlign: 'center',
margin: 'auto',
borderStyle: 'dotted',
borderWidth: '0.3rem',
borderRadius: '0.3rem',
}
export const PhotoCrop: FC<Props> = ({ callback }) => {
const [result, setResult] = useState<any>();
const onCrop = (cropped: any) => {
setResult(cropped);
callback(result);
};
const onClose = () => {
setResult(null);
};
const onBeforeFileLoad = (elem: any) => {
if (elem.target.files[0].size > 1000000) {
elem.target.value = "";
alert("A imagem selecionada é grande de mais!")
}
};
const dimention = 300;
return (
<PhotoCropper
borderStyle={borderStyle}
label="Escolha uma imagem"
width={dimention}
height={dimention}
imageWidth={dimention}
imageHeight={dimention}
onCrop={(e) => onCrop(e)}
onClose={() => onClose()}
onBeforeFileLoad={onBeforeFileLoad}
/>
);
};

View File

@@ -1 +0,0 @@
export { AvatarEditor } from "./AvatarEditor";

View File

@@ -10,12 +10,19 @@ type Props = {
export const UserAvatar: FC<Props> = ({user, className}) => { export const UserAvatar: FC<Props> = ({user, className}) => {
return ( return (
<div className={`rounded-full border-2 border-primary-light shadow ${className || ''}`}> <div className={`rounded-full border-2 border-primary-light shadow ${className || ''}`}>
<BoringAvatar {user.avatarUrl ?
<img
className="rounded-full"
src={user.avatarUrl}
alt={`Avatar do usuário ${user.name}`}
/>
: <BoringAvatar
size={"100%"} size={"100%"}
name={user.name} name={user.name}
variant="pixel" variant="pixel"
colors={["#595F72", "#575D90", "#84A07C", "#C3D350", "#E6F14A"]} colors={["#595F72", "#575D90", "#84A07C", "#C3D350", "#E6F14A"]}
/> />
}
</div> </div>
) )
}; };

View File

@@ -4,7 +4,6 @@ export * from "./Button";
export * from "./Card"; export * from "./Card";
export * from "./CardGrid"; export * from "./CardGrid";
export * from "./InputGroup"; export * from "./InputGroup";
export * from "./AvatarEditor";
export * from "./Navegator"; export * from "./Navegator";
export * from "./UserAvatar"; export * from "./UserAvatar";
export * from "./Dialog"; export * from "./Dialog";

View File

@@ -1,23 +1,18 @@
import React, { import { gql, useQuery } from "@apollo/client";
createContext, useContext, useState, FC import React, { createContext, FC, useContext } from "react";
} from "react";
import { useQuery, gql } from "@apollo/client";
import { Query, UserRole } from "../__generated__/graphql-schema";
import { UnauthorizedAccess } from "../pages/session"; import { UnauthorizedAccess } from "../pages/session";
import { Loading } from "../pages/shared"; import { Loading } from "../pages/shared";
import { Query, UserRole } from "../__generated__/graphql-schema";
export type UserContext = { export type UserContext = {
user?: Query['currentUser'] user?: Query["currentUser"];
refetch: () => void isOnlyTeacher: boolean;
isOnlyTeacher: boolean };
}
const Context = createContext<UserContext>({ const Context = createContext<UserContext>({
refetch: () => {
},
isOnlyTeacher: false, isOnlyTeacher: false,
}) });
export const useCurrentUser = (): UserContext => { export const useCurrentUser = (): UserContext => {
const context = useContext(Context); const context = useContext(Context);
@@ -36,35 +31,27 @@ const CurrentUserQuery = gql`
name name
email email
roles roles
avatarUrl
} }
} }
`; `;
type Props = { type Props = {
children: any children: any;
} };
export const UserContext: FC<Props> = ({ children }) => { export const UserContext: FC<Props> = ({ children }) => {
const [user, setUser] = useState<Query['currentUser']>(); const { loading, data } = useQuery<Query>(CurrentUserQuery);
const isOnlyTeacher = !!(user?.roles.includes(UserRole.Teacher) && user?.roles.length === 1) const user = data?.currentUser;
const isOnlyTeacher = !!(
user?.roles.includes(UserRole.Teacher) && user?.roles.length === 1
);
const { refetch: refetchUserQuery, loading } = useQuery<Query>(CurrentUserQuery, { if (loading) return <Loading />;
onCompleted: ({ currentUser }) => { if (!user?.roles.length) return <UnauthorizedAccess />;
setUser(currentUser)
}
})
const refetch = async () => {
const { data: { currentUser } } = await refetchUserQuery()
setUser(currentUser)
}
if (loading) return <Loading />
if (!user) return <UnauthorizedAccess />
return ( return (
<Context.Provider value={{ user, refetch, isOnlyTeacher }}> <Context.Provider value={{ user, isOnlyTeacher }}>
{children} {children}
</Context.Provider> </Context.Provider>
); );

View File

@@ -1,27 +1,21 @@
import React, { useState } from "react"; import React from "react";
import { CurrentUserAvatar, Navigator } from "../../components";
import { useCurrentUser } from "../../contexts"; import { useCurrentUser } from "../../contexts";
import { AvatarEditor, Navigator, CurrentUserAvatar } from "../../components";
export const Profile = () => { export const Profile = () => {
const [avatarEditorIsOpen, setAvatarEditorIsOpen] = useState(false);
const { user } = useCurrentUser(); const { user } = useCurrentUser();
return ( return (
<> <>
<AvatarEditor
isOpen={avatarEditorIsOpen}
setIsOpen={setAvatarEditorIsOpen}
/>
<Navigator home /> <Navigator home />
<div className="bg-gray-100 w-full my-3"> <div className="bg-gray-100 w-full my-3">
<main> <main>
<div className="flex items-center flex-col max-w-4xl m-auto"> <div className="flex items-center flex-col max-w-4xl m-auto">
<div className="bg-white shadow border border-gray-100 flex flex-col items-center rounded p-4 w-full mt-12 mb-4 relative"> <div className="bg-white shadow border border-gray-100 flex flex-col items-center rounded p-4 w-full mt-12 mb-4 relative">
<div <div
className="w-20 absolute cursor-pointer" className="w-20 absolute"
style={{ top: "-3.10rem" }} style={{ top: "-3.10rem" }}
onClick={() => setAvatarEditorIsOpen(true)}
> >
<CurrentUserAvatar /> <CurrentUserAvatar />
</div> </div>

View File

@@ -3,6 +3,7 @@
# Table name: users # Table name: users
# #
# id :bigint not null, primary key # id :bigint not null, primary key
# avatar_url :string
# email :string default(""), not null # email :string default(""), not null
# encrypted_password :string default(""), not null # encrypted_password :string default(""), not null
# name :string not null # name :string not null
@@ -29,4 +30,10 @@ class User < ApplicationRecord
has_and_belongs_to_many :roles has_and_belongs_to_many :roles
validates :name, presence: true validates :name, presence: true
def self.from_omniauth(email, avatar_url)
@user = User.find_by!(email: email)
@user.update(avatar_url: avatar_url)
@user
end
end end

View File

@@ -0,0 +1,5 @@
class AddAvatarUrlToUser < ActiveRecord::Migration[7.0]
def change
add_column(:users, :avatar_url, :string, null: true)
end
end

3
db/schema.rb generated
View File

@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2022_07_21_133421) do ActiveRecord::Schema[7.0].define(version: 2022_07_22_153417) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -152,6 +152,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_07_21_133421) do
t.string "name", null: false t.string "name", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "avatar_url"
t.index ["email"], name: "index_users_on_email", unique: true t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end end

View File

@@ -10,13 +10,11 @@
"@nivo/core": "^0.79.0", "@nivo/core": "^0.79.0",
"@nivo/pie": "^0.79.1", "@nivo/pie": "^0.79.1",
"@reduxjs/toolkit": "^1.8.3", "@reduxjs/toolkit": "^1.8.3",
"axios": "^0.27.2",
"boring-avatars": "^1.7.0", "boring-avatars": "^1.7.0",
"ckeditor5-mathtype": "^1.0.4", "ckeditor5-mathtype": "^1.0.4",
"esbuild": "^0.14.49", "esbuild": "^0.14.49",
"graphql": "^16.5.0", "graphql": "^16.5.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-avatar-edit": "^1.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.33.1", "react-hook-form": "^7.33.1",
"react-icons": "^4.4.0", "react-icons": "^4.4.0",

View File

@@ -3,6 +3,7 @@
# Table name: users # Table name: users
# #
# id :bigint not null, primary key # id :bigint not null, primary key
# avatar_url :string
# email :string default(""), not null # email :string default(""), not null
# encrypted_password :string default(""), not null # encrypted_password :string default(""), not null
# name :string not null # name :string not null

View File

@@ -3,6 +3,7 @@
# Table name: users # Table name: users
# #
# id :bigint not null, primary key # id :bigint not null, primary key
# avatar_url :string
# email :string default(""), not null # email :string default(""), not null
# encrypted_password :string default(""), not null # encrypted_password :string default(""), not null
# name :string not null # name :string not null

View File

@@ -484,11 +484,6 @@ array-union@^2.1.0:
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
at-least-node@^1.0.0: at-least-node@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
@@ -507,14 +502,6 @@ autoprefixer@^9.4.5, autoprefixer@^9.8.5:
postcss "^7.0.32" postcss "^7.0.32"
postcss-value-parser "^4.1.0" postcss-value-parser "^4.1.0"
axios@^0.27.2:
version "0.27.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
dependencies:
follow-redirects "^1.14.9"
form-data "^4.0.0"
"babel-plugin-styled-components@>= 1.12.0": "babel-plugin-styled-components@>= 1.12.0":
version "2.0.7" version "2.0.7"
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086" resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086"
@@ -541,11 +528,6 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
blueimp-load-image@^5.14.0:
version "5.16.0"
resolved "https://registry.yarnpkg.com/blueimp-load-image/-/blueimp-load-image-5.16.0.tgz#16b763f57e6725f8865517bca8eb7c3dc7d41e09"
integrity sha512-3DUSVdOtlfNRk7moRZuTwDmA3NnG8KIJuLcq3c0J7/BIr6X3Vb/EpX3kUH1joxUhmoVF4uCpDfz7wHkz8pQajA==
boring-avatars@^1.7.0: boring-avatars@^1.7.0:
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/boring-avatars/-/boring-avatars-1.7.0.tgz#70ac7146bbf37d8e69a35544b24f1d75558f868a" resolved "https://registry.yarnpkg.com/boring-avatars/-/boring-avatars-1.7.0.tgz#70ac7146bbf37d8e69a35544b24f1d75558f868a"
@@ -706,13 +688,6 @@ color@^3.1.2:
color-convert "^1.9.3" color-convert "^1.9.3"
color-string "^1.6.0" color-string "^1.6.0"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
commander@^5.0.0: commander@^5.0.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
@@ -853,11 +828,6 @@ defined@^1.0.0:
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ== integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
dependency-graph@^0.9.0: dependency-graph@^0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318"
@@ -1037,11 +1007,6 @@ esprima@^4.0.0:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
exif-js@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/exif-js/-/exif-js-2.3.0.tgz#9d10819bf571f873813e7640241255ab9ce1a814"
integrity sha512-1Og9pAzG2FZRVlaavH8bB8BTeHcjMdJhKmeQITkX+uLRCD0xPtKAdZ2clZmQdJ56p9adXtJ8+jwrGp/4505lYg==
fast-glob@^3.2.9: fast-glob@^3.2.9:
version "3.2.11" version "3.2.11"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
@@ -1075,20 +1040,6 @@ find-up@^4.1.0:
locate-path "^5.0.0" locate-path "^5.0.0"
path-exists "^4.0.0" path-exists "^4.0.0"
follow-redirects@^1.14.9:
version "1.15.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
fs-extra@^8.0.0: fs-extra@^8.0.0:
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
@@ -1372,11 +1323,6 @@ jsonfile@^6.0.1:
optionalDependencies: optionalDependencies:
graceful-fs "^4.1.6" graceful-fs "^4.1.6"
konva@^8.3.5:
version "8.3.10"
resolved "https://registry.yarnpkg.com/konva/-/konva-8.3.10.tgz#66e93815878c2d48f1b6076d5a06b18ec4eb3217"
integrity sha512-5zOynjWBG9wWgpA634SDH+764eyoISpmHLTOCfQ3GFN8OBVd83Genk6H0R4D3hXV0kEGIFAv7RDcSVDtQpPOMw==
locate-path@^5.0.0: locate-path@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
@@ -1416,18 +1362,6 @@ micromatch@^4.0.4:
braces "^3.0.2" braces "^3.0.2"
picomatch "^2.3.1" picomatch "^2.3.1"
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
mini-create-react-context@^0.4.0: mini-create-react-context@^0.4.0:
version "0.4.1" version "0.4.1"
resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e"
@@ -1729,15 +1663,6 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
react-avatar-edit@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/react-avatar-edit/-/react-avatar-edit-1.2.0.tgz#0ac169868367470a59e5a743ba1ee3093e6f343e"
integrity sha512-xTn/hC8KOTFvMagkAiLNq2yWTosCL88ZX34/CTb7dyadGSR27tc56JYBeYcLojTn2y/Hin8azT9aNVvQytAQ/w==
dependencies:
blueimp-load-image "^5.14.0"
exif-js "^2.3.0"
konva "^8.3.5"
react-dom@^18.2.0: react-dom@^18.2.0:
version "18.2.0" version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"