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 %} +
+
+
+
+
+ + + + + + + + + + + + {% for project in projects %} + + + + + + + {% endfor %} + +
#idНазваниеАвторДействия
{{ project.id }}{{ project.keyProject }}{{ project.name }}{{ project.author }}
+ + 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 %} + + + + + + + + + + {% endfor %} + +
#НазваниеОписаниеСрок выполненияАвторВыполненаДействия
{{ task.id }}{{ task.name }}{{ task.description }}{{ task.dueDate|date("d.m.Y") }}{{ task.author }}{{ task.isCompleted ? 'Выполнена' : 'Не выполнена' }} + {% if (is_granted("complete", task)) %} + Сделано + {% endif %} +
+ +
+
+
+
+
+{% 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