Skip to content

Commit

Permalink
Merge pull request #521 from pankona/separate-access-token
Browse files Browse the repository at this point in the history
Separate access token page from main page
  • Loading branch information
pankona committed May 6, 2022
2 parents 5e59730 + 08e04a1 commit d167194
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 75 deletions.
1 change: 1 addition & 0 deletions hashira-web/.gitignore
@@ -1,3 +1,4 @@
node_modules
public/assets
build
yarn-error.log
1 change: 1 addition & 0 deletions hashira-web/package.json
Expand Up @@ -24,6 +24,7 @@
"ansi-regex": "6.0.1",
"firebase-tools": "^10.8.0",
"prettier": "^2.6.2",
"react-router-dom": "^6.3.0",
"reload": "^3.2.0",
"styled-components": "^5.3.5",
"styled-normalize": "^8.0.7",
Expand Down
83 changes: 83 additions & 0 deletions hashira-web/src/AccessToken.tsx
@@ -0,0 +1,83 @@
import React from "react";
import * as firebase from "./firebase";
import Header from "./Header";
import { useFetchAccessTokens } from "./hooks";

const AccessToken: React.FC<{ user: firebase.User | null | undefined }> = ({
user,
}) => {
const [fetchAccessTokenState, fetchAccessTokens] = useFetchAccessTokens();
const accesstokens = fetchAccessTokenState.data;
const [checkedTokens, setCheckedTokens] = React.useState<{
[key: string]: boolean;
}>({});

React.useEffect(() => {
if (user) {
Promise.all([fetchAccessTokens(user.uid)]).catch((e) => {
console.log("fetch error:", JSON.stringify(e));
});
}
}, [user]);

return (
<div>
<Header user={user} isLoading={!user} />
{user && accesstokens && (
<>
<button
onClick={async () => {
await firebase.claimNewAccessToken(user.uid);
await fetchAccessTokens(user.uid);
}}
>
Generate new access token
</button>
<button
disabled={((): boolean => {
for (const v in checkedTokens) {
if (checkedTokens[v]) {
return false;
}
}
return true;
})()}
onClick={async () => {
const accesstokens: string[] = [];
for (let v in checkedTokens) {
accesstokens.push(v);
}

await firebase.revokeAccessTokens(user.uid, accesstokens);
await fetchAccessTokens(user.uid);
}}
>
Revoke access token
</button>
{accesstokens.map((token: string) => {
return (
<li key={token}>
<input
id={token}
type="checkbox"
checked={checkedTokens[token] || false}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setCheckedTokens({
...checkedTokens,
[e.target.id]: e.target.checked,
});
}}
name={token}
value={token}
/>
{token}
</li>
);
})}
</>
)}
</div>
);
};

export default AccessToken;
73 changes: 6 additions & 67 deletions hashira-web/src/App.tsx
Expand Up @@ -7,36 +7,30 @@ import styled from "styled-components";
import { StyledHorizontalSpacer, StyledVerticalSpacer } from "./styles";
import {
useAddTasks,
useFetchAccessTokens,
useFetchTasksAndPriorities,
useUpdateTasks,
useUpdateTasks2,
useUser,
} from "./hooks";

const StyledBody = styled.div`
padding-left: 8px;
padding-right: 8px;
`;

