Merge pull request #1 from FranP-code/react-moving

Apply React page to Master
This commit is contained in:
Francisco Pessano
2022-04-25 20:04:36 -03:00
committed by GitHub
42 changed files with 965 additions and 270 deletions

24
.gitignore vendored
View File

@@ -1,5 +1,29 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
node_modules
package-lock.json
.env
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

22
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#3399ff",
"activityBar.activeBorder": "#bf0060",
"activityBar.background": "#3399ff",
"activityBar.foreground": "#15202b",
"activityBar.inactiveForeground": "#15202b99",
"activityBarBadge.background": "#bf0060",
"activityBarBadge.foreground": "#e7e7e7",
"sash.hoverBorder": "#3399ff",
"statusBar.background": "#007fff",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#3399ff",
"statusBarItem.remoteBackground": "#007fff",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#007fff",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#007fff99",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "#007fff"
}

View File

@@ -1,87 +0,0 @@
const Express = require('express')
const app = Express()
const port = (process.env.PORT || 3030)
const axios = require('axios')
require('dotenv').config()
const favicon = require('serve-favicon');
app.use(favicon(__dirname + '/public/favicon.ico'));
const hbs = require('hbs')
hbs.registerPartials(__dirname + '/views/partials')
app.set('view engine', 'hbs')
app.use(Express.static('public'));
app.get('/', (req, res) => {
res.render('index')
})
app.get('/auth', async (req, res) => {
async function requestAccessToken() {
try {
const reqData = {
code: req.query.code,
grant_type: "authorization_code",
redirect_uri: "https://telegram-to-notion.herokuapp.com/auth"
}
const auth = {
Authorization: "Basic " + Buffer.from(`${process.env.NOTION_INTEGRATION_ID}:${process.env.NOTION_INTEGRATION_SECRET}`).toString('base64')
}
console.log(auth)
const response = await axios({
method: "POST",
url: "https://api.notion.com/v1/oauth/token",
data: reqData,
auth: {
username: Buffer.from(process.env.NOTION_INTEGRATION_ID.toString('base64')),
password: Buffer.from(process.env.NOTION_INTEGRATION_SECRET.toString('base64'))
} //THANK YOU https://stackoverflow.com/questions/67534080/notion-api-invalid-client-oauth-integration/68699544#68699544?newreg=949504cf865c4a52b2c0ce7afe936c9b
})
console.log(response.status) //400 in positive case
console.log(response.data)
/**
* access_token: string,
* token_type: string,
* bot_id: string,
* workspace_name: string,
* workspace_icon: string,
* workspace_id: string
*/
return response
}
catch (error) {
console.log("error")
console.log(error)
return {status: 400}
}
}
const response = await requestAccessToken()
res.render('auth', {
name: "fran",
success: response.status === 200 ? true : false,
data: response.data
})
})
app.get('/privacy-policy', (req, res) => {
res.render('privacy-policy')
})
app.get('/terms-of-use', (req, res) => {
res.render('terms-of-use')
})
app.listen(port, () => console.log('port', port))

View File

