use devise instead auth0
This commit is contained in:
@@ -12,5 +12,6 @@
|
||||
// Turbolinks.start()
|
||||
// ActiveStorage.start()
|
||||
|
||||
import "regenerator-runtime";
|
||||
import "stylesheets/application";
|
||||
import "regenerator-runtime";
|
||||
import "../src/index";
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
import "../src/index";
|
||||
@@ -1,15 +1,21 @@
|
||||
import type { Variables, RequestParameters, CacheConfig } from "relay-runtime";
|
||||
import { Environment, Network, RecordSource, Store } from "relay-runtime";
|
||||
|
||||
async function fetchRelay(
|
||||
export const fetchRelay = async (
|
||||
params: RequestParameters,
|
||||
variables: Variables,
|
||||
_cacheConfig: CacheConfig
|
||||
) {
|
||||
) => {
|
||||
const csrfToken =
|
||||
document
|
||||
.querySelector('meta[name="csrf-token"]')
|
||||
?.getAttribute("content") ?? "";
|
||||
|
||||
const response = await fetch("/graphql", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRF-Token": csrfToken,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: params.text,
|
||||
@@ -30,7 +36,7 @@ async function fetchRelay(
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
export const environment = new Environment({
|
||||
network: Network.create(fetchRelay),
|
||||
|
||||
@@ -1,33 +1,37 @@
|
||||
import { graphql } from "babel-plugin-relay/macro";
|
||||
import type { FC } from "react";
|
||||
import React, { Suspense } from "react";
|
||||
import { RelayEnvironmentProvider } from "react-relay";
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
import React from "react";
|
||||
import { useLazyLoadQuery } from "react-relay";
|
||||
|
||||
import { environment } from "../relay/environment";
|
||||
import { Navbar } from "./components/Navbar";
|
||||
import { SideNav } from "./components/SideNav";
|
||||
import { AppContext } from "./contexts/AppContext";
|
||||
import { AuthProvider } from "./contexts/AuthProvider";
|
||||
import { Navbar, SideNav } from "./components";
|
||||
import { AppProvider } from "./contexts/AppProvider";
|
||||
import { UserProvider } from "./contexts/UserProvider";
|
||||
import { Routes } from "./Routes";
|
||||
import type { AppQuery } from "./__generated__/AppQuery.graphql";
|
||||
|
||||
export const App: FC = () => {
|
||||
const { currentUser } = useLazyLoadQuery<AppQuery>(
|
||||
graphql`
|
||||
query AppQuery {
|
||||
currentUser {
|
||||
firstName
|
||||
}
|
||||
}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
|
||||
return (
|
||||
<RelayEnvironmentProvider environment={environment}>
|
||||
<Suspense fallback="Carregando...">
|
||||
<Router>
|
||||
<AuthProvider>
|
||||
<AppContext>
|
||||
<main className="min-h-screen w-full bg-gray-50 flex flex-col">
|
||||
<Navbar />
|
||||
<div className="flex flex-grow">
|
||||
<SideNav />
|
||||
<Routes />
|
||||
</div>
|
||||
</main>
|
||||
</AppContext>
|
||||
</AuthProvider>
|
||||
</Router>
|
||||
</Suspense>
|
||||
</RelayEnvironmentProvider>
|
||||
<AppProvider>
|
||||
<UserProvider user={currentUser}>
|
||||
<main className="min-h-screen w-full bg-gray-50 flex flex-col">
|
||||
<Navbar />
|
||||
<div className="flex flex-grow">
|
||||
<SideNav />
|
||||
<Routes />
|
||||
</div>
|
||||
</main>
|
||||
</UserProvider>
|
||||
</AppProvider>
|
||||
);
|
||||
};
|
||||
|
||||
97
app/javascript/src/__generated__/AppQuery.graphql.ts
generated
Normal file
97
app/javascript/src/__generated__/AppQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,97 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from "relay-runtime";
|
||||
export type AppQueryVariables = {};
|
||||
export type AppQueryResponse = {
|
||||
readonly currentUser: {
|
||||
readonly firstName: string;
|
||||
} | null;
|
||||
};
|
||||
export type AppQuery = {
|
||||
readonly response: AppQueryResponse;
|
||||
readonly variables: AppQueryVariables;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
query AppQuery {
|
||||
currentUser {
|
||||
firstName
|
||||
id
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "firstName",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "AppQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "User",
|
||||
"kind": "LinkedField",
|
||||
"name": "currentUser",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Operation",
|
||||
"name": "AppQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "User",
|
||||
"kind": "LinkedField",
|
||||
"name": "currentUser",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "ecf2bf1a08ead5c3e2edb202242ed8cf",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "AppQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query AppQuery {\n currentUser {\n firstName\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
(node as any).hash = 'ea65c9caf86d93b8ddded2ae3eaa7b0e';
|
||||
export default node;
|
||||
@@ -1,63 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { useAuth0 } from "@auth0/auth0-react";
|
||||
|
||||
import XStakeLogo from "../images/logo.png";
|
||||
import { useAppContext } from "../contexts/AppContext";
|
||||
|
||||
export const Navbar = () => {
|
||||
const { setSideNavExpanded } = useAppContext();
|
||||
|
||||
const handleExpandSideNav = () => {
|
||||
setSideNavExpanded((prevState) => !prevState);
|
||||
};
|
||||
|
||||
const { loginWithRedirect, logout, isAuthenticated } = useAuth0();
|
||||
|
||||
return (
|
||||
<nav className="fixed w-full h-16 flex bg-white shadow items-center px-4 space-x-2 z-50">
|
||||
<button
|
||||
className="w-10 h-10 xl:hidden"
|
||||
onClick={() => handleExpandSideNav()}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-full w-full"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<img
|
||||
src={XStakeLogo}
|
||||
alt="XStake Logo"
|
||||
width={64}
|
||||
placeholder="blurred"
|
||||
/>
|
||||
<h1 className="text-2xl font-bold">XStake</h1>
|
||||
<div className="w-full h-full flex items-center justify-end">
|
||||
{isAuthenticated ? (
|
||||
<button
|
||||
className="cursor-pointer hover:bg-gray-100 h-full px-4 font-bold"
|
||||
onClick={() => logout({ returnTo: window.location.origin })}
|
||||
>
|
||||
Sair
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="cursor-pointer hover:bg-gray-100 h-full px-4 font-bold"
|
||||
onClick={loginWithRedirect}
|
||||
>
|
||||
Entrar
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
75
app/javascript/src/components/Navbar/Navbar.tsx
Normal file
75
app/javascript/src/components/Navbar/Navbar.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import * as React from "react";
|
||||
|
||||
import XStakeLogo from "../../images/logo.png";
|
||||
import { useApp } from "../../contexts/AppProvider";
|
||||
import { useCurrentUser } from "../../contexts/UserProvider";
|
||||
|
||||
const linkStyles =
|
||||
"cursor-pointer hover:bg-gray-100 h-full px-4 font-bold flex items-center";
|
||||
|
||||
export const Navbar = () => {
|
||||
const { setSideNavExpanded } = useApp();
|
||||
const handleExpandSideNav = () => {
|
||||
setSideNavExpanded((prevState) => !prevState);
|
||||
};
|
||||
|
||||
const { isAuthenticated } = useCurrentUser();
|
||||
|
||||
const csrfToken =
|
||||
document
|
||||
.querySelector('meta[name="csrf-token"]')
|
||||
?.getAttribute("content") ?? "";
|
||||
|
||||
return (
|
||||
<nav className="fixed w-full h-16 flex bg-white shadow items-center px-4 space-x-2 z-50">
|
||||
<button
|
||||
className="w-10 h-10 xl:hidden"
|
||||
onClick={() => handleExpandSideNav()}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-full w-full"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<img
|
||||
src={XStakeLogo}
|
||||
alt="XStake Logo"
|
||||
width={64}
|
||||
placeholder="blurred"
|
||||
/>
|
||||
<h1 className="text-2xl font-bold">XStake</h1>
|
||||
<div className="w-full h-full flex items-center justify-end">
|
||||
{isAuthenticated ? (
|
||||
<form className="h-full" method="post" action="/users/sign_out">
|
||||
<input className={linkStyles} type="submit" value="Sair" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
defaultValue={csrfToken}
|
||||
/>
|
||||
<input type="hidden" name="_method" value="delete" />
|
||||
</form>
|
||||
) : (
|
||||
<form className="h-full" method="post" action="/users/sign_in">
|
||||
<input className={linkStyles} type="submit" value="Entrar" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="authenticity_token"
|
||||
defaultValue={csrfToken}
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
1
app/javascript/src/components/Navbar/index.ts
Normal file
1
app/javascript/src/components/Navbar/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./Navbar";
|
||||
@@ -2,7 +2,7 @@ import * as React from "react";
|
||||
import cx from "classnames";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { useAppContext } from "../contexts/AppContext";
|
||||
import { useApp } from "../contexts/AppProvider";
|
||||
|
||||
type MenuItem = {
|
||||
label: string;
|
||||
@@ -25,7 +25,7 @@ const MenuItems: MenuItem[] = [
|
||||
];
|
||||
|
||||
export const SideNav = () => {
|
||||
const { sideNavExpanded, setSideNavExpanded } = useAppContext();
|
||||
const { sideNavExpanded, setSideNavExpanded } = useApp();
|
||||
|
||||
const handleCloseSideNav = () => {
|
||||
setSideNavExpanded(false);
|
||||
|
||||
2
app/javascript/src/components/index.ts
Normal file
2
app/javascript/src/components/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./Navbar";
|
||||
export * from "./SideNav";
|
||||
@@ -8,7 +8,7 @@ export type AppContext = {
|
||||
|
||||
const Context = createContext<AppContext | null>(null);
|
||||
|
||||
export const useAppContext = (): AppContext => {
|
||||
export const useApp = (): AppContext => {
|
||||
const context = useContext(Context);
|
||||
|
||||
if (context === null) {
|
||||
@@ -18,7 +18,7 @@ export const useAppContext = (): AppContext => {
|
||||
return context;
|
||||
};
|
||||
|
||||
export const AppContext: FC = ({ children }) => {
|
||||
export const AppProvider: FC = ({ children }) => {
|
||||
const [sideNavExpanded, setSideNavExpanded] = useState(false);
|
||||
|
||||
return (
|
||||
@@ -1,24 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { Auth0Provider } from "@auth0/auth0-react";
|
||||
import type { FC } from "react";
|
||||
import React from "react";
|
||||
|
||||
export const AuthProvider: FC = ({ children }) => {
|
||||
// @ts-ignore
|
||||
const domain = window.AUTH_DOMAIN;
|
||||
// @ts-ignore
|
||||
const clientId = window.AUTH_CLIENT_ID;
|
||||
// @ts-ignore
|
||||
const audience = window.AUTH_AUDIENCE;
|
||||
|
||||
return (
|
||||
<Auth0Provider
|
||||
domain={domain}
|
||||
clientId={clientId}
|
||||
audience={audience}
|
||||
redirectUri={window.location.origin}
|
||||
>
|
||||
{children}
|
||||
</Auth0Provider>
|
||||
);
|
||||
};
|
||||
32
app/javascript/src/contexts/UserProvider.tsx
Normal file
32
app/javascript/src/contexts/UserProvider.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { FC } from "react";
|
||||
import React, { createContext, useContext } from "react";
|
||||
|
||||
type CurrentUserContext = {
|
||||
user: {
|
||||
readonly firstName: string;
|
||||
} | null;
|
||||
isAuthenticated: boolean;
|
||||
};
|
||||
|
||||
const Context = createContext<CurrentUserContext>({
|
||||
user: null,
|
||||
isAuthenticated: false,
|
||||
});
|
||||
|
||||
export const useCurrentUser = (): CurrentUserContext => {
|
||||
const context = useContext(Context);
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
user: {
|
||||
readonly firstName: string;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const UserProvider: FC<Props> = ({ user, children }) => (
|
||||
<Context.Provider value={{ user, isAuthenticated: !!user }}>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
);
|
||||
@@ -1,12 +1,21 @@
|
||||
import React from "react";
|
||||
import React, { Suspense } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { RelayEnvironmentProvider } from "react-relay";
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
|
||||
import { environment } from "../relay/environment";
|
||||
import { App } from "./App";
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<RelayEnvironmentProvider environment={environment}>
|
||||
<Suspense fallback="Carregando...">
|
||||
<Router>
|
||||
<App />
|
||||
</Router>
|
||||
</Suspense>
|
||||
</RelayEnvironmentProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user