From 5757d76c8cbd7a59793c46335d510b6a3932e818 Mon Sep 17 00:00:00 2001 From: d_yanis Date: Wed, 25 Oct 2023 15:07:10 +0200 Subject: [PATCH 01/12] setup ts-react --- .gitignore | 28 ++++++++++++++++++++++++++ Documentation/data.puml | 2 +- package.json | 43 ++++++++++++++++++++++++++++++++++++++++ public/favicon.ico | Bin 0 -> 3870 bytes public/index.html | 43 ++++++++++++++++++++++++++++++++++++++++ public/logo192.png | Bin 0 -> 5347 bytes public/logo512.png | Bin 0 -> 9664 bytes public/manifest.json | 25 +++++++++++++++++++++++ public/robots.txt | 3 +++ src/App.css | 38 +++++++++++++++++++++++++++++++++++ src/App.test.tsx | 9 +++++++++ src/App.tsx | 26 ++++++++++++++++++++++++ src/index.css | 13 ++++++++++++ src/index.tsx | 19 ++++++++++++++++++ src/logo.svg | 1 + src/react-app-env.d.ts | 1 + src/reportWebVitals.ts | 15 ++++++++++++++ src/setupTests.ts | 5 +++++ tsconfig.json | 26 ++++++++++++++++++++++++ 19 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 public/index.html create mode 100644 public/logo192.png create mode 100644 public/logo512.png create mode 100644 public/manifest.json create mode 100644 public/robots.txt create mode 100644 src/App.css create mode 100644 src/App.test.tsx create mode 100644 src/App.tsx create mode 100644 src/index.css create mode 100644 src/index.tsx create mode 100644 src/logo.svg create mode 100644 src/react-app-env.d.ts create mode 100644 src/reportWebVitals.ts create mode 100644 src/setupTests.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 463794e..0068e2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,32 @@ .idea +.vs +.code vendor composer.lock *.phar + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +package-lock.json + +# 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* +>>>>>>> 85d7cd8 (setup ts-react) diff --git a/Documentation/data.puml b/Documentation/data.puml index 90a7929..0ad5135 100755 --- a/Documentation/data.puml +++ b/Documentation/data.puml @@ -68,4 +68,4 @@ class Color { + getValue(): int } -@enduml +@enduml \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..fd6d84a --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "iqball_web", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "@types/jest": "^27.5.2", + "@types/node": "^16.18.59", + "@types/react": "^18.2.31", + "@types/react-dom": "^18.2.14", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1", + "typescript": "^4.9.5", + "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/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..aa069f2 --- /dev/null +++ b/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/public/logo192.png b/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..fc44b0a3796c0e0a64c3d858ca038bd4570465d9 GIT binary patch literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..080d6c7 --- /dev/null +++ b/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/robots.txt b/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..74b5e05 --- /dev/null +++ b/src/App.css @@ -0,0 +1,38 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/App.test.tsx b/src/App.test.tsx new file mode 100644 index 0000000..2a68616 --- /dev/null +++ b/src/App.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..30e8f48 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import logo from './logo.svg'; +import './App.css'; + +function App() { + return ( + + ); +} + +export default App; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..ec2585e --- /dev/null +++ b/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..032464f --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement +); +root.render( + + + +); + +// 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(); diff --git a/src/logo.svg b/src/logo.svg new file mode 100644 index 0000000..9dfc1c0 --- /dev/null +++ b/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts new file mode 100644 index 0000000..6431bc5 --- /dev/null +++ b/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts new file mode 100644 index 0000000..49a2a16 --- /dev/null +++ b/src/reportWebVitals.ts @@ -0,0 +1,15 @@ +import { ReportHandler } from 'web-vitals'; + +const reportWebVitals = (onPerfEntry?: ReportHandler) => { + 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; diff --git a/src/setupTests.ts b/src/setupTests.ts new file mode 100644 index 0000000..8f2609b --- /dev/null +++ b/src/setupTests.ts @@ -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'; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a273b0c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ] +} From ca5b525f22a4ec2663aed1b43454fd40c6f71677 Mon Sep 17 00:00:00 2001 From: Override-6 Date: Thu, 26 Oct 2023 00:35:37 +0200 Subject: [PATCH 02/12] setup PHP with ReactJS development --- config.php | 0 {src => front}/App.css | 0 {src => front}/App.test.tsx | 0 {src => front}/App.tsx | 0 {src => front}/index.css | 0 {public => front}/index.html | 16 +++++++++++----- {src => front}/index.tsx | 0 {src => front}/logo.svg | 0 {src => front}/react-app-env.d.ts | 0 {src => front}/reportWebVitals.ts | 0 {src => front}/setupTests.ts | 0 public/front | 1 + index.php => public/index.php | 4 ++-- src/View/hello.html | 16 ---------------- src/View/hello.php | 21 +++++++++++++++++++++ vite.config.ts | 0 16 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 config.php rename {src => front}/App.css (100%) rename {src => front}/App.test.tsx (100%) rename {src => front}/App.tsx (100%) rename {src => front}/index.css (100%) rename {public => front}/index.html (80%) rename {src => front}/index.tsx (100%) rename {src => front}/logo.svg (100%) rename {src => front}/react-app-env.d.ts (100%) rename {src => front}/reportWebVitals.ts (100%) rename {src => front}/setupTests.ts (100%) create mode 120000 public/front rename index.php => public/index.php (88%) delete mode 100755 src/View/hello.html create mode 100755 src/View/hello.php create mode 100644 vite.config.ts diff --git a/config.php b/config.php new file mode 100644 index 0000000..e69de29 diff --git a/src/App.css b/front/App.css similarity index 100% rename from src/App.css rename to front/App.css diff --git a/src/App.test.tsx b/front/App.test.tsx similarity index 100% rename from src/App.test.tsx rename to front/App.test.tsx diff --git a/src/App.tsx b/front/App.tsx similarity index 100% rename from src/App.tsx rename to front/App.tsx diff --git a/src/index.css b/front/index.css similarity index 100% rename from src/index.css rename to front/index.css diff --git a/public/index.html b/front/index.html similarity index 80% rename from public/index.html rename to front/index.html index aa069f2..d988be7 100644 --- a/public/index.html +++ b/front/index.html @@ -1,30 +1,33 @@ + + + - + - + - React App + @@ -39,5 +42,8 @@ To begin the development, run `npm start` or `yarn start`. To create a production bundle, use `npm run build` or `yarn build`. --> + + + diff --git a/src/index.tsx b/front/index.tsx similarity index 100% rename from src/index.tsx rename to front/index.tsx diff --git a/src/logo.svg b/front/logo.svg similarity index 100% rename from src/logo.svg rename to front/logo.svg diff --git a/src/react-app-env.d.ts b/front/react-app-env.d.ts similarity index 100% rename from src/react-app-env.d.ts rename to front/react-app-env.d.ts diff --git a/src/reportWebVitals.ts b/front/reportWebVitals.ts similarity index 100% rename from src/reportWebVitals.ts rename to front/reportWebVitals.ts diff --git a/src/setupTests.ts b/front/setupTests.ts similarity index 100% rename from src/setupTests.ts rename to front/setupTests.ts diff --git a/public/front b/public/front new file mode 120000 index 0000000..c1394c9 --- /dev/null +++ b/public/front @@ -0,0 +1 @@ +../front \ No newline at end of file diff --git a/index.php b/public/index.php similarity index 88% rename from index.php rename to public/index.php index 0fbd9f7..7ced5a3 100644 --- a/index.php +++ b/public/index.php @@ -1,7 +1,7 @@ - - - - - - Document - - - -

