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 (
-
- );
-}
-
-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
-
+
+
+
+