Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const app = express()
app.use(express.json({ extended: true }))

app.use('/api/auth', require('./routes/auth.routes'))
app.use('/api/server', require('./routes/phpserver.routes'))
app.use('/api/notes', require('./routes/notes.routes'))

if (httpsRedirect) app.use(httpToHttps)

Expand Down
261 changes: 195 additions & 66 deletions client/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-markdown": "^6.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-stack-grid": "^0.7.1",
"react-textarea-autosize": "^8.3.3",
Expand Down
54 changes: 0 additions & 54 deletions client/src/App.css
Original file line number Diff line number Diff line change
@@ -1,48 +1,3 @@
.App-logo {
height: 3em;
pointer-events: none;
user-select: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

.card:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

.card {
transition: box-shadow 0.3s;
}

.card-text > h1 {
font-size: 1.625em;
}
.card-text > h2 {
font-size: 1.5em;
}
.card-text > h3 {
font-size: 1.375em;
}
.card-text > h4 {
font-size: 1.25em;
}
.card-text > h5 {
font-size: 1.125em;
}

.lds-dual-ring {
display: inline-block;
height: 1em;
Expand All @@ -68,12 +23,3 @@
transform: rotate(360deg);
}
}

@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap");

.brand {
font-family: "Roboto", sans-serif;
padding-top: 0.2rem !important;
pointer-events: none;
user-select: none;
}
282 changes: 31 additions & 251 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,267 +1,47 @@
import React from 'react';
import logo from './Shared/Logo/logo.svg';
import './App.css';
import CardList from './Cards/CardList'
import AddCard from './Cards/AddCard'
import Context from './context'
import Loader from './Shared/Loader'
import ModalCardEdit from './Cards/ModalCardEdit'
import ModalLogin from './Login/ModalLogin'
import DataService from './Services/DataService'
import Card, { checkCardsArr } from './Cards/cardType/Card'
//import useDebouncedEffect from './Shared/useDebouncedEffect.hook'

const { loadData, postData, updDataServLogin } = DataService()

const brandText = "Notes"

var cardCount = 0

function calcCount(cards) {
let id = cardCount;
[...cards].forEach(element => {
if (Number(element.id) >= id) id = Number(element.id)
});
return id
}

function useCardsArr(defaultValue) {
const [value, setValue] = React.useState(defaultValue)
import './App.css';

function trySetValue(cardsArr) {
if (checkCardsArr(cardsArr) || cardsArr === null) setValue(cardsArr)
else console.error('Массив cardsArr не прошел проверку \n', cardsArr)
}
import Loader from './shared/Loader'

return [value, trySetValue]
}

function useUpdater() {
const [updaterVal, setUpdaterVal] = React.useState(null)
const timer = React.useRef()
if (timer.current) clearTimeout(timer.current)
timer.current = setTimeout(() => {
console.log("Timed update")
setUpdaterVal(Date.now())
}, 60 * 1000) // обновяем через минуту
return [updaterVal]
}
import { BrowserRouter as Router } from 'react-router-dom'
import { useRoutes } from './routes'
import { useAuth } from './hooks/auth.hook'
import { AuthContext } from './context/AuthContext'
import { PageContext } from './context/PageContext'
import Header from './pages/SharedComponents/Header'