Hello

-

World

- - - \ No newline at end of file diff --git a/src/View/hello.php b/src/View/hello.php new file mode 100755 index 0000000..ca381bf --- /dev/null +++ b/src/View/hello.php @@ -0,0 +1,21 @@ + + + + + + + + + Document + + + + + \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..e69de29 From 44e7556cbdc9d8d8dd52a069bfd32a9b835306aa Mon Sep 17 00:00:00 2001 From: Override-6 Date: Thu, 26 Oct 2023 00:40:08 +0200 Subject: [PATCH 03/12] setup drone and continuous deployment on maxou.dev --- .gitignore | 4 +- Documentation/react-php-integration.md | 28 ++++++++++ ci/.drone.yml | 47 +++++++++++++++++ ci/build_react.msh | 31 +++++++++++ composer.json | 4 +- config.php | 22 ++++++++ front/App.css | 38 -------------- front/App.test.tsx | 9 ---- front/App.tsx | 26 ---------- {public => front/assets}/favicon.ico | Bin front/{ => assets}/logo.svg | 0 {public => front/assets}/logo192.png | Bin {public => front/assets}/logo512.png | Bin front/index.css | 13 ----- front/index.html | 49 ------------------ front/index.tsx | 19 ------- front/react-app-env.d.ts | 1 - front/reportWebVitals.ts | 15 ------ front/setupTests.ts | 5 -- front/views/DisplayResults.tsx | 24 +++++++++ front/views/SampleForm.tsx | 30 +++++++++++ package.json | 12 +++-- profiles/dev-config-profile.php | 8 +++ profiles/prod-config-profile.php | 9 ++++ public/front | 1 - public/index.php | 20 +++++-- public/manifest.json | 25 --------- public/robots.txt | 3 -- src/Controller/HelloPageController.php | 10 ---- src/Controller/SampleFormController.php | 15 ++++++ .../hello.php => react-display-file.php} | 14 +++-- src/react-display.php | 12 +++++ tsconfig.json | 2 +- vite.config.ts | 38 ++++++++++++++ 34 files changed, 303 insertions(+), 231 deletions(-) create mode 100644 Documentation/react-php-integration.md create mode 100644 ci/.drone.yml create mode 100755 ci/build_react.msh delete mode 100644 front/App.css delete mode 100644 front/App.test.tsx delete mode 100644 front/App.tsx rename {public => front/assets}/favicon.ico (100%) rename front/{ => assets}/logo.svg (100%) rename {public => front/assets}/logo192.png (100%) rename {public => front/assets}/logo512.png (100%) delete mode 100644 front/index.css delete mode 100644 front/index.html delete mode 100644 front/index.tsx delete mode 100644 front/react-app-env.d.ts delete mode 100644 front/reportWebVitals.ts delete mode 100644 front/setupTests.ts create mode 100644 front/views/DisplayResults.tsx create mode 100644 front/views/SampleForm.tsx create mode 100644 profiles/dev-config-profile.php create mode 100644 profiles/prod-config-profile.php delete mode 120000 public/front delete mode 100644 public/manifest.json delete mode 100644 public/robots.txt delete mode 100755 src/Controller/HelloPageController.php create mode 100644 src/Controller/SampleFormController.php rename src/{View/hello.php => react-display-file.php} (60%) create mode 100644 src/react-display.php diff --git a/.gitignore b/.gitignore index 0068e2c..b4c3368 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ vendor composer.lock *.phar +/dist + +views-mappings.php # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. @@ -29,4 +32,3 @@ package-lock.json npm-debug.log* yarn-debug.log* yarn-error.log* ->>>>>>> 85d7cd8 (setup ts-react) diff --git a/Documentation/react-php-integration.md b/Documentation/react-php-integration.md new file mode 100644 index 0000000..0c06574 --- /dev/null +++ b/Documentation/react-php-integration.md @@ -0,0 +1,28 @@ +# How is react used with php +This document explains how we use react and php together, +and how to create a react component that can be sent to the front end from php. + +## Folder tree of the project +```tree +. +├── ci // CI/CD related directory. +├── Documentation // Documentation directory. +├── front // React code goes here. +│ ├── views // React views goes here. +│ └── assets -> // assets goes here (images, svg etc) +├── profiles // PHP server environment profiles. +├── public // index.php goes here +└── src // php code goes here + ├── Controller + ├── Data + └── ... +``` + +we'll take a view later on each folder. + +## Compilation Constraint +We use typescript and react for the front, which requires to be transpiled to Javascript in order to be executed by browsers. +The fact that our `.tsx` components (our views) needs to be compiled to a js file to be executed does not allows us to dumbly refer to their file path in the php source code. + +## Use of ViteJS to build our react components +We use [ViteJS](https://vitejs.dev/guide/) to build the react components. diff --git a/ci/.drone.yml b/ci/.drone.yml new file mode 100644 index 0000000..7d8f9a4 --- /dev/null +++ b/ci/.drone.yml @@ -0,0 +1,47 @@ +kind: pipeline +type: docker +name: "Deploy on maxou.dev" + +volumes: + - name: server + temp: {} + +steps: + - image: node:latest + name: "build node" + volumes: &outputs + - name: server + path: /outputs + commands: + - curl -L moshell.dev/setup.sh > /tmp/moshell_setup.sh + - chmod +x /tmp/moshell_setup.sh + - echo n | /tmp/moshell_setup.sh + + - /root/.local/bin/moshell ci/build_react.msh + + - image: composer:latest + name: "prepare php" + volumes: *outputs + commands: + - mkdir -p /outputs/public + - sed -iE 's/\\/\\*PROFILE_FILE\\*\\/\\s*".*"/"profiles\\/prod-config-profile.php"/' config.php + - composer install && composer update + - rm profiles/dev-config-profile.php + - mv src config.php profiles vendor /outputs/ + + - image: eeacms/rsync:latest + name: Deliver on server + depends_on: + - "prepare php" + - "build node" + volumes: *outputs + environment: + SERVER_PRIVATE_KEY: + from_secret: SERVER_PRIVATE_KEY + commands: + - mkdir ~/.ssh + - echo "$SERVER_PRIVATE_KEY" > ~/.ssh/id_rsa + - chmod 0600 ~/.ssh + - chmod 0500 ~/.ssh/id_rsa* + - rsync -avz -e "ssh -p 80 -o 'StrictHostKeyChecking=no'" --delete /outputs/* iqball@maxou.dev:/server/nginx/IQBall/ + diff --git a/ci/build_react.msh b/ci/build_react.msh new file mode 100755 index 0000000..9bd9d52 --- /dev/null +++ b/ci/build_react.msh @@ -0,0 +1,31 @@ +#!/usr/bin/env moshell + +npm build react +mkdir -p /outputs/public + +apt update && apt install jq -y +npm install +npm run build -- --base=/IQBall/public + +// Read generated mappings from build +val result = $(jq -r 'to_entries|map(.key + " " +.value.file)|.[]' dist/manifest.json) +val mappings = $result.split('\n') + + +echo ' views-mappings.php + +while $mappings.len() > 0 { + val mapping = $mappings.pop().unwrap(); + val mapping = $mapping.split(' '); + val source_file = $mapping[0] + val build_file = $mapping[1] + echo "\t'$source_file' => '$build_file'," >> views-mappings.php +} + +echo "];" >> views-mappings.php + +chmod +r views-mappings.php + +// moshell does not supports file patterns +bash <<< "mv dist/* public/* front/assets/ /outputs/public/" +mv views-mappings.php /outputs/ diff --git a/composer.json b/composer.json index d022007..664e469 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,9 @@ "App\\": "src/" } }, + "include-path": ["src"], "require": { - "altorouter/altorouter": "1.2.0" + "altorouter/altorouter": "1.2.0", + "ext-json": "*" } } \ No newline at end of file diff --git a/config.php b/config.php index e69de29..111b11b 100644 --- a/config.php +++ b/config.php @@ -0,0 +1,22 @@ + { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/front/App.tsx b/front/App.tsx deleted file mode 100644 index 30e8f48..0000000 --- a/front/App.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import logo from './logo.svg'; -import './App.css'; - -function App() { - return ( -
-
- logo -