const App: React.VFC = () => {
const [checkedTokens, setCheckedTokens] = React.useState<{
[key: string]: boolean;
}>({});
const App: React.FC<{ user: firebase.User | null | undefined }> = ({
user,
}) => {
const [checkedTasks, setCheckedTasks] = React.useState<{
[key: string]: boolean;
}>({});
const [mode, setMode] = React.useState<"move" | "select">("select");

const user = useUser();
const [addTasksState, addTasks] = useAddTasks();
const [updateTasksState, updateTasks] = useUpdateTasks();
const [updateTasks2State, updateTasks2] = useUpdateTasks2();
const [fetchAccessTokenState, fetchAccessTokens] = useFetchAccessTokens();
const [fetchTasksAndPrioritiesState, fetchTasksAndPriorities] =
useFetchTasksAndPriorities();

const accesstokens = fetchAccessTokenState.data;
const tasksAndPriorities = fetchTasksAndPrioritiesState.data;
const isLoading =
addTasksState.isLoading ||
Expand Down Expand Up @@ -143,21 +137,15 @@ const App: React.VFC = () => {

React.useEffect(() => {
if (user) {
Promise.all([
fetchAccessTokens(user.uid),
fetchTasksAndPriorities(user.uid),
]).catch((e) => {
Promise.all([fetchTasksAndPriorities(user.uid)]).catch((e) => {
console.log("fetch error:", JSON.stringify(e));
});
}
}, [user]);

return (
<div>
<Header
user={user}
isLoading={!user || !accesstokens || !tasksAndPriorities}
/>
<Header user={user} isLoading={!user || !tasksAndPriorities} />
<StyledBody>
{user !== null && (
<TaskInput
Expand All @@ -171,7 +159,7 @@ const App: React.VFC = () => {
return <></>;
}

if (!user || !accesstokens || !tasksAndPriorities) {
if (!user || !tasksAndPriorities) {
return <div>Loading...</div>;
}

Expand Down Expand Up @@ -282,55 +270,6 @@ const App: React.VFC = () => {
/>
</div>
) : undefined}
<button
onClick={async () => {
await firebase.claimNewAccessToken(user.uid);
await fetchAccessTokens(user.uid);
}}
>
Generate new access token
</button>
<button
disabled={((): boolean => {
for (const v in checkedTokens) {
if (checkedTokens[v]) {
return false;
}
}
return true;
})()}
onClick={async () => {
const accesstokens: string[] = [];
for (let v in checkedTokens) {
accesstokens.push(v);
}

await firebase.revokeAccessTokens(user.uid, accesstokens);
await fetchAccessTokens(user.uid);
}}
>
Revoke access token
</button>
{accesstokens.map((token: string) => {
return (
<li key={token}>
<input
id={token}
type="checkbox"
checked={checkedTokens[token] || false}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setCheckedTokens({
...checkedTokens,
[e.target.id]: e.target.checked,
});
}}
name={token}
value={token}
/>
{token}
</li>
);
})}
</>
);
})()}
Expand Down
29 changes: 24 additions & 5 deletions hashira-web/src/Header.tsx
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { revision } from "./revision";
import * as firebase from "./firebase";
import styled from "styled-components";
import { useNavigate } from "react-router-dom";

const StyledHeader = styled.div`
display: flex;
Expand All @@ -26,16 +27,26 @@ const StyledRevision = styled.div`
const StyledLoginLogout = styled.div`
display: flex;
justify-content: end;
gap: 16px;
`;

const Header: React.VFC<{
const Header: React.FC<{
user: firebase.User | null | undefined;
isLoading: boolean;
}> = ({ user, isLoading }) => {
const navigate = useNavigate();

return (
<StyledHeader>
<div style={{ display: "flex", minWidth: "50%" }}>
<div style={{ minWidth: "fit-content", marginRight: "8px" }}>
<div
style={{
minWidth: "fit-content",
marginRight: "8px",
cursor: "pointer",
}}
onClick={() => navigate("/")}
>
hashira web
</div>
<StyledRevision>{revision()}</StyledRevision>
Expand All @@ -56,9 +67,17 @@ const Header: React.VFC<{
return <div></div>;
}
return (
<div style={{ cursor: "pointer" }} onClick={firebase.logout}>
Logout
</div>
<>
<div
onClick={() => navigate("/accesstokens")}
style={{ cursor: "pointer" }}
>
Access tokens
</div>
<div style={{ cursor: "pointer" }} onClick={firebase.logout}>
Logout
</div>
</>
);
}
})()}
Expand Down
20 changes: 20 additions & 0 deletions hashira-web/src/Router.tsx
@@ -0,0 +1,20 @@
import React from "react";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import AccessToken from "./AccessToken";
import App from "./App";
import { useUser } from "./hooks";

const Router: React.FC = () => {
const user = useUser();
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<App user={user} />} />
<Route path="/accesstokens" element={<AccessToken user={user} />} />
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</BrowserRouter>
);
};

export default Router;
5 changes: 2 additions & 3 deletions hashira-web/src/index.tsx
@@ -1,13 +1,12 @@
import React from "react";
import ReactDOM from "react-dom";
import { Normalize } from "styled-normalize";

import App from "./App";
import Router from "./Router";

const Root = () => (
<React.Fragment>
<Normalize />
<App />
<Router />
</React.Fragment>
);

Expand Down
34 changes: 34 additions & 0 deletions hashira-web/yarn.lock
Expand Up @@ -305,6 +305,13 @@
"@babel/plugin-syntax-jsx" "^7.16.7"
"@babel/types" "^7.17.0"

"@babel/runtime@^7.7.6":
version "7.17.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
dependencies:
regenerator-runtime "^0.13.4"

"@babel/template@^7.16.0":
version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6"
Expand Down Expand Up @@ -3248,6 +3255,13 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"

history@^5.2.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==
dependencies:
"@babel/runtime" "^7.7.6"

hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
Expand Down Expand Up @@ -4781,6 +4795,21 @@ react-refresh@^0.13.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.13.0.tgz#cbd01a4482a177a5da8d44c9755ebb1f26d5a1c1"
integrity sha512-XP8A9BT0CpRBD+NYLLeIhld/RqG9+gktUjW1FkE+Vm7OCinbG1SshcK5tb9ls4kzvjZr9mOQc7HYgBngEyPAXg==

react-router-dom@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d"
integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==
dependencies:
history "^5.2.0"
react-router "6.3.0"

react-router@6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557"
integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==
dependencies:
history "^5.2.0"

react@^18.1.0:
version "18.1.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
Expand Down Expand Up @@ -4841,6 +4870,11 @@ redeyed@~2.1.0:
dependencies:
esprima "~4.0.0"

regenerator-runtime@^0.13.4:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==

registry-auth-token@^4.0.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250"
Expand Down

0 comments on commit d167194

Please sign in to comment.