From 73a5c7fae9ffbe9ada721148c8c454a643aceebe Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Sun, 20 Feb 2022 16:11:50 +0100 Subject: chore!: restructure repo I separated public files from the config/dev files. It improves repo readability. I also moved dotenv helper to public/inc directory and extract the Matomo tracker in the same directory. --- .../react-small-apps/apps/notebook/.env.example | 11 ++ .../react-small-apps/apps/notebook/.gitignore | 24 +++ .../react-small-apps/apps/notebook/README.md | 31 ++++ .../react-small-apps/apps/notebook/package.json | 41 +++++ .../apps/notebook/public/favicon.ico | Bin 0 -> 3870 bytes .../apps/notebook/public/index.html | 20 +++ .../apps/notebook/public/manifest.json | 25 +++ .../apps/notebook/public/preview-cover.jpg | Bin 0 -> 32434 bytes .../apps/notebook/public/preview-page.jpg | Bin 0 -> 34118 bytes .../apps/notebook/public/robots.txt | 3 + .../react-small-apps/apps/notebook/src/App.css | 40 +++++ .../react-small-apps/apps/notebook/src/App.js | 174 +++++++++++++++++++++ .../react-small-apps/apps/notebook/src/App.test.js | 8 + .../src/components/commons/Button/Button.css | 78 +++++++++ .../src/components/commons/Button/Button.js | 26 +++ .../components/commons/FormElements/Input/Input.js | 31 ++++ .../commons/FormElements/TextArea/TextArea.js | 52 ++++++ .../src/components/commons/FormElements/index.js | 4 + .../notebook/src/components/commons/List/List.css | 3 + .../notebook/src/components/commons/List/List.js | 25 +++ .../apps/notebook/src/components/commons/index.js | 5 + .../src/components/helpers/hooks/useToggle.js | 10 ++ .../src/components/layout/Footer/Footer.css | 8 + .../src/components/layout/Footer/Footer.js | 11 ++ .../src/components/layout/Header/Header.css | 7 + .../src/components/layout/Header/Header.js | 12 ++ .../notebook/src/components/layout/Main/Main.css | 3 + .../notebook/src/components/layout/Main/Main.js | 7 + .../notebook/src/components/layout/Nav/Nav.css | 65 ++++++++ .../apps/notebook/src/components/layout/Nav/Nav.js | 62 ++++++++ .../notebook/src/components/layout/Nav/NavJump.js | 28 ++++ .../notebook/src/components/layout/Page/Cover.css | 30 ++++ .../notebook/src/components/layout/Page/Page.css | 83 ++++++++++ .../notebook/src/components/layout/Page/Page.js | 107 +++++++++++++ .../src/components/layout/Page/PageToolbar.js | 27 ++++ .../apps/notebook/src/components/layout/index.js | 7 + .../apps/notebook/src/config/pages.js | 16 ++ .../apps/notebook/src/images/restore.svg | 24 +++ .../apps/notebook/src/images/trash.svg | 48 ++++++ .../react-small-apps/apps/notebook/src/index.js | 20 +++ .../react-small-apps/apps/notebook/src/logo.svg | 1 + .../apps/notebook/src/reportWebVitals.js | 13 ++ .../apps/notebook/src/setupTests.js | 5 + 43 files changed, 1195 insertions(+) create mode 100644 public/projects/react-small-apps/apps/notebook/.env.example create mode 100644 public/projects/react-small-apps/apps/notebook/.gitignore create mode 100644 public/projects/react-small-apps/apps/notebook/README.md create mode 100644 public/projects/react-small-apps/apps/notebook/package.json create mode 100644 public/projects/react-small-apps/apps/notebook/public/favicon.ico create mode 100644 public/projects/react-small-apps/apps/notebook/public/index.html create mode 100644 public/projects/react-small-apps/apps/notebook/public/manifest.json create mode 100644 public/projects/react-small-apps/apps/notebook/public/preview-cover.jpg create mode 100644 public/projects/react-small-apps/apps/notebook/public/preview-page.jpg create mode 100644 public/projects/react-small-apps/apps/notebook/public/robots.txt create mode 100644 public/projects/react-small-apps/apps/notebook/src/App.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/App.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/App.test.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/Button/Button.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/Button/Button.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/FormElements/Input/Input.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/FormElements/TextArea/TextArea.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/FormElements/index.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/List/List.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/List/List.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/commons/index.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/helpers/hooks/useToggle.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Footer/Footer.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Footer/Footer.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Header/Header.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Header/Header.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Main/Main.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Main/Main.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Nav/Nav.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Nav/Nav.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Nav/NavJump.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Page/Cover.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Page/Page.css create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Page/Page.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/Page/PageToolbar.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/components/layout/index.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/config/pages.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/images/restore.svg create mode 100644 public/projects/react-small-apps/apps/notebook/src/images/trash.svg create mode 100644 public/projects/react-small-apps/apps/notebook/src/index.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/logo.svg create mode 100644 public/projects/react-small-apps/apps/notebook/src/reportWebVitals.js create mode 100644 public/projects/react-small-apps/apps/notebook/src/setupTests.js (limited to 'public/projects/react-small-apps/apps/notebook') diff --git a/public/projects/react-small-apps/apps/notebook/.env.example b/public/projects/react-small-apps/apps/notebook/.env.example new file mode 100644 index 0000000..1b48ea9 --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/.env.example @@ -0,0 +1,11 @@ +# Create React App config. +# See: https://create-react-app.dev/docs/advanced-configuration/ + +# Development +BROWSER='firefox-developer-edition' +BUILD_PATH='build' +PORT=3000 +HTTPS=false + +# Production +PUBLIC_URL='./' diff --git a/public/projects/react-small-apps/apps/notebook/.gitignore b/public/projects/react-small-apps/apps/notebook/.gitignore new file mode 100644 index 0000000..0732bb1 --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/.gitignore @@ -0,0 +1,24 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local +.vscode + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/public/projects/react-small-apps/apps/notebook/README.md b/public/projects/react-small-apps/apps/notebook/README.md new file mode 100644 index 0000000..06df8dd --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/README.md @@ -0,0 +1,31 @@ +# React Notebook + +A notebook implementation with React. + +## Requirements + +- Yarn + +## How to + +### Start the development version + +`yarn run start` + +### Start the build version: + +1. `yarn run build` +2. (`yarn global add serve`) +3. `serve -s build` + +## Previews + +You can see a live preview here: https://demo.armandphilippot.com/#notebook + +| Cover | Page | +| --- | --- | +| ![Cover preview](./public/preview-cover.jpg) | ![Page preview](./public/preview-page.jpg) | + +## License + +This project is open source and available under the [MIT license](../LICENSE). diff --git a/public/projects/react-small-apps/apps/notebook/package.json b/public/projects/react-small-apps/apps/notebook/package.json new file mode 100644 index 0000000..2d0aa06 --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/package.json @@ -0,0 +1,41 @@ +{ + "name": "react-notebook", + "description": "A notebook implementation with ReactJS.", + "version": "1.0.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^5.16.2", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^13.5.0", + "modern-normalize": "^1.1.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-router-dom": "^6.2.1", + "react-scripts": "5.0.0", + "web-vitals": "^2.1.4" + }, + "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" + ] + } +} diff --git a/public/projects/react-small-apps/apps/notebook/public/favicon.ico b/public/projects/react-small-apps/apps/notebook/public/favicon.ico new file mode 100644 index 0000000..a11777c Binary files /dev/null and b/public/projects/react-small-apps/apps/notebook/public/favicon.ico differ diff --git a/public/projects/react-small-apps/apps/notebook/public/index.html b/public/projects/react-small-apps/apps/notebook/public/index.html new file mode 100644 index 0000000..95386ce --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/public/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + + Notebook + + + +
+ + diff --git a/public/projects/react-small-apps/apps/notebook/public/manifest.json b/public/projects/react-small-apps/apps/notebook/public/manifest.json new file mode 100644 index 0000000..080d6c7 --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/public/manifest.json @@ -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" +} diff --git a/public/projects/react-small-apps/apps/notebook/public/preview-cover.jpg b/public/projects/react-small-apps/apps/notebook/public/preview-cover.jpg new file mode 100644 index 0000000..ef04f6b Binary files /dev/null and b/public/projects/react-small-apps/apps/notebook/public/preview-cover.jpg differ diff --git a/public/projects/react-small-apps/apps/notebook/public/preview-page.jpg b/public/projects/react-small-apps/apps/notebook/public/preview-page.jpg new file mode 100644 index 0000000..ed238f9 Binary files /dev/null and b/public/projects/react-small-apps/apps/notebook/public/preview-page.jpg differ diff --git a/public/projects/react-small-apps/apps/notebook/public/robots.txt b/public/projects/react-small-apps/apps/notebook/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/public/projects/react-small-apps/apps/notebook/src/App.css b/public/projects/react-small-apps/apps/notebook/src/App.css new file mode 100644 index 0000000..76d2aec --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/src/App.css @@ -0,0 +1,40 @@ +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, + Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + font-size: 1rem; + line-height: 1.618; +} + +.app { + display: flex; + flex-flow: column nowrap; + gap: clamp(1rem, 3vw, 2rem); + min-height: 100vh; + width: min(calc(100vw - 2rem), 1000px); + margin: auto; +} + +.notebook { + background: hsl(0, 4%, 20%); + box-shadow: 2px 2px 2px 0 hsl(0, 0%, 13%), 2px 2px 5px 3px hsl(0, 0%, 40%); + display: grid; + grid-template-columns: repeat(2, 1fr); + min-height: 550px; + margin-top: 3rem; + padding: 0.8rem 1.3rem 1.2rem 1.3rem; + position: relative; +} + +@media screen and (max-width: 1024px) { + .notebook { + padding: 0.8rem 1.3rem 1.2rem 0.1rem; + } +} + +.notebook--cover { + padding: 1rem; +} + +a { + color: hsl(212, 46%, 34%); +} diff --git a/public/projects/react-small-apps/apps/notebook/src/App.js b/public/projects/react-small-apps/apps/notebook/src/App.js new file mode 100644 index 0000000..6057342 --- /dev/null +++ b/public/projects/react-small-apps/apps/notebook/src/App.js @@ -0,0 +1,174 @@ +import { Navigate, Route, Routes, useLocation } from "react-router-dom"; +import { Footer, Header, Main, Nav, Page } from "./components/layout"; +import { useCallback, useEffect, useState } from "react"; +import { defaultPages } from "./config/pages"; +import "./App.css"; + +let pageId = 0; + +function App() { + const storedPages = JSON.parse(localStorage.getItem("notebook-pages")); + const initialPages = storedPages || defaultPages; + const [pages, setPages] = useState(initialPages); + const [currentPage, setCurrentPage] = useState({}); + const [deletedPages, setDeletedPages] = useState([]); + const location = useLocation(); + + pageId = storedPages ? storedPages.at(storedPages.length - 1).id : pageId; + + const isCover = () => currentPage && currentPage.id === 0; + const isPageExists = useCallback( + (id) => { + const pageIndex = pages.findIndex((page) => page.id === id); + return pageIndex === -1 ? false : true; + }, + [pages] + ); + + const addNewPage = useCallback(() => { + pageId++; + const newPage = { + id: pageId, + body: "", + title: `Page ${pageId}`, + url: `/page/${pageId}`, + }; + setPages((previous) => [...previous, newPage]); + }, []); + + const removePage = useCallback(() => { + const currentPageId = currentPage.id; + const pagesCopy = pages.slice(0); + const currentPageIndex = pages.findIndex( + (page) => page.id === currentPageId + ); + setDeletedPages((prev) => [...prev, currentPage]); + pagesCopy.splice(currentPageIndex, 1); + const newPages = pagesCopy.map((page) => { + if (page.id <= currentPageId) return page; + const newId = page.id - 1; + const newURL = `/page/${newId}`; + return { ...page, id: newId, url: newURL }; + }); + setCurrentPage(...newPages.filter((page) => page.id === currentPageId)); + setPages(newPages); + pageId = pageId - 1; + }, [pages, currentPage]); + + const restorePage = useCallback(() => { + const deletedPage = deletedPages.pop(); + const pagesCopy = pages.slice(0); + const restoredPageIndex = pagesCopy.findIndex( + (page) => page.id === deletedPage.id + ); + const newPages = pagesCopy.map((page) => { + if (page.id < deletedPage.id) return page; + const newId = page.id + 1; + const newURL = `/page/${newId}`; + return { ...page, id: newId, url: newURL }; + }); + newPages.splice(restoredPageIndex, 0, deletedPage); + setCurrentPage(...newPages.filter((page) => page.id === deletedPage.id)); + setPages(newPages); + }, [pages, deletedPages]); + + useEffect(() => { + !isPageExists(1) && addNewPage(); + }, [isPageExists, addNewPage]); + + useEffect(() => { + const requestedPage = pages.find((page) => page.url === location.pathname); + if (requestedPage) { + setCurrentPage(requestedPage); + } else { + setCurrentPage(() => pages.find((page) => page.url === "/404")); + } + }, [location.pathname, pages]); + + useEffect(() => { + if (currentPage) document.title = `Notebook - ${currentPage.title}`; + }, [currentPage]); + + useEffect(() => { + setPages((prevPages) => { + return prevPages.map((page) => { + if (page.id !== currentPage.id) return page; + return { ...page, body: currentPage.body }; + }); + }); + }, [currentPage.id, currentPage.body]); + + useEffect(() => { + setPages((prevPages) => { + return prevPages.map((page) => { + if (page.id !== currentPage.id) return page; + return { ...page, title: currentPage.title }; + }); + }); + }, [currentPage.id, currentPage.title]); + + useEffect(() => { + localStorage.setItem("notebook-pages", JSON.stringify(pages)); + }, [pages]); + + return ( + <> +
+
+
+
+ + + } + /> + } /> + } /> + + } + /> + + } + path="/404" + /> + } /> + +
+
+