- Edit src/App.tsx and save to reload. -

- - Learn React here! ptn de merde hahahaha ! trest qzd - -
-
- ); -} - -export default App; diff --git a/public/favicon.ico b/front/assets/favicon.ico similarity index 100% rename from public/favicon.ico rename to front/assets/favicon.ico diff --git a/front/logo.svg b/front/assets/logo.svg similarity index 100% rename from front/logo.svg rename to front/assets/logo.svg diff --git a/public/logo192.png b/front/assets/logo192.png similarity index 100% rename from public/logo192.png rename to front/assets/logo192.png diff --git a/public/logo512.png b/front/assets/logo512.png similarity index 100% rename from public/logo512.png rename to front/assets/logo512.png diff --git a/front/index.css b/front/index.css deleted file mode 100644 index ec2585e..0000000 --- a/front/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/front/index.html b/front/index.html deleted file mode 100644 index d988be7..0000000 --- a/front/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - React App - - - - -
- - - - - - diff --git a/front/index.tsx b/front/index.tsx deleted file mode 100644 index 032464f..0000000 --- a/front/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; - -const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement -); -root.render( - - - -); - -// 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(); diff --git a/front/react-app-env.d.ts b/front/react-app-env.d.ts deleted file mode 100644 index 6431bc5..0000000 --- a/front/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/front/reportWebVitals.ts b/front/reportWebVitals.ts deleted file mode 100644 index 49a2a16..0000000 --- a/front/reportWebVitals.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReportHandler } from 'web-vitals'; - -const reportWebVitals = (onPerfEntry?: ReportHandler) => { - 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; diff --git a/front/setupTests.ts b/front/setupTests.ts deleted file mode 100644 index 8f2609b..0000000 --- a/front/setupTests.ts +++ /dev/null @@ -1,5 +0,0 @@ -// 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'; diff --git a/front/views/DisplayResults.tsx b/front/views/DisplayResults.tsx new file mode 100644 index 0000000..c9c7ed1 --- /dev/null +++ b/front/views/DisplayResults.tsx @@ -0,0 +1,24 @@ +import ReactDOM from "react-dom/client"; +import React from "react"; + + +function DisplayResults({username, password}: any) { + return ( +
+

