diff --git a/.env b/.env
index 11831a1..042d484 100644
--- a/.env
+++ b/.env
@@ -29,6 +29,6 @@ APP_SECRET=b2b0f5c49ef6e56406e93246d9250c00
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
-DATABASE_URL="mysql://symfony:symfony@localhost:3306/symfony?serverVersion=10.3.34-MariaDB&charset=utf8mb4"
+DATABASE_URL="mysql://symfony:symfony@127.0.0.1:3306/symfony?serverVersion=10.3.34-MariaDB&charset=utf8mb4"
# DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?ser/verVersion=13&charset=utf8"
###< doctrine/doctrine-bundle ###
diff --git a/config/packages/security.yaml b/config/packages/security.yaml
index 7b38924..787631a 100644
--- a/config/packages/security.yaml
+++ b/config/packages/security.yaml
@@ -35,6 +35,6 @@ security:
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/task/*, roles: ROLE_USER }
-
+ - { path: ^/project/*, roles: ROLE_USER}
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
diff --git a/config/routes.yaml b/config/routes.yaml
index c3283aa..fee3c65 100644
--- a/config/routes.yaml
+++ b/config/routes.yaml
@@ -1,3 +1,3 @@
-#index:
-# path: /
-# controller: App\Controller\DefaultController::index
+index:
+ path: /
+ controller: App\Controller\ProjectController::list
diff --git a/migrations/Version20220602121009.php b/migrations/Version20220602121009.php
new file mode 100644
index 0000000..ff9270c
--- /dev/null
+++ b/migrations/Version20220602121009.php
@@ -0,0 +1,34 @@
+addSql('CREATE TABLE project (id INT AUTO_INCREMENT NOT NULL, author_id INT NOT NULL, key_project VARCHAR(5) NOT NULL, name VARCHAR(255) NOT NULL, INDEX IDX_2FB3D0EEF675F31B (author_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+ $this->addSql('ALTER TABLE project ADD CONSTRAINT FK_2FB3D0EEF675F31B FOREIGN KEY (author_id) REFERENCES user (id)');
+ $this->addSql('ALTER TABLE task CHANGE is_completed is_completed TINYINT(1) DEFAULT 0 NOT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql('DROP TABLE project');
+ $this->addSql('ALTER TABLE task CHANGE is_completed is_completed TINYINT(1) DEFAULT NULL');
+ }
+}
diff --git a/migrations/Version20220602123943.php b/migrations/Version20220602123943.php
new file mode 100644
index 0000000..6def082
--- /dev/null
+++ b/migrations/Version20220602123943.php
@@ -0,0 +1,35 @@
+addSql('ALTER TABLE task ADD project_id INT NOT NULL');
+ $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25166D1F9C FOREIGN KEY (project_id) REFERENCES project (id)');
+ $this->addSql('CREATE INDEX IDX_527EDB25166D1F9C ON task (project_id)');
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25166D1F9C');
+ $this->addSql('DROP INDEX IDX_527EDB25166D1F9C ON task');
+ $this->addSql('ALTER TABLE task DROP project_id');
+ }
+}
diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php
new file mode 100644
index 0000000..7f8283b
--- /dev/null
+++ b/src/Controller/ProjectController.php
@@ -0,0 +1,80 @@
+getUser();
+ $projects = $this->getDoctrine()->getManager()
+ ->getRepository(Project::class)
+ ->getAvailableProjects($user->getId(), $this->isGranted('ROLE_ADMIN'));
+ return $this->render('project/list.html.twig', [
+ 'projects' => $projects,
+ ]);
+ }
+
+
+ /**
+ * @Route("/projects/create", name="project_create")
+ */
+ public function create(Request $request): Response
+ {
+ $project = new Project();
+ $form = $this->createForm(ProjectType::class, $project);
+
+ $form->handleRequest($request);
+
+ if ($form->isSubmitted() && $form->isValid()) {
+
+ $project->setAuthor($this->getUser());
+
+ $this->getDoctrine()->getManager()->persist($project);
+ $this->getDoctrine()->getManager()->flush();
+
+ return $this->redirectToRoute('project_list');
+ }
+
+ return $this->render("project/create.html.twig", [
+ 'form' => $form->createView()
+ ]);
+ }
+
+ /**
+ * @Route("project/show={id}", name="show_porject")
+ * @param $id
+ * @return void
+ */
+ public function show($id): Response
+ {
+ $project = $this->getDoctrine()->getManager()->find(Project::class, $id);
+
+ if ($project === null) {
+ throw $this->createNotFoundException(sprintf("Project with id %s not found", $id));
+ }
+
+ $tasks = $this->getDoctrine()->getRepository(Task::class)
+ ->findBy(['project' => $id], []);
+
+ return $this->render('project/show.html.twig',[
+ 'id' => $id,
+ 'tasks' => $tasks,
+ ]);
+ }
+}
diff --git a/src/Entity/Project.php b/src/Entity/Project.php
new file mode 100644
index 0000000..892d84c
--- /dev/null
+++ b/src/Entity/Project.php
@@ -0,0 +1,76 @@
+id;
+ }
+
+ public function getKeyProject(): ?string
+ {
+ return $this->keyProject;
+ }
+
+ public function setKeyProject(string $keyProject): self
+ {
+ $this->keyProject = $keyProject;
+
+ return $this;
+ }
+
+ public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+ public function setName(?string $name): self
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ public function getAuthor(): ?User
+ {
+ return $this->author;
+ }
+
+ public function setAuthor(?User $author): self
+ {
+ $this->author = $author;
+
+ return $this;
+ }
+}
diff --git a/src/Entity/Task.php b/src/Entity/Task.php
index 66a4b57..f7dd285 100644
--- a/src/Entity/Task.php
+++ b/src/Entity/Task.php
@@ -55,6 +55,11 @@ class Task
*/
protected $author;
+ /**
+ * @ORM\ManyToOne(targetEntity=Project::class, inversedBy="project")
+ */
+ private $project;
+
/**
* Create empty task
*/
@@ -161,7 +166,15 @@ public function setIsCompleted(bool $isCompleted = false)
$this->isCompleted = $isCompleted;
}
+ public function getProject(): ?Project
+ {
+ return $this->project;
+ }
+ public function setProject(?Project $project): self
+ {
+ $this->project = $project;
-
+ return $this;
+ }
}
\ No newline at end of file
diff --git a/src/Entity/User.php b/src/Entity/User.php
index 98648d0..1e321f4 100644
--- a/src/Entity/User.php
+++ b/src/Entity/User.php
@@ -3,6 +3,8 @@
namespace App\Entity;
use App\Repository\UserRepository;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
@@ -34,6 +36,16 @@ class User implements UserInterface
*/
private $password;
+ /**
+ * @ORM\OneToMany(targetEntity=Project::class, mappedBy="author")
+ */
+ private $projects;
+
+ public function __construct()
+ {
+ $this->projects = new ArrayCollection();
+ }
+
public function __toString()
{
return $this->getUsername();
diff --git a/src/Form/ProjectType.php b/src/Form/ProjectType.php
new file mode 100644
index 0000000..38b9536
--- /dev/null
+++ b/src/Form/ProjectType.php
@@ -0,0 +1,22 @@
+add('keyProject', TextType::class)
+ ->add('name', TextType::class)
+ ->add('save', SubmitType::class)
+ ;
+ }
+}
diff --git a/src/Repository/ProjectRepository.php b/src/Repository/ProjectRepository.php
new file mode 100644
index 0000000..efbb0a6
--- /dev/null
+++ b/src/Repository/ProjectRepository.php
@@ -0,0 +1,87 @@
+getEntityManager()->getRepository(Project::class)
+ ->findAll();
+ }
+ $filter['author'] = $id;
+
+ return $this->getEntityManager()->getRepository(Project::class)->findBy($filter);
+ }
+
+ /**
+ * @throws ORMException
+ * @throws OptimisticLockException
+ */
+ public function add(Project $entity, bool $flush = true): void
+ {
+ $this->_em->persist($entity);
+ if ($flush) {
+ $this->_em->flush();
+ }
+ }
+
+ /**
+ * @throws ORMException
+ * @throws OptimisticLockException
+ */
+ public function remove(Project $entity, bool $flush = true): void
+ {
+ $this->_em->remove($entity);
+ if ($flush) {
+ $this->_em->flush();
+ }
+ }
+
+ // /**
+ // * @return Project[] Returns an array of Project objects
+ // */
+ /*
+ public function findByExampleField($value)
+ {
+ return $this->createQueryBuilder('p')
+ ->andWhere('p.exampleField = :val')
+ ->setParameter('val', $value)
+ ->orderBy('p.id', 'ASC')
+ ->setMaxResults(10)
+ ->getQuery()
+ ->getResult()
+ ;
+ }
+ */
+
+ /*
+ public function findOneBySomeField($value): ?Project
+ {
+ return $this->createQueryBuilder('p')
+ ->andWhere('p.exampleField = :val')
+ ->setParameter('val', $value)
+ ->getQuery()
+ ->getOneOrNullResult()
+ ;
+ }
+ */
+}
diff --git a/src/Type/TaskType.php b/src/Type/TaskType.php
index 3b58193..488602a 100644
--- a/src/Type/TaskType.php
+++ b/src/Type/TaskType.php
@@ -2,7 +2,10 @@
namespace App\Type;
+use App\Entity\Project;
+use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
@@ -19,6 +22,10 @@ public function buildForm(FormBuilderInterface $builder, array $options)
->add('dueDate', DateType::class, [
'years' => range(2022,2023)
])
+ ->add('Project', EntityType::class, [
+ 'class' => Project::class,
+ 'choice_label' => 'name',
+ ])
->add('save', SubmitType::class)
;
}
diff --git a/templates/project/create.html.twig b/templates/project/create.html.twig
new file mode 100644
index 0000000..d8d1a08
--- /dev/null
+++ b/templates/project/create.html.twig
@@ -0,0 +1,16 @@
+{% extends 'base.html.twig' %}
+
+{% block body %}
+
+
+
+
+
+
+ {{ form(form, {'action': path('project_create'), 'method': 'POST'}) }}
+
+
+
+
+
+{% endblock %}
diff --git a/templates/project/list.html.twig b/templates/project/list.html.twig
new file mode 100644
index 0000000..d4a920f
--- /dev/null
+++ b/templates/project/list.html.twig
@@ -0,0 +1,39 @@
+{% extends 'base.html.twig' %}
+
+{% block body %}
+
+
+
+
+
+
+
+
+ | # |
+ id |
+ Название |
+ Автор |
+ Действия |
+
+
+
+ {% for project in projects %}
+
+ | {{ project.id }} |
+ {{ project.keyProject }} |
+ {{ project.name }} |
+ {{ project.author }} |
+
+ {% endfor %}
+
+
+
+
Make project
+
Go to task list
+
+
+
+
+
+
+{% endblock %}
diff --git a/templates/project/show.html.twig b/templates/project/show.html.twig
new file mode 100644
index 0000000..3ce8be4
--- /dev/null
+++ b/templates/project/show.html.twig
@@ -0,0 +1,45 @@
+{% extends 'base.html.twig' %}
+
+{% block body %}
+
+
+
+
+
+
+
+
+ | # |
+ Название |
+ Описание |
+ Срок выполнения |
+ Автор |
+ Выполнена |
+ Действия |
+
+
+
+ {% for task in tasks %}
+
+ | {{ task.id }} |
+ {{ task.name }} |
+ {{ task.description }} |
+ {{ task.dueDate|date("d.m.Y") }} |
+ {{ task.author }} |
+ {{ task.isCompleted ? 'Выполнена' : 'Не выполнена' }} |
+
+ {% if (is_granted("complete", task)) %}
+ Сделано
+ {% endif %}
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/task/list.html.twig b/templates/task/list.html.twig
index 0d50fd4..91ae845 100644
--- a/templates/task/list.html.twig
+++ b/templates/task/list.html.twig
@@ -15,6 +15,7 @@
Описание |
Срок выполнения |
Автор |
+ Проект |
Выполнена |
Действия |
@@ -27,6 +28,7 @@
{{ task.description }} |
{{ task.dueDate|date("d.m.Y") }} |
{{ task.author }} |
+ {{ task.project.name }} |
{{ task.isCompleted ? 'Выполнена' : 'Не выполнена' }} |
{% if (is_granted("complete", task)) %}
@@ -38,8 +40,8 @@
- Создать задачу
-
+ Создать задачу
+ Go to project list
|