@@ -1,29 +1,42 @@
{
"name": "telegram-to-notion-website",
"version": "1.0.0",
"description": "Website for the Telegram to Notion Bot",
"main": "index.js",
"scripts": {
"dev": "nodemon index.js",
"start": "node index.js"
},
"keywords": [
"telegram",
"notion",
"bot",
"website"
],
"author": "FranP-Code",
"license": "ISC",
"devDependencies": {
"nodemon": "^2.0.15"
},
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.0.1",
"@testing-library/user-event": "^13.5.0",
"@uiball/loaders": "^1.2.4",
"axios": "^0.26.1",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"hbs": "^4.2.0",
"path": "^0.12.7",
"serve-favicon": "^2.5.0"
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-scripts": "5.0.1",
"styled-components": "^5.3.5",
"web-vitals": "^2.1.4",
"wouter": "^2.8.0-alpha.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

1
public/_redirects Normal file
View File

@@ -0,0 +1 @@
/* /index.html 200

View File

@@ -1,29 +0,0 @@
.request-success {
display: flex;
align-items: center;
background-color: #ffebcd;
padding: 3vh 0px 3vh 2vw;
user-select: all;
-webkit-user-select: all;
}
.request-success code {
overflow-wrap: anywhere;
}
.request-success img {
width: 50px;
margin-right: 3vw;
user-select: none;
}
.request-error {
color: rgb(143, 0, 0)
}

View File

@@ -1,21 +0,0 @@
html, body {
margin: 0;
padding: 0;
}
body {
margin: 0vh 3vw;
font-family: 'Be Vietnam Pro', sans-serif;
}
#beta-banner {
background-color: #F38181;
color: #393E46;
padding: 2vh 0.5vw;
margin: 0px -3vw;
}
#beta-banner p {
margin: 0;
}

View File

@@ -1,26 +0,0 @@
.main {
display: flex;
flex-direction: column;
}
.button {
width: fit-content;
background-color: #4797ff;
color: #fff;
padding: 2vh 5vw;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
}
ul {
margin-top: 5vh;
}
ul li{
font-size: 20pt;
font-weight: bold;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

43
public/index.html Normal file
View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Telegram to Notion Bot</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

25
public/manifest.json Normal file
View File

@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

3
public/robots.txt Normal file
View File

@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@@ -1,20 +0,0 @@
# Telegram to Notion Bot's website
This is the complementary platform to the [Telegram to Notion Bot](https://t.me/TelegrmToNotionBot).
<img src="https://i.ibb.co/2FPm3zk/Screenshot-from-2022-04-12-10-49-53.png">
Right now is on **beta version**, because it haves all the features needed but it needs a little more of styling in the differents pages.
## Link
**[Here](https://telegram-to-notion.herokuapp.com) you can visit it**
## Credits
- Copy icon from [feather](https://feathericons.com)
- Main font is [Be Vietnam Pro](https://fonts.google.com/specimen/Be+Vietnam+Pro)
## Additional
Dont forget to check also the [Telegram to Notion Bot](https://github.com/FranP-code/Telegram-to-Notion-Bot) repository.

27
src/App.jsx Normal file
View File

@@ -0,0 +1,27 @@
import React from 'react'
import {Route} from 'wouter'
//Components
import Header from './components/Header/Header'
//Pages
import About from './Pages/About/About'
import Auth from './Pages/Auth/Auth'
import PrivacyPolicy from './Pages/PrivacyPolicy/PrivacyPolicy'
import TermsOfUse from './Pages/TermsOfUse/TermsOfUse'
import Index from './Pages/Index/Index'
function App() {
return (
<>
<Header />
<Route path="/about" children={<About/>} />
<Route path="/auth" children={<Auth/>} />
<Route path="/privacy-policy" children={<PrivacyPolicy/>} />
<Route path="/terms-of-use" children={<TermsOfUse/>} />
<Route path="/" children={<Index/>} />
</>
);
}
export default App;

50
src/Pages/About/About.jsx Normal file
View File

@@ -0,0 +1,50 @@
import React from 'react'
import styled from 'styled-components'
import { Link } from 'wouter'
const About = () => {
const Style = styled.main`
padding: 0px 3vw;
section {
margin-bottom: 5vh;
}
a {
color: #4d77ff
}
`
return (
<Style>
<section>
<h2>What is this?</h2>
<p>This is a <strong>Telegram Bot</strong> that allow you send text messages and add it to one selected Notion Database. Principally useful for mobile users.</p>
</section>
<section>
<h2>I want to send you feedback, questions or some critic</h2>
<p>You can send it to me to my email: <strong>franpessano1@gmail.com</strong></p>
</section>
<section>
<h2>I want to ignore some database of Notion on the Bot</h2>
<p>For force to the bot to ignore some database, add to it a propierty called <code style={{color: '#fd6565'}}>telegramIgnore</code> of any type.</p>
</section>
<section>
<h2>Is this afiliated with Notion or Telegram?</h2>
<p>Nope, this is not affiliated with Notion or Telegram in any way. This is just a app developed of a fanboy of Telegram and Notion open for the wide world.</p>
</section>
<section>
<h2>Where is the source code?</h2>
<p>On GitHub.</p>
<ul>
<li>Here is for <Link href='https://github.com/FranP-code/Telegram-to-Notion-Bot'>the bot itself</Link></li>
<li>Here is for <Link href='https://github.com/FranP-code/Telegram-to-Notion-Website'>the frontend (this page)</Link></li>
<li>Here is for <Link href='https://github.com/FranP-code/Telegram-to-Notion-Backend'>the backend</Link></li>
</ul>
</section>
</Style>
)
}
export default About

103
src/Pages/Auth/Auth.jsx Normal file
View File

@@ -0,0 +1,103 @@
import React, {useState} from "react"
import axios from 'axios'
import Loading from "../../components/Loading/Loading"
import authImage from './auth_copy.svg'
import './auth-style.css'
import Notification from "../../components/Notification/Notification"
function Auth() {
const [loading, setLoading] = useState(true)
const [permanentCode, setPermanentCode] = useState(false)
const [notification, setNotification] = useState(false)
const getPermanentCode = () => {
const temporalCode = new URLSearchParams(window.location.search).get("code")
if (!temporalCode) {
setPermanentCode("empty")
setLoading(false)
return
}
let requestUrl
if (process.env.REACT_APP_ENV_MODE === "production") {
requestUrl = "http://localhost:5050/api/v1/auth"
} else {
requestUrl = "https://telegram-to-notion-backend.herokuapp.com/api/v1/auth"
}
axios({
method: "POST",
url: requestUrl,
headers: {'Content-Type': 'application/json'},
data: {code: temporalCode}
})
.then(res => {
console.log(res)
setPermanentCode(res ? res.data : null)
})
.catch(err => {
console.log(err.response)
setPermanentCode(false)
})
.finally(() => {
setLoading(false)
})
}
React.useEffect(() => {
getPermanentCode()
}, [])
return (
<div className="auth fullscreen">
{
loading ?
<Loading />
:
<>
{
permanentCode && permanentCode !== "empty" ?
<>
<h2>Copy the following code on Telegram chat</h2>
<div className="success">
<img src={authImage} alt="Copy text" />
<code
className="code-selection"
onClick={() => {
navigator.clipboard.writeText(permanentCode)
setNotification("Text copied to clipboard!")
}}
>
{permanentCode}
</code>
</div>
</>
:
<>
{
permanentCode === "empty" ?
<div className="error">
<h3>There is no temporal code. Please try again later.</h3>
</div>
:
<div className="error">
<h3>There has been an error getting the code. Please try again later.</h3>
</div>
}
</>
}
</>
}
<Notification notification={notification} setNotification={setNotification}/>
</div>
)
}
export default Auth

View File

@@ -0,0 +1,27 @@
.auth {
padding: 1vh 3vw;
}
.auth h2, .auth h3 {
margin-top: 5vh;
}
.auth .success {
display: flex;
align-items: center;
background-color: #ffebcd;
padding: 5vh 2vw;
margin-top: 5vh;
border-radius: 20px;
}
.auth .success img {
width: 75px;
height: 75px;
margin-right: 3vw;
}
.auth .success .code-selection {
-webkit-user-select: all;
-moz-user-select: all;
user-select: all;
overflow-wrap: anywhere;
color: rgb(73, 70, 50);
font-size: 1.2em;
}/*# sourceMappingURL=auth-style.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["auth-style.scss","auth-style.css"],"names":[],"mappings":"AAAA;EACI,gBAAA;ACCJ;ADCI;EACI,eAAA;ACCR;ADEI;EAEI,aAAA;EACA,mBAAA;EAEA,yBAAA;EAEA,gBAAA;EAEA,eAAA;EAEA,mBAAA;ACLR;ADOQ;EACI,WAAA;EACA,YAAA;EAEA,iBAAA;ACNZ;ADSQ;EACI,wBAAA;KAAA,qBAAA;UAAA,gBAAA;EACA,uBAAA;EAEA,sBAAA;EACA,gBAAA;ACRZ","file":"auth-style.css"}

View File

@@ -0,0 +1,37 @@
.auth {
padding: 1vh 3vw;
h2, h3 {
margin-top: 5vh;
}
.success {
display: flex;
align-items: center;
background-color: #ffebcd;
padding: 5vh 2vw;
margin-top: 5vh;
border-radius: 20px;
img {
width: 75px;
height: 75px;
margin-right: 3vw;
}
.code-selection {
user-select: all;
overflow-wrap: anywhere;
color: rgb(73, 70, 50);
font-size: 1.2em;
}
}
}

View File

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 348 B

111
src/Pages/Index/Index.jsx Normal file
View File

@@ -0,0 +1,111 @@
import background from './background.svg'
import styled from "styled-components"
function Index() {
const IndexStyles = styled.div`
height: calc(100vh - 15vh - 1px); //Minus header height and 1 pixel for prevent scrollbar
width: 100%;
display: flex;
flex-direction: column;
aspect-ratio: 960/300;
background-image: url(${background});
background-repeat: no-repeat;
background-position: center;
background-size: cover;
.title-list {
color: #000;
li {
display: flex;
align-items: flex-end;
margin-bottom: 1vh;
a {
width: fit-content;
color: #000;
text-decoration: none;
&:hover h2 {
text-decoration: underline!important;
}
}
h2 {
display: inline-block;
margin: 0;
font-size: 25pt;
}
span {
display: inline-block;
color: #999;
margin-top: 5px;
align-self: center;
}
}
}
.link-to-bot {
width: fit-content;
color: #fff;
background-color: #4797ff;
border-radius: 5px;
margin-top: 3vh;
margin-left: 1vw;
padding: 3vh 6vw;
font-size: 20pt;
font-weight: bold;
text-decoration: none;
transition: 0.4s ease-in-out;
&:hover {
background-color: #0088cc;
transition: 0.4s ease-in-out;
}
}
`
const listData = [
{text: "Free"},
{text: "Open Source", link: "https://github.com/FranP-code/Telegram-to-Notion-Bot"},
{text: "Unlimited"},
{text: "Forever", secondaryText: "(while I can afford it)"}
]
return (
<IndexStyles className="index">
<ul className="title-list">
{
listData.map((obj, index) => (
<li key={index}>
{obj.link ? <a href={obj.link} target="_blank" children={<h2> {obj.text}</h2>} rel="noreferrer"/> : <h2> {obj.text}</h2>}
{obj.secondaryText ? <span>&nbsp;{obj.secondaryText}</span> : null}
</li>
))
}
</ul>
<a className="link-to-bot" href="https://t.me/TelegrmToNotionBot" target="_blank" children="Check it out" rel="noreferrer"/>
</IndexStyles>
)
}
export default Index

View File

@@ -0,0 +1 @@
<svg id="visual" viewBox="0 0 960 540" width="960" height="540" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><path d="M0 446L26.7 449.2C53.3 452.3 106.7 458.7 160 453.8C213.3 449 266.7 433 320 420C373.3 407 426.7 397 480 402.3C533.3 407.7 586.7 428.3 640 431.2C693.3 434 746.7 419 800 414.5C853.3 410 906.7 416 933.3 419L960 422L960 541L933.3 541C906.7 541 853.3 541 800 541C746.7 541 693.3 541 640 541C586.7 541 533.3 541 480 541C426.7 541 373.3 541 320 541C266.7 541 213.3 541 160 541C106.7 541 53.3 541 26.7 541L0 541Z" fill="#4797ff" stroke-linecap="round" stroke-linejoin="miter"></path></svg>

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -1,9 +1,9 @@
{{> global }}
import React from 'react'
<body>
{{> betaBanner }}
<div class="main">
<h1>Privacy Policy</h1>
const PrivacyPolicy = () => {
return (
<div style={{padding: "2vh 3vw"}}>
<h1>Privacy Policy</h1>
<p>Last updated: April 11, 2022</p>
<p>This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You.</p>
<p>We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy. This Privacy Policy has been created with the help of the <a href="https://www.freeprivacypolicy.com/blog/sample-privacy-policy-template/" target="_blank">Privacy Policy Template</a>.</p>
@@ -134,5 +134,8 @@
<ul>
<li>By email: franpessano1@gmail.com</li>
</ul>
</div>
</body>
</div>
)
}
export default PrivacyPolicy

View File

@@ -1,8 +1,8 @@
{{> global cssFile="index"}}
<body>
{{> betaBanner }}
<div class="main">
<h1>Terms and conditions</h1>
const TermsOfUse = () => {
return (
<div style={{padding: "2vh 3vw"}}>
<h1>Terms and conditions</h1>
<p>These terms and conditions (Agreement) set forth the general terms and conditions of your use of the Telegram to Notion Bot mobile application (Mobile Application or Service) and any of its related products and services (collectively, Services). This Agreement is legally binding between you (User, you or your) and this Mobile Application developer (Operator, we, us or our). If you are entering into this agreement on behalf of a business or other legal entity, you represent that you have the authority to bind such entity to this agreement, in which case the terms User, you or your shall refer to such entity. If you do not have such authority, or if you do not agree with the terms of this agreement, you must not accept this agreement and may not access and use the Mobile Application and Services. By accessing and using the Mobile Application and Services, you acknowledge that you have read, understood, and agree to be bound by the terms of this Agreement. You acknowledge that this Agreement is a contract between you and the Operator, even though it is electronic and is not physically signed by you, and it governs your use of the Mobile Application and Services. This terms and conditions policy was created with the help of the <a target="_blank" href="https://www.websitepolicies.com/terms-and-conditions-generator" rel="noopener">terms and conditions generator</a>.</p>
<h2>Accounts and membership</h2>
<p>You must be at least 16 years of age to use the Mobile Application and Services. By using the Mobile Application and Services and by agreeing to this Agreement you warrant and represent that you are at least 16 years of age.</p>
@@ -20,5 +20,8 @@
<p>If you have any questions, concerns, or complaints regarding this Agreement, we encourage you to contact us using the details below:</p>
<p>&#102;r&#97;&#110;&#112;e&#115;s&#97;n&#111;&#49;&#64;g&#109;&#97;&#105;&#108;.&#99;&#111;m</p>
<p>This document was last updated on April 11, 2022</p>
</div>
</body>
</div>
)
}
export default TermsOfUse

View File

@@ -0,0 +1,88 @@
import icon from './icon.png'
import styled from 'styled-components'
import { Link } from 'wouter'
function Header() {
const HeaderStyles = styled.header`
height: 15vh;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0px 2vw;
border-bottom: 1px solid #eee;
user-select: none;
.logotype {
display: flex;
align-items: center;
cursor: pointer;
img {
width: 80px;
height: 80px;
margin-right: 1vw;
&:hover {
animation: rotate-image 0.5s cubic-bezier(1.000, 0.000, 0.000, 1.000) both;
}
}
@keyframes rotate-image {
0% {
transform: rotate(0deg)
}
100% {
transform: rotate(360deg)
}
}
}
.links {
display: flex;
flex-direction: column;
a {
color: #000;
font-weight: bold;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
`
return (
<HeaderStyles>
<Link href='/'>
<div className='logotype'>
<img src={icon} alt="Page icon"></img>
<h1>Telegram to Notion Bot</h1>
</div>
</Link>
<div className="links">
<Link href="/about">
About
</Link>
<Link href="/privacy-policy">
Privacy policy
</Link>
<Link href="/terms-of-use">
Terms of use
</Link>
</div>
</HeaderStyles>
)
}
export default Header

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,31 @@
import React from 'react'
import styled from 'styled-components'
import {DotSpinner} from '@uiball/loaders'
const Loading = () => {
const Styles = styled.div`
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding-bottom: 20vh;
* {
width: 10vw !important;
height: 10vw !important;
}
`
return (
<Styles>
<DotSpinner color="#4797ff"/>
</Styles>
)
}
export default Loading

View File

@@ -0,0 +1,36 @@
import React from 'react'
import './notification-style.css'
const Notification = ({notification, setNotification}) => {
React.useEffect(() => {
if (notification === false) {
return
}
setTimeout(() => {
const elem = document.querySelector("#notification-element")
elem.classList.remove('fade-in')
elem.classList.add('fade-out')
}, 2000)
setTimeout(() => {
setNotification(false)
}, 2400)
}, [notification])
return (
<>
{
notification ?
<div className="notification fade-in" id="notification-element">
<p>{notification}</p>
</div>
: null
}
</>
)
}
export default Notification

View File

@@ -0,0 +1,17 @@
.notification {
width: 15vw;
min-width: 300px;
background-color: rgba(71, 151, 255, 0.1647058824);
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.541);
position: absolute;
top: 80%;
left: 50%;
transform: translate(-50%, 0);
padding: 2vh 3vw;
border-radius: 10px;
}
.notification p {
overflow-wrap: anywhere;
text-align: center;
font-weight: bold;
}/*# sourceMappingURL=notification-style.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["notification-style.scss","notification-style.css"],"names":[],"mappings":"AAAA;EAEI,WAAA;EACA,gBAAA;EAEA,kDAAA;EACA,6CAAA;EAEA,kBAAA;EACA,QAAA;EACA,SAAA;EACA,6BAAA;EAEA,gBAAA;EAEA,mBAAA;ACJJ;ADMI;EACI,uBAAA;EACA,kBAAA;EACA,iBAAA;ACJR","file":"notification-style.css"}

View File

@@ -0,0 +1,25 @@
.notification {
width: 15vw;
min-width: 300px;
background-color: #4797ff2a;
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.541);
position: absolute;
top: 80%;
left: 50%;
transform: translate(-50%, 0);
padding: 2vh 3vw;
border-radius: 10px;
p {
overflow-wrap: anywhere;
text-align: center;
font-weight: bold;
}
}

18
src/index.js Normal file
View File

@@ -0,0 +1,18 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import './styles.css'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// <React.StrictMode> //!WTF React
<App />
// </React.StrictMode> //Thank you: https://stackoverflow.com/a/61091205/18740899
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

13
src/reportWebVitals.js Normal file
View File

@@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

5
src/setupTests.js Normal file
View File

@@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

98
src/styles.css Normal file
View File

@@ -0,0 +1,98 @@
html, body {
margin: 0;
padding: 0;
}
body {
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;700;900&display=swap");
font-family: "Inter", sans-serif;
}
html, body, #root {
height: 100%;
}
#root {
display: flex;
flex-direction: column;
}
.fullscreen {
flex-grow: 1;
}
h1, h2, h3, h4, h5, h6 {
margin: 0;
}
img {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.fade-in {
-webkit-animation: fade-in 0.5s cubic-bezier(0.39, 0.575, 0.565, 1) both;
animation: fade-in 0.5s cubic-bezier(0.39, 0.575, 0.565, 1) both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:26:50
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-in
* ----------------------------------------
*/
@-webkit-keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-out {
-webkit-animation: fade-out 1s ease-out both;
animation: fade-out 1s ease-out both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:27:42
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-out
* ----------------------------------------
*/
@-webkit-keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}/*# sourceMappingURL=styles.css.map */

1
src/styles.css.map Normal file
View File

@@ -0,0 +1 @@
{"version":3,"sources":["styles.scss","styles.css"],"names":[],"mappings":"AAAA;EACI,SAAA;EACA,UAAA;ACCJ;;ADEA;EACY,+FAAA;EACR,gCAAA;ACCJ;;ADEA;EACI,YAAA;ACCJ;;ADEA;EACI,aAAA;EACA,sBAAA;ACCJ;;ADEA;EACI,YAAA;ACCJ;;ADEA;EACI,SAAA;ACCJ;;ADEA;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;ACCJ;;ADIA;EACC,wEAAA;EACG,gEAAA;ACDJ;;ADIA;;;;;mDAAA;AAOA;;;;EAAA;AAKC;EACG;IACE,UAAA;ECFJ;EDIE;IACE,UAAA;ECFJ;AACF;ADIA;EACI;IACI,UAAA;ECFN;EDIE;IACI,UAAA;ECFN;AACF;ADKA;EACC,4CAAA;EACG,oCAAA;ACHJ;;ADKA;;;;;mDAAA;AAOA;;;;EAAA;AAKC;EACG;IACI,UAAA;ECHN;EDKE;IACI,UAAA;ECHN;AACF;ADKI;EACA;IACI,UAAA;ECHN;EDKE;IACI,UAAA;ECHN;AACF","file":"styles.css"}

100
src/styles.scss Normal file
View File

@@ -0,0 +1,100 @@
html, body {
margin: 0;
padding: 0;
}
body {
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;700;900&display=swap');
font-family: 'Inter', sans-serif;
}
html, body, #root {
height: 100%;
}
#root {
display: flex;
flex-direction: column;
}
.fullscreen {
flex-grow: 1;
}
h1, h2, h3, h4, h5, h6 {
margin: 0;
}
img {
user-select: none;
}
//Animations
.fade-in {
-webkit-animation: fade-in 0.5s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
animation: fade-in 0.5s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:26:50
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-in
* ----------------------------------------
*/
@-webkit-keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-out {
-webkit-animation: fade-out 1s ease-out both;
animation: fade-out 1s ease-out both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:27:42
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-out
* ----------------------------------------
*/
@-webkit-keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

View File

@@ -1,19 +0,0 @@
{{> global cssFile="auth"}}
<body>
{{> betaBanner }}
<div>
{{#if success}}
<h2>Copy the following code on the Telegram chat</h2>
<div class="request-success">
<img src="/img/auth_copy.svg" alt="copy">
<code>{{data.access_token}}</code>
</div>
{{else}}
<div class="request-error">
<h2>There has been an error authorizing the app, please try again</h2>
</div>
{{/if}}
</div>
</body>
</html>

View File

@@ -1,14 +0,0 @@
{{> global cssFile="index"}}
<body>
{{> betaBanner }}
<div class="main">
<h1>Telegram to Notion Bot's website</h1>
<a href="https://t.me/TelegrmToNotionBot" class="button">Here you can visit it!</a>
<ul>
<li>100% Free</li>
<li>Unlimited messages</li>
<li>Forever</li>
</ul>
</div>
</body>

View File

@@ -1,3 +0,0 @@
<header id="beta-banner">
<p>This website is on beta version. Futures updates will be to make more <em>aesthetic</em> the website for all users. Thanks for the compression</p>
</header>

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@400;700;900&display=swap" rel="stylesheet">
<title>Telegram to Notion Bot</title>
<link rel="stylesheet" href="/css/global.css">
<link rel="stylesheet" href="/css/{{cssFile}}.css">
</head>