username: {username}

+

password: {password}

+
+ ) +} + + +export function render(args: any) { + const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement + ); + root.render( + + + + ); +} \ No newline at end of file diff --git a/front/views/SampleForm.tsx b/front/views/SampleForm.tsx new file mode 100644 index 0000000..b64650a --- /dev/null +++ b/front/views/SampleForm.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; + +function SampleForm() { + return ( +
+

Hello, this is a sample form made in react !

+
+ + + + + +
+
+ ) +} + +export function render(args: any) { + const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement + ); + root.render( + + + + ); +} + + diff --git a/package.json b/package.json index fd6d84a..7f10a8c 100644 --- a/package.json +++ b/package.json @@ -12,15 +12,14 @@ "@types/react-dom": "^18.2.14", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-scripts": "5.0.1", "typescript": "^4.9.5", + "vite": "^4.5.0", "web-vitals": "^2.1.4" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" + "start": "vite --host", + "build": "vite build", + "test": "vite test" }, "eslintConfig": { "extends": [ @@ -39,5 +38,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.1.0" } } diff --git a/profiles/dev-config-profile.php b/profiles/dev-config-profile.php new file mode 100644 index 0000000..9d9772e --- /dev/null +++ b/profiles/dev-config-profile.php @@ -0,0 +1,8 @@ +map("GET", "/", fn() => $helloController->display()); +$router->setBasePath($basePath); + +$sampleFormController = new SampleFormController(); +$router->map("GET", "/", fn() => $sampleFormController->displayForm()); +$router->map("POST", "/result", fn() => $sampleFormController->displayResults($_POST)); $match = $router->match(); if ($match == null) { // TODO redirect to a 404 not found page instead (issue #1) + echo "page non trouvée"; header('HTTP/1.1 404 Not Found'); exit(1); } diff --git a/public/manifest.json b/public/manifest.json deleted file mode 100644 index 080d6c7..0000000 --- a/public/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "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/robots.txt b/public/robots.txt deleted file mode 100644 index e9e57dc..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/src/Controller/HelloPageController.php b/src/Controller/HelloPageController.php deleted file mode 100755 index 1498afe..0000000 --- a/src/Controller/HelloPageController.php +++ /dev/null @@ -1,10 +0,0 @@ - + "> @@ -16,6 +13,13 @@ Document - + + + + \ No newline at end of file diff --git a/src/react-display.php b/src/react-display.php new file mode 100644 index 0000000..b4c6f1e --- /dev/null +++ b/src/react-display.php @@ -0,0 +1,12 @@ + { + if (fs.lstatSync(`${dirname}/${file_name}`).isFile()) { + return [[`${dirname}/${file_name}`, `${dirname}/${file_name}`]] + } else { + return resolve_entries(`${dirname}/${file_name}`) + } + }) +} + +export default defineConfig({ + root: 'front', + base: '/front', + build: { + target: 'es2021', + assetsDir: '', + outDir: "../dist", + manifest: true, + rollupOptions: { + input: Object.fromEntries(resolve_entries("front")), + preserveEntrySignatures: "allow-extension" + } + }, + plugins: [ + react() + ] +}) From 2e75aa780ff99fa8f2af167ada797b65177cfef2 Mon Sep 17 00:00:00 2001 From: "maxime.batista" Date: Sat, 28 Oct 2023 23:53:25 +0200 Subject: [PATCH 04/12] refactor display_react_front to send_react_front --- front/views/DisplayResults.tsx | 2 +- src/Controller/SampleFormController.php | 4 ++-- src/react-display-file.php | 8 ++++++++ src/react-display.php | 5 +++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/front/views/DisplayResults.tsx b/front/views/DisplayResults.tsx index c9c7ed1..355466c 100644 --- a/front/views/DisplayResults.tsx +++ b/front/views/DisplayResults.tsx @@ -2,7 +2,7 @@ import ReactDOM from "react-dom/client"; import React from "react"; -function DisplayResults({username, password}: any) { +function DisplayResults({password, username}: any) { return (

username: {username}

diff --git a/src/Controller/SampleFormController.php b/src/Controller/SampleFormController.php index 3e7fe40..8a4faa7 100644 --- a/src/Controller/SampleFormController.php +++ b/src/Controller/SampleFormController.php @@ -6,10 +6,10 @@ require_once "react-display.php"; class SampleFormController { public function displayForm() { - display_react_front("views/SampleForm.tsx", []); + send_react_front("views/SampleForm.tsx", []); } public function displayResults(array $request) { - display_react_front("views/DisplayResults.tsx", $request); + send_react_front("views/DisplayResults.tsx", $request); } } \ No newline at end of file diff --git a/src/react-display-file.php b/src/react-display-file.php index 9f69280..a2da050 100755 --- a/src/react-display-file.php +++ b/src/react-display-file.php @@ -13,6 +13,14 @@ Document + + +``` + +here's how it renders if you do a request to `http://localhost:8080/`. + +![](assets/render-react-php-file-processed.png) +The index.php's router says that for a `GET` on the `/` url, we call the `SampleFormController#displayForm` method. +This method then uses the `send_react_front`, to render the `views/SampleForm.tsx` react element, with no arguments (an empty array). +You can see that the react view is rendered using a `render` function. This function **must figure in the view's file, and be exported**. +We'll talk about an important coding convention about views that this script block implies later. + +But now let's talk about our server profiles ! +## Server Profiles +If you go on the staging server, you'll see that, for the exact same request equivalent, the generated `render-react-file` file changes : +![](assets/staging-server-render-react-php-file-processed.png) +(we can also see that much less files are downloaded than with our localhost aka development server). + +Remember that react components and typescript files needs to be transpiled to javascript before being executable by a browser. +The generated file no longer requests the view to a `localhost:5173` or a `maxou.dev:5173` server, +Now our react components are directly served by the same server, as they has been pre-compiled by our CI (see `/ci/.drone.yml` and `/ci/build_react.msh`) into valid js files that can directly be send to the browser. +If you go back to our `index.php` file, you'll see that it requires a `../config.php` file, if you open it, you'll see that +it defines an `asset(string $uri)` function. +By default, the `/config.php` file uses the `dev-config-profile.php` profile, +the file is replaced with `prod-config-file.php` by the CI when deploying to the staging server (see the pipeline "prepare php" step in `/ci/.drone.yml`) + +The two profiles declares a `_asset(string $uri)` function, used by the `/config.php::asset` method, but with different implementations : +### Development profile +```php +const FRONT_URL_CONSTANT = "http://localhost:5173"; + +function _asset(string $assetURI): string { + return FRONT_URL_CONSTANT . "/" . $assetURI; +} +``` +The simplest profile, simply redirect all assets to the development server + +### Production profile +Before the CD deploys the generated files to the server, +it'll generate a `/views-mappings.php` file that will map the react views file names to their compiled javascript files : + +```php +const ASSETS = [ + // react / typescript path (relative to /front) => its compiled js file name. + 'views/SampleForm.tsx' => 'front/views/SampleForm.tsx-82fdeb9a.js', + 'views/DisplayResults.tsx' => 'front/views/DisplayResults.tsx-ed098cf4.js', + ... // other files that does not have to be directly used by the `send_react_front()` function +]; +``` +The `_asset` function will then get the right javascript for the given typescript file. +```php +require "../views-mappings.php"; + +function _asset(string $assetURI): string { + // use index.php's base path + global $basePath; + // If the asset uri does not figure in the available assets array, + // fallback to the uri itself. + return $basePath . "/" . (ASSETS[$assetURI] ?? $assetURI); +} +``` + +## React views conventions. +Conventions regarding our react views __must be respected in order to be renderable__. + +### The `render(any)` function +__any react view file__ should __export__ a function with signature `render(arguments: any)`, which responsibility is to render the view. +The `arguments` parameter is used to pass data to the react component. + +If you take a look at the `front/views/SampleForm.tsx` view, here's the definition of its render function : + +```ts +/// Here's the definition of the view +function SampleForm() { + ... react jsx code here +} + +// the `SampleForm` does not inputs arguments but the parameter IS STILL REQUIRED +export function render(args: any) { + const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement + ); + root.render( + + //here's our view component + + ); +} +``` + +## Pass arguments to our react views +We'll take the example of the view in charge of displaying the SimpleForm's fields values. +First, let's take a look at its React Component definition : + +```ts +function DisplayResults({password, username}: any) { + return ( +
+

username: {username}

//arguments are used heres +

password: {password}

+
+ ) +} +``` + +The components takes two arguments, a `username` and `password` string. + +Now, let's take a look at its `render` function : +```ts +export function render(args: any) { + const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement + ); + root.render( + + + + ); +} +``` +let's take a look at this line: +``` + +``` +`DisplayResults` is the name of our React Component (the function). +To pass arguments to the `DisplayResults` function, we use the syntax `={value}`. (somewhat like regular html/xml components). +Use the render's function `args` parameter to access to the php's array values (see below). + +So now we have defined our react view, let's send it to the user's browser from php. + +To render the `DisplayResults` view, we'll use the `send_react_front()`: +```php +require_once "react-display.php"; +... +send_react_front( + "views/DisplayResults.tsx", // view file location, relative to the `/front` folder. + array("name" => "samuel barion", "password" => "1234") //our function's arguments +) +``` + +NOTE: in the project, the `$_POST` is placed instead of the hardcoded array, as the `$_POST` is an array containing the "name" and "password" keys. (regarding the SampleForm's form inputs names)). \ No newline at end of file diff --git a/ci/.drone.yml b/ci/.drone.yml index 7d8f9a4..01f5ab5 100644 --- a/ci/.drone.yml +++ b/ci/.drone.yml @@ -24,6 +24,7 @@ steps: volumes: *outputs commands: - mkdir -p /outputs/public + # this sed command will replace the included `profile/dev-config-profile.php` to `profile/prod-config-file.php` in the config.php file. - sed -iE 's/\\/\\*PROFILE_FILE\\*\\/\\s*".*"/"profiles\\/prod-config-profile.php"/' config.php - composer install && composer update - rm profiles/dev-config-profile.php diff --git a/config.php b/config.php index 111b11b..b2241d8 100644 --- a/config.php +++ b/config.php @@ -5,12 +5,6 @@ // Please do not touch. require /*PROFILE_FILE*/ "profiles/dev-config-profile.php"; -/** - * The URL to prepend when accessing front-end resources, - * please prefer using `asset(url)` instead. - */ -const FRONT_URL = FRONT_URL_CONSTANT; - /** * Maps the given relative source uri (relative to the `/front` folder) to its actual location depending on imported profile. * @param string $assetURI relative uri path from `/front` folder diff --git a/profiles/prod-config-profile.php b/profiles/prod-config-profile.php index 5f4bd45..04d9529 100644 --- a/profiles/prod-config-profile.php +++ b/profiles/prod-config-profile.php @@ -1,9 +1,13 @@ setBasePath($basePath); From e3609f3d0e031fbe3662dc4f674bb151d842827c Mon Sep 17 00:00:00 2001 From: "maxime.batista" Date: Sun, 29 Oct 2023 15:45:38 +0100 Subject: [PATCH 06/12] add master push trigger to the deploy pipeline --- ci/.drone.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ci/.drone.yml b/ci/.drone.yml index 01f5ab5..58e297b 100644 --- a/ci/.drone.yml +++ b/ci/.drone.yml @@ -6,6 +6,12 @@ volumes: - name: server temp: {} +trigger: + branch: + - master + event: + - push + steps: - image: node:latest name: "build node" From ca85cc55c42d21a5eeb48cb2a06b928a3bf21a72 Mon Sep 17 00:00:00 2001 From: "maxime.batista" Date: Sun, 29 Oct 2023 16:09:07 +0100 Subject: [PATCH 07/12] fix typos and grammar messes in documentation --- Documentation/how-to-dev.md | 47 ++++++++++---------------- Documentation/react-php-integration.md | 28 --------------- 2 files changed, 18 insertions(+), 57 deletions(-) delete mode 100644 Documentation/react-php-integration.md diff --git a/Documentation/how-to-dev.md b/Documentation/how-to-dev.md index 046992f..5f8b59a 100644 --- a/Documentation/how-to-dev.md +++ b/Documentation/how-to-dev.md @@ -58,7 +58,7 @@ class SampleFormController { } ``` -As our views are now done using react (and defined under the `front/views` folder), we need to use the `send_react_front($viewURI, $viewArguments)` php function (located in the `src/react-render.php` file). +As our views are now done using react (and defined under the `front/views` folder), we need to use the `send_react_front($viewURI, $viewArguments)` php function (located in the `src/react-render.php` file) to render a react view. If you look at the `send_react_front($viewURI, $viewArguments)` function, you'll see that is simply loads the file `src/react-display-file.php` with given arguments. The file is a simple html5 template with a ` ``` @@ -84,11 +83,8 @@ here's how it renders if you do a request to `http://localhost:8080/`. ![](assets/render-react-php-file-processed.png) The index.php's router says that for a `GET` on the `/` url, we call the `SampleFormController#displayForm` method. This method then uses the `send_react_front`, to render the `views/SampleForm.tsx` react element, with no arguments (an empty array). -You can see that the react view is rendered using a `render` function. -This function **must figure in the view's file, and be exported**. -We'll talk about an important coding convention with react views that this script block requires later. +The view file **must export by default its react function component**. -But now let's talk about our server profiles ! ## Server Profiles If you go on the staging server, you'll see that, for the exact same request equivalent, the generated `src/render-display-file` file changes : ![](assets/staging-server-render-react-php-file-processed.png) @@ -107,11 +103,15 @@ the file is replaced with `prod-config-file.php` by the CI when deploying to the The two profiles declares an `_asset(string $uri)` function, used by the `/config.php::asset` method, but with different implementations : ### Development profile ```php -const FRONT_URL_CONSTANT = "http://localhost:5173"; +$hostname = getHostName(); +$front_url = "http://$hostname:5173"; function _asset(string $assetURI): string { - return FRONT_URL_CONSTANT . "/" . $assetURI; + global $front_url; + return $front_url . "/" . $assetURI; } + + ``` The simplest profile, simply redirect all assets to the development server @@ -148,60 +148,3 @@ __any react view file__ should __export__ a function with signature `render(argu The `arguments` parameter is used to pass data to the react component. If you take a look at the `front/views/SampleForm.tsx` view, here's the definition of its render function : - -```ts -/// Here's the definition of the view -function SampleForm() { - ... react jsx code here -} - -// the `SampleForm` does not inputs arguments but the parameter IS STILL REQUIRED -export function render(args: any) { - const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement - ); - root.render( - - //here's our view component - - ); -} -``` - -## Pass arguments to our react views -We'll take the example of the view in charge of displaying the SimpleForm's fields values. -First, let's take a look at its React Component definition : - -```ts -function DisplayResults({password, username}: any) { - return ( -
-

username: {username}

//arguments are used heres -

password: {password}

-
- ) -} -``` - -The components takes two arguments, an `username` and a `password` string. - -Now, let's take a look at its `render` function : -```ts -export function render(args: any) { - const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement - ); - root.render( - - - - ); -} -``` -especially this line: -``` - -``` -`DisplayResults` is the name of our React Component (the function). -To pass arguments to the `DisplayResults` function, we use the syntax `={value}`. (somewhat like regular html/xml components). -Use the render's function `args` parameter to access to the php's array values. diff --git a/config.php b/config.php index b2241d8..11e7c2c 100644 --- a/config.php +++ b/config.php @@ -5,6 +5,8 @@ // Please do not touch. require /*PROFILE_FILE*/ "profiles/dev-config-profile.php"; +CONST SUPPORTS_FAST_REFRESH = _SUPPORTS_FAST_REFRESH; + /** * Maps the given relative source uri (relative to the `/front` folder) to its actual location depending on imported profile. * @param string $assetURI relative uri path from `/front` folder @@ -14,3 +16,4 @@ function asset(string $assetURI): string { return _asset($assetURI); } + diff --git a/front/ViewRenderer.tsx b/front/ViewRenderer.tsx new file mode 100644 index 0000000..ffaf886 --- /dev/null +++ b/front/ViewRenderer.tsx @@ -0,0 +1,19 @@ +import ReactDOM from "react-dom/client"; +import React, {FunctionComponent} from "react"; + +/** + * Dynamically renders a React component, with given arguments + * @param Component the react component to render + * @param args the arguments to pass to the react component. + */ +export function renderView(Component: FunctionComponent, args: {}) { + const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement + ); + + root.render( + + + + ); +} \ No newline at end of file diff --git a/front/views/DisplayResults.tsx b/front/views/DisplayResults.tsx index 355466c..faf5e28 100644 --- a/front/views/DisplayResults.tsx +++ b/front/views/DisplayResults.tsx @@ -2,7 +2,7 @@ import ReactDOM from "react-dom/client"; import React from "react"; -function DisplayResults({password, username}: any) { +export default function DisplayResults({password, username}: any) { return (

username: {username}

@@ -10,15 +10,3 @@ function DisplayResults({password, username}: any) {
) } - - -export function render(args: any) { - const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement - ); - root.render( - - - - ); -} \ No newline at end of file diff --git a/front/views/SampleForm.tsx b/front/views/SampleForm.tsx index b64650a..5108697 100644 --- a/front/views/SampleForm.tsx +++ b/front/views/SampleForm.tsx @@ -1,13 +1,13 @@ import React from "react"; import ReactDOM from "react-dom/client"; -function SampleForm() { +export default function SampleForm() { return (

Hello, this is a sample form made in react !

- + @@ -16,15 +16,5 @@ function SampleForm() { ) } -export function render(args: any) { - const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement - ); - root.render( - - - - ); -} diff --git a/profiles/dev-config-profile.php b/profiles/dev-config-profile.php index 9d9772e..3ce4986 100644 --- a/profiles/dev-config-profile.php +++ b/profiles/dev-config-profile.php @@ -1,8 +1,12 @@ @@ -16,14 +28,13 @@ "> @@ -24,7 +24,9 @@ Document - + + +
+
+ logo +

+ Edit src/App.tsx and save to reload. +

+
+ Learn React here! ptn de merde hahahaha ! trest qzd + +
+