diff --git a/backend/src/DataFixtures/ProjectFixtures.php b/backend/src/DataFixtures/ProjectFixtures.php index 2ce92ad..3747deb 100644 --- a/backend/src/DataFixtures/ProjectFixtures.php +++ b/backend/src/DataFixtures/ProjectFixtures.php @@ -3,6 +3,7 @@ namespace App\DataFixtures; use App\Entity\Project; +use App\Entity\Request; use App\Entity\User; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\DependentFixtureInterface; @@ -14,15 +15,77 @@ class ProjectFixtures extends Fixture implements DependentFixtureInterface public function load(ObjectManager $manager) { - $dev1 = $manager + //NEW PROJECT + $user = $manager ->getRepository(User::class) ->findOneByUsername('dev1') ; - $project1 = new Project(); - $project1->setName("Test"); - $project1->addUser($dev1); - $manager->persist($project1); + $project = new Project(); + $request = $manager + ->getRepository(Request::class) + ->findOneByTitle('Demande num 1') + ; + $project->addRequest($request); + $request = $manager + ->getRepository(Request::class) + ->findOneByTitle('Demande num 2') + ; + $project->addRequest($request); + $request = $manager + ->getRepository(Request::class) + ->findOneByTitle('Demande num 3') + ; + $project->addRequest($request); + + $project->setName("Projet 1"); + $project->addUser($user); + $manager->persist($project); + + //NEW PROJECT + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client1') + ; + + $project = new Project(); + + $request = $manager + ->getRepository(Request::class) + ->findOneByTitle('Demande num 4') + ; + $project->addRequest($request); + $request = $manager + ->getRepository(Request::class) + ->findOneByTitle('Demande num 5') + ; + $project->addRequest($request); + + $project->setName("Projet 2"); + $project->addUser($user); + $manager->persist($project); + + //NEW PROJECT + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client1') + ; + + $project = new Project(); + $project->setName("Projet 3"); + $project->addUser($user); + $manager->persist($project); + + //NEW PROJECT + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client2') + ; + + $project = new Project(); + $project->setName("Projet 4"); + $project->addUser($user); + $manager->persist($project); $manager->flush(); @@ -32,6 +95,7 @@ class ProjectFixtures extends Fixture implements DependentFixtureInterface { return [ UserFixtures::class, + RequestFixtures::class ]; } diff --git a/backend/src/DataFixtures/RequestFixtures.php b/backend/src/DataFixtures/RequestFixtures.php new file mode 100644 index 0000000..e8f515f --- /dev/null +++ b/backend/src/DataFixtures/RequestFixtures.php @@ -0,0 +1,121 @@ +getRepository(User::class) + ->findOneByUsername('client1') + ; + + $status = $manager + ->getRepository(RequestStatus::class) + ->findOneBySlug('en-attente') + ; + + $request = new Request(); + $request->setTitle("Demande num 1"); + $request->setAuthor($user); + $request->setCreatedAt(new DateTime()); + $request->setStatus($status); + $manager->persist($request); + + //NEW REQUEST + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client1') + ; + + $status = $manager + ->getRepository(RequestStatus::class) + ->findOneBySlug('pris-en-compte') + ; + + $request = new Request(); + $request->setTitle("Demande num 2"); + $request->setAuthor($user); + $request->setCreatedAt(new DateTime()); + $request->setStatus($status); + $manager->persist($request); + + //NEW REQUEST + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client1') + ; + + $status = $manager + ->getRepository(RequestStatus::class) + ->findOneBySlug('en-cours-de-traitement') + ; + + $request = new Request(); + $request->setTitle("Demande num 3"); + $request->setAuthor($user); + $request->setCreatedAt(new DateTime()); + $request->setStatus($status); + $manager->persist($request); + + //NEW REQUEST + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client2') + ; + + $status = $manager + ->getRepository(RequestStatus::class) + ->findOneBySlug('traite') + ; + + $request = new Request(); + $request->setTitle("Demande num 4"); + $request->setAuthor($user); + $request->setCreatedAt(new DateTime()); + $request->setStatus($status); + $manager->persist($request); + + //NEW REQUEST + $user = $manager + ->getRepository(User::class) + ->findOneByUsername('client2') + ; + + $status = $manager + ->getRepository(RequestStatus::class) + ->findOneBySlug('clos') + ; + + $request = new Request(); + $request->setTitle("Demande num 5"); + $request->setAuthor($user); + $request->setCreatedAt(new DateTime()); + $request->setStatus($status); + $manager->persist($request); + + $manager->flush(); + + } + + public function getDependencies() + { + return [ + RequestStatusFixtures::class, + UserFixtures::class, + ]; + } + + +} diff --git a/backend/src/DataFixtures/RequestStatusFixtures.php b/backend/src/DataFixtures/RequestStatusFixtures.php index 1d7a867..3041bdd 100644 --- a/backend/src/DataFixtures/RequestStatusFixtures.php +++ b/backend/src/DataFixtures/RequestStatusFixtures.php @@ -11,16 +11,32 @@ class RequestStatusFixtures extends Fixture public function load(ObjectManager $manager) { $statuses = [ - 'En attente', - 'Pris en compte', - 'En cours de traitement', - 'Traité', - 'Clos', + [ + 'label' => 'En attente', + 'slug' => 'en-attente' + ], + [ + 'label' => 'Pris en compte', + 'slug' => 'pris-en-compte' + ], + [ + 'label' => 'En cours de traitement', + 'slug' => 'en-cours-de-traitement' + ], + [ + 'label' => 'Traité', + 'slug' => 'traite' + ], + [ + 'label' => 'Clos', + 'slug' => 'clos' + ], ]; - foreach($statuses as $statusLabel) { + foreach($statuses as $s) { $status = new RequestStatus(); - $status->setLabel($statusLabel); + $status->setLabel($s['label']); + $status->setSlug($s['slug']); $manager->persist($status); } diff --git a/backend/src/Entity/RequestStatus.php b/backend/src/Entity/RequestStatus.php index 803adc5..8affdfb 100644 --- a/backend/src/Entity/RequestStatus.php +++ b/backend/src/Entity/RequestStatus.php @@ -23,6 +23,11 @@ class RequestStatus */ private $label; + /** + * @ORM\Column(type="string", length=64) + */ + private $slug; + /** * @ORM\OneToMany(targetEntity="App\Entity\Request", mappedBy="status") */ @@ -50,6 +55,18 @@ class RequestStatus return $this; } + public function getSlug(): ?string + { + return $this->slug; + } + + public function setSlug(string $slug): self + { + $this->slug = $slug; + + return $this; + } + /** * @return Collection|Request[] */ diff --git a/frontend/src/actions/project.js b/frontend/src/actions/project.js new file mode 100644 index 0000000..fc03b46 --- /dev/null +++ b/frontend/src/actions/project.js @@ -0,0 +1,27 @@ +export const PROJECT_USER_LIST = 'PROJECT_USER_LIST'; +export const PROJECT_USER_LIST_SUCCESS = 'PROJECT_USER_LIST_SUCCESS'; +export const PROJECT_USER_LIST_FAILURE = 'PROJECT_USER_LIST_FAILURE'; + +export function projectUserListRequest() { + return { type: PROJECT_USER_LIST} +} +export function projectUserListSuccess(projects) { + return { type: PROJECT_USER_LIST_SUCCESS, projects } +} +export function projectUserListFailure(error) { + return { type: PROJECT_USER_LIST_FAILURE, error } +} + +export const PROJECT_LIST = 'PROJECT_LIST'; +export const PROJECT_LIST_SUCCESS = 'PROJECT_LIST_SUCCESS'; +export const PROJECT_LIST_FAILURE = 'PROJECT_LIST_FAILURE'; + +export function projectList() { + return { type: PROJECT_LIST} +} +export function projectListSuccess(projects) { + return { type: PROJECT_LIST_SUCCESS, projects } +} +export function projectListFailure(error) { + return { type: PROJECT_LIST_FAILURE, error } +} \ No newline at end of file diff --git a/frontend/src/app.js b/frontend/src/app.js index c7e5e20..a67b5c6 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -4,6 +4,8 @@ import { HashRouter } from 'react-router-dom' // ou BrowserRouter import { Route, Switch, Redirect } from 'react-router' import HomePage from './pages/home'; import { ConnectedLoginPage as LoginPage } from './pages/login'; +import DashBoardClient from './pages/DashBoardClient'; +import DashBoardDev from './pages/DashBoardDev'; class App extends Component { render () { @@ -13,6 +15,8 @@ class App extends Component { + + } /> diff --git a/frontend/src/components/ProjectList.js b/frontend/src/components/ProjectList.js new file mode 100644 index 0000000..35bd13d --- /dev/null +++ b/frontend/src/components/ProjectList.js @@ -0,0 +1,12 @@ +import React from 'react' +import ProjectTile from './ProjectTile' + +export default ({ projects, withRequest }) => ( +
+ { + projects.map(project => ( + + )) + } +
+) diff --git a/frontend/src/components/ProjectTile.js b/frontend/src/components/ProjectTile.js new file mode 100644 index 0000000..ca4b6df --- /dev/null +++ b/frontend/src/components/ProjectTile.js @@ -0,0 +1,11 @@ +import React from 'react' +import RequestList from './RequestList' + +export default ({ project, withRequest }) => ( +
+

{project.name}

+ { + withRequest && + } +
+) diff --git a/frontend/src/components/RequestList.js b/frontend/src/components/RequestList.js new file mode 100644 index 0000000..bb45a75 --- /dev/null +++ b/frontend/src/components/RequestList.js @@ -0,0 +1,12 @@ +import React from 'react' +import RequestTile from './RequestTile' + +export default ({ requests }) => ( +
+ { + requests.map(request => ( + + )) + } +
+) diff --git a/frontend/src/components/RequestTile.css b/frontend/src/components/RequestTile.css new file mode 100644 index 0000000..124d2eb --- /dev/null +++ b/frontend/src/components/RequestTile.css @@ -0,0 +1,19 @@ +.request-status-en-attente { + background-color: orange !important; +} + +.request-status-pris-en-compte { + background-color: palevioletred !important; +} + +.request-status-en-cours-de-traitement { + background-color: greenyellow !important; +} + +.request-status-traite { + background-color: green !important; +} + +.request-status-clos { + background-color: black !important; +} diff --git a/frontend/src/components/RequestTile.js b/frontend/src/components/RequestTile.js new file mode 100644 index 0000000..6338754 --- /dev/null +++ b/frontend/src/components/RequestTile.js @@ -0,0 +1,14 @@ +import React from 'react' +import styles from './RequestTile.css' +import { Link } from 'react-router-dom' + +export default ({ request }) => ( + +
+

{request.title}

+
+ {request.author} || {request.createdAt} +
+
+ +) diff --git a/frontend/src/pages/DashBoardClient.js b/frontend/src/pages/DashBoardClient.js new file mode 100644 index 0000000..6f4ad8b --- /dev/null +++ b/frontend/src/pages/DashBoardClient.js @@ -0,0 +1,97 @@ +import React, { useEffect } from 'react' +import { connect } from 'react-redux' +import Page from './page'; +import ProjectList from '../components/ProjectList'; +import { projectUserListRequest } from '../actions/project'; + +const DashBoardClient = ({ projects = [], ...props }) => { + + useEffect(() => { + props.dispatch(projectUserListRequest()) + }, []) + projects = [ + { + id: 1, + name: 'mon premier projet', + requests: [ + { + id: 1, + title: 'Demande num 1', + author: 'Gael Peltey', + status: { + id: 1, + slug: 'en-attente' + }, + createdAt: 'le 20 juillet 2019' + }, + { + id: 2, + title: 'Demande num 2', + author: 'Jean Guy', + status: { + id: 2, + slug: 'pris-en-compte' + }, + createdAt: 'le 20 juillet 2020' + }, + { + id: 3, + title: 'Demande num 3', + author: 'Gael Peltey', + status: { + id: 3, + slug: 'en-cours-de-traitement' + }, + createdAt: 'le 20 juillet 2021' + } + + ] + }, + { + id: 2, + name: 'mon deuxième projet', + }, + { + id: 3, + name: 'mon troisième projet', + requests: [ + { + id: 4, + title: 'Demande num 4', + author: 'David Pujadas', + status: { + id: 4, + slug: 'traite' + }, + createdAt: 'le 20 juillet 2022' + }, + { + id: 5, + title: 'Demande num 5', + author: 'Jean Mi', + status: { + id: 5, + slug: 'clos' + }, + createdAt: 'le 20 juillet 2023' + } + + ] + }, + ] + return ( + +
+

Mon dashboard

+
+ +
+ ); + } + + +const mapStateToProps = ({ project }) => ({ + projects: project.items, +}) + +export default connect(mapStateToProps)(DashBoardClient) \ No newline at end of file diff --git a/frontend/src/pages/DashBoardDev.js b/frontend/src/pages/DashBoardDev.js new file mode 100644 index 0000000..1c0d68b --- /dev/null +++ b/frontend/src/pages/DashBoardDev.js @@ -0,0 +1,97 @@ +import React, { useEffect } from 'react' +import { connect } from 'react-redux' +import Page from './page'; +import ProjectList from '../components/ProjectList'; +import { projectList } from '../actions/project'; + +const DashBoardDev = ({ projects = [], ...props }) => { + + useEffect(() => { + props.dispatch(projectList()) + }, []) + projects = [ + { + id: 1, + name: 'mon premier projet', + requests: [ + { + id: 1, + title: 'Demande num 1', + author: 'Gael Peltey', + status: { + id: 1, + slug: 'en-attente' + }, + createdAt: 'le 20 juillet 2019' + }, + { + id: 2, + title: 'Demande num 2', + author: 'Jean Guy', + status: { + id: 2, + slug: 'pris-en-compte' + }, + createdAt: 'le 20 juillet 2020' + }, + { + id: 3, + title: 'Demande num 3', + author: 'Gael Peltey', + status: { + id: 3, + slug: 'en-cours-de-traitement' + }, + createdAt: 'le 20 juillet 2021' + } + + ] + }, + { + id: 2, + name: 'mon deuxième projet', + }, + { + id: 3, + name: 'mon troisième projet', + requests: [ + { + id: 4, + title: 'Demande num 4', + author: 'David Pujadas', + status: { + id: 4, + slug: 'traite' + }, + createdAt: 'le 20 juillet 2022' + }, + { + id: 5, + title: 'Demande num 5', + author: 'Jean Mi', + status: { + id: 5, + slug: 'clos' + }, + createdAt: 'le 20 juillet 2023' + } + + ] + }, + ] + return ( + +
+

Developpeur Dashboard

+
+ +
+ ); + } + + +const mapStateToProps = ({ project }) => ({ + projects: project.items, +}) + +export default connect(mapStateToProps)(DashBoardDev) \ No newline at end of file diff --git a/frontend/src/pages/page.js b/frontend/src/pages/page.js index 186c8a1..510092d 100644 --- a/frontend/src/pages/page.js +++ b/frontend/src/pages/page.js @@ -19,7 +19,7 @@ export default function Page({ title, messages, dispatch, children }) { }, [messages]) return ( -
+
{ children }
diff --git a/frontend/src/reducers/project.js b/frontend/src/reducers/project.js new file mode 100644 index 0000000..6e74768 --- /dev/null +++ b/frontend/src/reducers/project.js @@ -0,0 +1,31 @@ +import { + PROJECT_USER_LIST_SUCCESS, + PROJECT_USER_LIST_FAILURE +} from '../actions/project' + +const initialState = { + items: [] +} + +export default (state = initialState, action) => { + + console.log(`Action: ${JSON.stringify(action)}`) + + switch (action.type) { + + case PROJECT_USER_LIST_SUCCESS: + return { + ...state, + items: action.projects + } + case PROJECT_USER_LIST_FAILURE: + return { + ...state, + items: [], + error: action.error + } + + } + return state + +} \ No newline at end of file diff --git a/frontend/src/sagas/project.js b/frontend/src/sagas/project.js new file mode 100644 index 0000000..a7cdb22 --- /dev/null +++ b/frontend/src/sagas/project.js @@ -0,0 +1,53 @@ +import { call, put } from 'redux-saga/effects'; +import { projectUserListFailure, projectUserListSuccess, projectListFailure, projectListSuccess } from '../actions/project'; + +export function* projectUserListSaga() { + let result + try { + result = yield call(projectUserList); + } catch(err) { + yield put(projectUserListFailure(err)); + return + } + + if ('error' in result) { + yield put(projectUserListFailure(result.error)); + return + } + + yield put(projectUserListSuccess(result.data)); +} + +const projectUserList = () => { + return fetch('http://localhost:8001/api/v1/me', { + method: 'GET', + mode: 'cors', + credentials: 'include' + }).then(res => res.json()) +} + + +export function* projectListSaga() { + let result + try { + result = yield call(projectList); + } catch(err) { + yield put(projectListFailure(err)); + return + } + + if ('error' in result) { + yield put(projectListFailure(result.error)); + return + } + + yield put(projectListSuccess(result.data)); +} + +const projectList = () => { + return fetch('http://localhost:8001/api/v1/projects', { + method: 'GET', + mode: 'cors', + credentials: 'include' + }).then(res => res.json()) +} \ No newline at end of file diff --git a/frontend/src/sagas/root.js b/frontend/src/sagas/root.js index 3e561d1..975d32c 100644 --- a/frontend/src/sagas/root.js +++ b/frontend/src/sagas/root.js @@ -1,9 +1,13 @@ import { all, takeLatest } from 'redux-saga/effects'; import { LOGIN_REQUEST } from '../actions/auth.actions'; import { loginSaga} from './auth.sagas'; +import { PROJECT_USER_LIST, PROJECT_LIST } from '../actions/project'; +import { projectUserListSaga, projectListSaga } from './project'; export default function* rootSaga() { yield all([ takeLatest(LOGIN_REQUEST, loginSaga), + takeLatest(PROJECT_USER_LIST, projectUserListSaga), + takeLatest(PROJECT_LIST, projectListSaga), ]); } diff --git a/frontend/src/store/store.js b/frontend/src/store/store.js index dc8cbd6..59aeb1d 100644 --- a/frontend/src/store/store.js +++ b/frontend/src/store/store.js @@ -3,12 +3,14 @@ import createSagaMiddleware from 'redux-saga' import rootSaga from '../sagas/root' import { sessionReducer } from '../reducers/session.reducers'; import { messagesReducer } from '../reducers/messages.reducers'; +import project from '../reducers/project' const sagaMiddleware = createSagaMiddleware() const rootReducer = combineReducers({ session: sessionReducer, messages: messagesReducer, + project }); const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;