function App() {
const [cardsArr, setCards] = useCardsArr(null)
const [editCardId, setEditCardId] = React.useState(null)
const [loading, setLoading] = React.useState({ state: false, res: false })
const { token, login, logout, userId, email, ready } = useAuth()
const isAuthenticated = !!token
const routes = useRoutes(isAuthenticated)

const [openLogin, setOpenLogin] = React.useState(false)
const [logged, setLogged] = React.useState(false)
const [userName, setUserName] = React.useState(undefined)
const [nav, setNav] = React.useState()

const [updaterVal] = useUpdater()

React.useEffect(loadDataFromServer, [logged, userName, updaterVal]) // eslint-disable-line react-hooks/exhaustive-deps
//useDebouncedEffect(loadDataToServer, [cardsArr], 300) // eslint-disable-line react-hooks/exhaustive-deps
React.useEffect(loadDataToServer, [cardsArr]) // eslint-disable-line react-hooks/exhaustive-deps
React.useEffect(clearOldData, [logged, userName]) // eslint-disable-line react-hooks/exhaustive-deps

///////////
function onLogin(login) {
//console.log("onLogin", login)
return new Promise((res, rej) => {
onLogout()
.then(() => {
//console.log("onLogin", login, "onLogout.then")
updDataServLogin(login)
.then(r => {
//console.log("onLogin", login, "onLogout.then", "updDataServLogin.then")
setLogged(Boolean(r))
setUserName(login)
res(r)
})
.catch(e => {
//console.log("onLogin", login, "onLogout.then", "updDataServLogin.catch", e)
rej(e)
})
})
.catch(e => console.log("logout catch in onLogin", e))
})
}

function onLogout() {
//console.log("onLogout")
return new Promise((res) => {
updDataServLogin(null)
.finally(() => {
if (logged) {
//console.log("onLogout - was logged, dislogin")
setUserName(undefined)
setLogged(false)
} else {
//console.log("onLogout - also not logged")
clearOldData()
}
})
.finally(res)
.catch(e => console.log("Data service dislogin failed", e))
})
}

function clearOldData() {
//console.log("clearOldData, logged:", logged)
if (!logged) setCards(null)
}
///////////

///////////
function loadDataToServer() {
try {
let startUsername = userName
if (logged && userName) postData(cardsArr)
.then(res => {
if (!cardsArr) console.log("empty post!")
console.log('[onPostData]', res)
if (startUsername !== userName) {
console.log("упс, несостыковочка с userName");
loadDataToServer()
}
})
.catch(e => console.log(`Data post request error. Response: ${e}`))
}
catch (e) {
console.error(e)
}
}

function loadDataFromServer() {
try {
let startUsername = userName
if (logged && userName) {
setLoading({ state: true, res: loading.res })
loadData()
.then(data => {
console.log('[onLoadData]', 'Данные с сервера загружены')
if (startUsername === userName) setLoadedCards(data)
else console.log("упс, несостыковочка с userName");
setLoading({ state: false, res: true })
})
.catch(e => {
console.log(`Data load request error. Response:`, e)
setLoading({ state: false, res: false })
})
}
}
catch (e) {
setLoading({ state: false, res: false })
console.error(e)
}
}
///////////

///////////
function setLoadedCards(cards) {
setCards([...cards])
cardCount = calcCount(cards)
}

function removeCard(index) {
cardsArr.splice(index, 1)
setCards([...cardsArr])
}

function deleteAll() {
setCards([])
}

function addCard(cardData = {}) {
const newCard = new Card({ id: ++cardCount, name: cardData.name, color: cardData.color, text: cardData.text })
setCards(

(cardsArr != null) ? cardsArr.concat([newCard]) : [newCard]
if (!ready) {
return (
<div className="container display-4 text-center p-3" >
<Loader />
</div>
)
}

function changeCardColor(index, color) {
cardsArr[index].color = color
setCards([...cardsArr])
}

function editCardContent(index, name, text) {
if (cardsArr[index]) {
let card = new Card(cardsArr[index])
card.name = name
card.text = text
cardsArr[index] = card
}
setCards([...cardsArr])
}
///////////

///////////
function getCardByIndex(index) {
return index !== null ? cardsArr[index] : null
}
function setEditCard(index) {
setEditCardId(index)
}
function unsetEditCard() {
setEditCardId(null)
}
///////////

return (
<Context.Provider value={{ removeCard, changeCardColor, setEditCard, unsetEditCard, editCardContent, editCardId }}>
<div className="App pb-3 mb-3">
<header className="p-1">
<nav className="d-flex container px-0 flex-wrap-reverse justify-content-around">
<div className="text-center d-flex p-1 align-items-center justify-content-center flex-wrap">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="h2 m-0 text-dark pr-3 brand">{brandText}</h1>
</div>
<div className="text-center d-flex p-0 align-items-center flex-wrap ml-auto">
{logged &&
<button className="btn btn-light m-1" onClick={loadDataFromServer}>
{loading.state ? <Loader className='px-1' /> : <i className="bi bi-arrow-clockwise px-1"></i>}
<span className='d-xl-inline d-none'>Update</span>
</button>
}
<button className="btn btn-light m-1" onClick={() => setOpenLogin(true)}>
{logged ? <span><i className="bi bi-person"></i> {userName}</span> : <span><i className="bi bi-arrow-right-circle"></i> LOG IN</span>}
</button>
</div>
</nav>
<ModalLogin onLogin={onLogin} onLogout={onLogout} logged={logged} userName={userName} isOpen={openLogin} setOpenState={setOpenLogin} />
</header>

<main className="p-1 pb-3 mb-3">
<AddCard onCreate={addCard} onDeleteAll={deleteAll} />
<ModalCardEdit card={getCardByIndex(editCardId)} index={editCardId} />

{cardsArr && cardsArr.length ? (
<CardList cards={cardsArr} />
) : (loading.state || !loading.res) ? null : logged ? (
<div className="container text-center">
<p className="m-3 p-3 h5 text-muted">No cards. You can add a new one!</p>
</div>
) : (
<div className="container text-center">
<p className="m-3 p-3 h5 text-muted">Unlogged</p>
</div>
)}

{(logged && !loading.state && !loading.res) && (
<div className="container text-center">
<p className="m-3 p-3 h5 text-muted">Data not loaded</p>
</div>
)}

{loading.state &&
<div className="container display-4 text-center p-3" >
<Loader />
</div>
}
</main>
</div>
</Context.Provider>
);
<AuthContext.Provider value={{
token, login, logout, userId, email, isAuthenticated
}}>
<PageContext.Provider value={{setNav}}>
<Router>
<Header>{nav}</Header>
<div className="App pb-3 mb-3">
{routes}
</div>
</Router>
</PageContext.Provider>

</AuthContext.Provider>
)
}

export default App;
Loading