Commit 00810fbe authored by Gaurav KC's avatar Gaurav KC
Browse files

Add base components

parent 82db5cbb
NODE_PATH=src
\ No newline at end of file
HOST=127.0.0.1
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Custom
.DS_Store
build
# React Blockstack Starter App
This is a foundation for developing Blockstack apps with React,
using the [React-Blockstack](https://www.npmjs.com/package/react-blockstack) library on top of the Blockstack SDK.
It applies Bootstrap for layout and style, but it is trivial to substitute with another framework of your choice (or none at all).
The project is based on [Create React App](https://github.com/facebook/create-react-app),
a starter app for React, where you can find further documentation.
## Available Scripts
First run:
### `npm install`
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.<br>
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.<br>
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
### Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
### Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
### Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
### Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
### `npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
[build]
command = "npm run build"
functions = "functions"
publish = "build"
[[redirects]]
from = "/*"
to = "/index.html 200"
[[redirects]]
from = "/media/*"
to = "/media/:splat"
[[headers]]
for = "/index.html"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Access-Control-Allow-Methods = "POST, GET, OPTIONS, DELETE, PUT"
[[headers]]
for = "/manifest.json"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Access-Control-Allow-Methods = "POST, GET, OPTIONS, DELETE, PUT"
This diff is collapsed.
{
"name": "hello-blockstack",
"version": "0.0.0",
"description": "A simple Blockstack app using ReactJS",
"author": "",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/njordhov/react-blockstack.git"
},
"dependencies": {
"blockstack": "^19.3.0",
"react": "^16.8.6",
"react-blockstack": "^0.6.4",
"react-blockstack-button": "^0.1.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts build",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"bootstrap": "^4.3.1",
"react-test-renderer": "^16.8.6",
"react-scripts": "^3.1.1"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Password Manager</title>
</head>
<body>
<div id="App"></div>
</body>
</html>
{
"name": "REBL One",
"description": "A starter app using React with Blockstack",
"icons": [
{
"src": "favicon.ico",
"sizes": "192x192",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone"
}
[build]
command = "npm run build"
functions = "functions"
publish = "build"
[[redirects]]
from = "/media/*"
to = "/media/:splat"
[[redirects]]
from = "/*"
to = "/index.html 200"
[[headers]]
for = "/index.html"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Access-Control-Allow-Methods = "POST, GET, OPTIONS, DELETE, PUT"
[[headers]]
for = "/manifest.json"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Headers = "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Access-Control-Allow-Methods = "POST, GET, OPTIONS, DELETE, PUT"
<svg width="206" height="40" viewBox="0 0 206 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.493457 3.61699C-1.78808e-07 4.7573 -1.26995e-07 6.21143 1.28989e-10 9.11969L4.75693e-07 19.9993L9.51257e-07 30.879C1.07838e-06 33.7872 1.13245e-06 35.2414 0.493457 36.3817C1.09952 37.7822 2.21647 38.8991 3.61699 39.5052C4.7573 39.9987 6.21143 39.9987 9.11969 39.9987H19.9993H30.879C33.7872 39.9987 35.2414 39.9987 36.3817 39.5052C37.7822 38.8991 38.8991 37.7822 39.5052 36.3817C39.9987 35.2414 39.9987 33.7872 39.9987 30.879V19.9993V9.11969C39.9987 6.21143 39.9987 4.7573 39.5052 3.61699C38.8991 2.21647 37.7822 1.09951 36.3817 0.493455C35.2414 -2.08609e-07 33.7872 -1.26995e-07 30.879 1.29012e-10L19.9993 4.75693e-07L9.11969 9.51258e-07C6.21143 1.07838e-06 4.7573 1.13245e-06 3.61699 0.493456C2.21647 1.09952 1.09952 2.21647 0.493457 3.61699ZM26.3846 17.2316C24.3886 17.2316 22.7701 15.6131 22.7701 13.6166C22.7701 11.6211 24.3886 10.0026 26.3846 10.0026C28.3807 10.0026 29.9992 11.6211 29.9992 13.6166C29.9992 15.6131 28.3807 17.2316 26.3846 17.2316ZM17.2257 13.6162C17.2257 15.6114 15.6079 17.2292 13.6123 17.2292C11.6177 17.2292 9.99991 15.6114 9.99991 13.6162C9.99991 11.621 11.6177 10.0032 13.6123 10.0032C15.6079 10.0032 17.2257 11.621 17.2257 13.6162ZM26.385 22.7812C24.3885 22.7812 22.77 24.3997 22.77 26.3958C22.77 28.3919 24.3885 30.0104 26.385 30.0104C28.3805 30.0104 29.999 28.3919 29.999 26.3958C29.999 24.3997 28.3805 22.7812 26.385 22.7812ZM13.6126 22.7847C15.6078 22.7847 17.2255 24.4025 17.2255 26.3981C17.2255 28.3927 15.6078 30.0104 13.6126 30.0104C11.6174 30.0104 9.99967 28.3927 9.99967 26.3981C9.99967 24.4025 11.6174 22.7847 13.6126 22.7847Z" fill="white"/>
<path d="M63.1229 31.9989C67.9196 31.9989 70.8101 29.5927 70.8101 25.6241C70.8101 22.6242 68.7477 20.4524 65.6853 20.1087V19.9837C67.9352 19.6087 69.7008 17.4681 69.7008 15.0776C69.7008 11.6715 67.0759 9.45279 63.076 9.45279H54.0763V31.9989H63.1229ZM57.5762 12.3121H62.2323C64.7635 12.3121 66.2009 13.4683 66.2009 15.562C66.2009 17.7963 64.5291 19.0462 61.498 19.0462H57.5762V12.3121ZM57.5762 29.1396V21.718H62.2011C65.5134 21.718 67.2321 22.968 67.2321 25.4054C67.2321 27.8428 65.5603 29.1396 62.4042 29.1396H57.5762Z" fill="white"/>
<path d="M73.8644 31.9989H77.2393V9.45279H73.8644V31.9989Z" fill="white"/>
<path d="M88.0902 32.3114C92.7932 32.3114 95.8868 29.0771 95.8868 23.7804C95.8868 18.4994 92.7775 15.2651 88.0902 15.2651C83.4028 15.2651 80.2936 18.4994 80.2936 23.7804C80.2936 29.0771 83.3872 32.3114 88.0902 32.3114ZM88.0902 29.5302C85.4496 29.5302 83.731 27.4366 83.731 23.7804C83.731 20.1399 85.4496 18.0463 88.0902 18.0463C90.7307 18.0463 92.4494 20.1399 92.4494 23.7804C92.4494 27.4366 90.7463 29.5302 88.0902 29.5302Z" fill="white"/>
<path d="M112.925 21.218C112.628 17.9838 110.05 15.2651 105.816 15.2651C101.144 15.2651 98.0817 18.5619 98.0817 23.7804C98.0817 29.0928 101.144 32.3114 105.847 32.3114C109.8 32.3114 112.597 29.9365 112.956 26.4366H109.706C109.316 28.3428 107.956 29.4834 105.878 29.4834C103.253 29.4834 101.519 27.3897 101.519 23.7804C101.519 20.2493 103.238 18.0775 105.847 18.0775C108.05 18.0775 109.363 19.4681 109.706 21.218H112.925Z" fill="white"/>
<path d="M119.198 22.6086H119.167V9.45279H115.792V31.9989H119.167V26.0929L120.573 24.7023L126.151 31.9989H130.073L122.995 22.6398L129.807 15.562H125.838L119.198 22.6086Z" fill="white"/>
<path d="M131.314 20.2181C131.314 22.6086 132.861 24.1086 135.986 24.8273L138.658 25.4523C140.455 25.8585 141.064 26.4835 141.064 27.5459C141.064 28.8896 139.814 29.7334 137.783 29.7334C135.72 29.7334 134.549 28.8896 134.236 27.1709H130.893C131.205 30.2958 133.674 32.3114 137.783 32.3114C141.658 32.3114 144.455 30.249 144.455 27.2491C144.455 24.8741 143.173 23.5617 139.814 22.7805L137.142 22.1711C135.361 21.7649 134.611 21.0618 134.611 20.0306C134.611 18.7181 135.83 17.8275 137.658 17.8275C139.548 17.8275 140.72 18.8275 140.908 20.4212H144.08C143.97 17.39 141.486 15.2651 137.658 15.2651C133.877 15.2651 131.314 17.2807 131.314 20.2181Z" fill="white"/>
<path d="M148.384 11.6715V15.562H145.993V18.2337H148.384V27.6709C148.384 30.8427 149.681 32.1083 153.009 32.1083C153.759 32.1083 154.509 32.0458 154.884 31.952V29.2803C154.665 29.3271 154.118 29.3584 153.774 29.3584C152.399 29.3584 151.774 28.7178 151.774 27.2959V18.2337H154.899V15.562H151.774V11.6715H148.384Z" fill="white"/>
<path d="M163.5 29.6084C161.688 29.6084 160.5 28.6709 160.5 27.2334C160.5 25.8272 161.641 24.9366 163.656 24.796L167.703 24.546V25.8429C167.703 27.9834 165.859 29.6084 163.5 29.6084ZM162.563 32.2802C164.719 32.2802 166.797 31.1239 167.75 29.2959H167.828V31.9989H171.062V20.6712C171.062 17.3744 168.516 15.2651 164.531 15.2651C160.469 15.2651 157.938 17.4525 157.75 20.4212H160.938C161.235 18.9525 162.453 18.015 164.406 18.015C166.469 18.015 167.703 19.1087 167.703 20.9368V22.2024L163.203 22.468C159.297 22.6867 157.094 24.4523 157.094 27.3272C157.094 30.2802 159.344 32.2802 162.563 32.2802Z" fill="white"/>
<path d="M188.772 21.218C188.476 17.9838 185.898 15.2651 181.663 15.2651C176.992 15.2651 173.929 18.5619 173.929 23.7804C173.929 29.0928 176.992 32.3114 181.695 32.3114C185.648 32.3114 188.444 29.9365 188.804 26.4366H185.554C185.163 28.3428 183.804 29.4834 181.726 29.4834C179.101 29.4834 177.367 27.3897 177.367 23.7804C177.367 20.2493 179.085 18.0775 181.695 18.0775C183.898 18.0775 185.21 19.4681 185.554 21.218H188.772Z" fill="white"/>
<path d="M195.045 22.6086H195.014V9.45279H191.639V31.9989H195.014V26.0929L196.42 24.7023L201.998 31.9989H205.92L198.842 22.6398L205.654 15.562H201.686L195.045 22.6086Z" fill="white"/>
</svg>
import React from "react";
import { useBlockstack } from "react-blockstack";
import Content from "./components/Content.js";
import Landing from "./components/Landing.js";
export default function App() {
const { person, signIn } = useBlockstack();
return (
<>
{signIn && <Landing />}
{person && <Content person={person} />}
</>
);
}
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import MainContent from './components/MainContent';
import Dashboard from './components/Dashboard';
import Form from './components/Form';
export default function AppRouter () {
return (
<Switch>
<Route exact path="/" component={Dashboard} />
<Route exact path="/icon" render={(props) => <MainContent {...props} walletPath={'icon'} />} />
<Route exact path="/ethereum" render={(props) => <MainContent {...props} walletPath={'ethereum'} />} />
<Route path="/icon/new" render={(props) => <Form {...props} walletPath={'icon'} />} />
<Route path="/ethereum/new" render={(props) => <Form {...props} walletPath={'ethereum'} />} />
</Switch>
);
};
import React, {useRef} from 'react'
import { useFile, useBlockstack } from 'react-blockstack'
const avatarFallbackImage = 'https://s3.amazonaws.com/onename/avatar-placeholder.png';
function Profile ({ person }) {
return (
<div className="Profile">
<div className="avatar-section text-center">
<img src={ (person && person.avatarUrl()) || avatarFallbackImage }
className="img-rounded avatar" id="avatar-image" alt="Avatar"/>
</div>
<h1 className="text-center mt-2">
Hello, <span id="heading-name">{ (person && person.name()) || 'App Developer' }</span>!
</h1>
</div>
)
}
function NoteField ({title, path, placeholder}) {
const [note, setNote] = useFile(path)
const textfield = useRef()
const spinner = useRef()
const saveAction = () => {
spinner.current.classList.remove('d-none')
setNote(textfield.current.value)
setTimeout(() => spinner.current.classList.add('d-none'), 1500)
}
return(
<div className="NoteField input-group ">
<div className="input-group-prepend">
<span className="input-group-text">{title}</span>
</div>
<input type="text" ref={textfield} className="form-control" disabled={note === undefined}
defaultValue={ note || ""} placeholder={placeholder}
onKeyUp={(e) => {if (e.key === "Enter") saveAction()}}/>
<div className="input-group-append">
<button className="btn btn-outline-secondary" type="button"
disabled={!setNote} onClick={saveAction}>
<div ref={spinner} role="status"
className="d-none spinner-border spinner-border-sm text-info align-text-top mr-2"/>
Save
</button>
</div>
</div>
)
}
export default function Main ({ person }) {
const { signOut } = useBlockstack();
return (
<main className="panel-welcome mt-5">
<div className="row">
<div className="mx-auto col-sm-10 col-md-8 px-4">
<Profile person={person}/>
</div>
</div>
<button
className="btn btn-primary btn-lg"
onClick={ signOut }>
Log Out
</button>
<div className="lead row mt-5">
<div className="mx-auto col col-sm-10 col-md-8 px-4">
<NoteField title="Note" path="note" placeholder="to yourself..."/>
</div>
<div className="card col col-sm-10 col-md-8 mx-auto mt-5 text-center px-0 border-warning">
<div className="card-header">
<h5 className="card-title">Instructions</h5>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">
Type any text in the field above.
</li>
<li class="list-group-item">
Type the <i>Enter</i> key or click the <i>Save</i> button to store the note.
</li>
<li class="list-group-item">Reload the page to confirm that the text is retained.</li>
</ul>
</div>
<div className="alert alert-warning text-center col col-sm-10 col-md-8 mt-3 mx-auto px-5">
<h5>Next Step</h5>
<p>
Log out to get back to the Landing page where
you can deploy your own clone of&nbsp;this&nbsp;app!
</p>
</div>
</div>
</main>
)
}
import React from 'react';
import TopBar from './TopBar.js';
import { BrowserRouter } from 'react-router-dom';
import AppRouter from '../AppRouter.js';
export default function Content ({ person }) {
const avatarUrl = person.avatarUrl() || 'https://s3.amazonaws.com/onename/avatar-placeholder.png';
const name = person.name() || 'User';
return (
<main className="container-fluid">
<div className="row vh-100">
<div className="col-12 col-md-3 col-xl-2 h-100 border">
Sidebar
</div>
<div className="col-12 col-md-9 col-xl-10 border border-left-0">
<TopBar avatarUrl={avatarUrl} name={name} />
<BrowserRouter>
<AppRouter />
</BrowserRouter>
</div>
</div>
</main>
)
}
\ No newline at end of file
import React from 'react';
import Card from 'react-bootstrap/Card';
import { Link } from "react-router-dom";
export default function Dashboard() {
return (
<div className="row py-3">
<Link to='/icon'>
<div className="col-3">
<Card style={{ width: "17rem" }} className="mr-2">
<Card.Body>
<Card.Title>{"ICON"}</Card.Title>
</Card.Body>
</Card>
</div>
</Link>
<Link to='/ethereum'>
<div className="col-3">
<Card style={{ width: "17rem" }} className="mr-2">
<Card.Body>
<Card.Title>{"ETHEREUM"}</Card.Title>
</Card.Body>
</Card>
</div>
</Link>
</div>
);
}
import React, { useRef, useState, useEffect } from "react";
import { useFile } from "react-blockstack";
import { Link } from "react-router-dom";
export default function Form(props) {
const {walletPath} = props;
const [credentials, setCredentials] = useFile(`${walletPath}.json`);
const title = useRef("");
const address = useRef("");
const handleClick = () => {
if (title.current.value.length && address.current.value.length) {
const newCred = {
walletName: title.current.value,
walletAddress: address.current.value
};
const oldCred = credentials ? JSON.parse(credentials) : [];
setCredentials(JSON.stringify([...oldCred, newCred]));
}
};
return (
<>
<div className="row my-3">
<div className="col-12 py-1">
<Link to={`/${walletPath}`}>
<span className="py-2">
<i className="fa fa-arrow-left"></i> Back
</span>
</Link>
<div className="mt-2 font-weight-bold text-uppercase">
{"Create New Credential"}
</div>
</div>
</div>
<div className="row">
<form className="col-12">
<div className="form-group row">
<label htmlFor="inputName" className="col-sm-2 col-form-label">
Wallet Name
</label>
<div className="col-4">
<input
type="text"
ref={title}
className="form-control"
id="inputName"
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="inputAddress" className="col-sm-2 col-form-label">
Wallet Address
</label>
<div className="col-4">
<input
type="text"
className="form-control"
id="inputAddress"
ref={address}
/>
</div>
</div>
<div className="form-group row">
<div className="col-sm-10">
<button
disabled={credentials === undefined}
type="button"
className="btn btn-primary"
onClick={handleClick}
>
Save
</button>
</div>
</div>
</form>
</div>
</>
);
}
import React from "react";
import { BlockstackButton } from "react-blockstack-button";
import { useBlockstack } from "react-blockstack";
export default function Landing() {
const { signIn } = useBlockstack();
return (
<>
<nav class="navbar fixed-top navbar-dark bg-dark text-light">
<a class="navbar-brand" href="/" href="#">
Home
</a>
</nav>
<div className="Landing vh-100 d-flex align-items-center">
<div className="container">
<div className="panel-landing text-center py-5">
<h1 className="landing-heading">Password Manager</h1>
<p className="lead">
Secure your crypto wallets and credentials with decentralised
technology
</p>
<BlockstackButton variant={'light'} onClick={signIn} />
</div>
</div>
</div>
</>
);
}
import React from "react";
import Card from "react-bootstrap/Card";
import { useFile } from "react-blockstack";
import { Link } from "react-router-dom";
export default function MainContent(props) {
const componentPath = props.match.path;
const {walletPath} = props;
const [credentials, setCredentials] = useFile(`${walletPath}.json`);
const handleDelete = () => {
setCredentials(null);
}
return (
<>
<div className="row mt-3">
<div className="col-12 py-1">
<Link to="/">
<span className="py-2">
<i className="fa fa-arrow-left"></i> Back
</span>
</Link>
<div className="mt-3 font-weight-bold text-uppercase">{`${walletPath} Wallets`}</div>
</div>
</div>
{credentials === undefined ? (
<div className="mt-3">Loading..</div>
) : (
<>
<div className="row mt-3">