From: Raphaël Gertz Date: Fri, 25 Oct 2019 14:33:24 +0000 (+0200) Subject: Initial import X-Git-Tag: 0.0.1~2 X-Git-Url: https://git.rapsys.eu/airbundle/commitdiff_plain/f110b8ba20232e0ceeb67390f8e672431868d32d Initial import --- f110b8ba20232e0ceeb67390f8e672431868d32d diff --git a/Controller/DefaultController.php b/Controller/DefaultController.php new file mode 100644 index 0000000..31d4b89 --- /dev/null +++ b/Controller/DefaultController.php @@ -0,0 +1,305 @@ +get('translator'); + + //Set section + $section = $trans->trans('Contact'); + + //Set title + $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title')); + + //Create the form according to the FormType created previously. + //And give the proper parameters + $form = $this->createForm('Rapsys\AirBundle\Form\ContactType', null, [ + // To set the action use $this->generateUrl('route_identifier') + 'action' => $this->generateUrl('rapsys_air_contact'), + 'method' => 'POST' + ]); + + if ($request->isMethod('POST')) { + // Refill the fields in case the form is not valid. + $form->handleRequest($request); + + if ($form->isValid()) { + //Get data + $data = $form->getData(); + + //Get contact name + $contactName = $this->getParameter('rapsys_air.contact_name'); + + //Get contact mail + $contactMail = $this->getParameter('rapsys_air.contact_mail'); + + //Get logo + $logo = $this->getParameter('rapsys_air.logo'); + + //Get title + $title = $trans->trans($this->getParameter('rapsys_air.title')); + + //Get subtitle + $subtitle = $trans->trans('Hi,').' '.$contactName; + + $message = \Swift_Message::newInstance() + ->setSubject($data['subject']) + ->setFrom([$data['mail'] => $data['name']]) + ->setTo([$contactMail => $contactName]) + ->setBody($data['message']) + ->addPart( + $this->renderView( + '@RapsysAir/mail/generic.html.twig', + [ + 'logo' => $logo, + 'title' => $title, + 'subtitle' => $subtitle, + 'home' => $this->get('router')->generate('rapsys_air_homepage', [], UrlGeneratorInterface::ABSOLUTE_URL), + 'subject' => $data['subject'], + 'contact_name' => $contactName, + 'message' => strip_tags($data['message']) + ] + ), + 'text/html' + ); + //Send message + if ($this->get('mailer')->send($message)) { + //Redirect to cleanup the form + return $this->redirectToRoute('rapsys_air_contact', ['sent' => 1]); + } + } + } + + //Render template + return $this->render('@RapsysAir/form/contact.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]); + } + + public function indexAction() { + //Get translator + $trans = $this->get('translator'); + + //Set section + $section = $trans->trans('Index'); + + //Set title + $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title')); + + return $this->render('@RapsysAir/page/index.html.twig', ['title' => $title, 'section' => $section]); + } + + public function adminAction(Request $request) { + $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!'); + + //Get translator + $trans = $this->get('translator'); + + //Set section + $section = $trans->trans('Admin'); + + //Set title + $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title')); + + //Create the form according to the FormType created previously. + //And give the proper parameters + $form = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [ + // To set the action use $this->generateUrl('route_identifier') + 'action' => $this->generateUrl('rapsys_air_admin'), + 'method' => 'POST', + 'attr' => [ 'class' => 'form_col' ] + ]); + + //Get doctrine + $doctrine = $this->getDoctrine(); + + //Handle request + if ($request->isMethod('POST')) { + // Refill the fields in case the form is not valid. + $form->handleRequest($request); + + if ($form->isValid()) { + //Get data + $data = $form->getData(); + + //Get manager + $manager = $doctrine->getManager(); + + //Protect session fetching + try { + $session = $doctrine->getRepository(Session::class)->findOneByLocationSlotDate($data['location'], $data['slot'], $data['date']); + //Catch no session case + } catch (\Doctrine\ORM\NoResultException $e) { + //Create the session + $session = new Session(); + $session->setLocation($data['location']); + $session->setSlot($data['slot']); + $session->setDate($data['date']); + $session->setCreated(new \DateTime('now')); + $session->setUpdated(new \DateTime('now')); + $manager->persist($session); + //Flush to get the ids + #$manager->flush(); + } + + //Init application + $application = false; + + //Protect application fetching + try { + //TODO: handle admin case where we provide a user in extra + $application = $doctrine->getRepository(Application::class)->findOneBySessionUser($session, $this->getUser()); + + //Add error message to mail field + $form->get('slot')->addError(new FormError($trans->trans('Application already exists'))); + //Catch no application cases + //XXX: combine these catch when php 7.1 is available + } catch (\Doctrine\ORM\NoResultException $e) { + //Catch invalid argument because session is not already persisted + } catch(\Doctrine\ORM\ORMInvalidArgumentException $e) { + } + + //Create new application if none found + if (!$application) { + //Create the application + $application = new Application(); + $application->setSession($session); + //TODO: handle admin case where we provide a user in extra + $application->setUser($this->getUser()); + $application->setCreated(new \DateTime('now')); + $application->setUpdated(new \DateTime('now')); + $manager->persist($application); + + //Flush to get the ids + $manager->flush(); + + //Add notice in flash message + $this->addFlash('notice', $trans->trans('Application request the %date% for %location% on the slot %slot% saved', ['%location%' => $data['location']->getTitle(), '%slot%' => $data['slot']->getTitle(), '%date%' => $data['date']->format('Y-m-d')])); + + //Redirect to cleanup the form + return $this->redirectToRoute('rapsys_air_admin'); + } + } + } + + //Compute period + $period = new \DatePeriod( + //Start from first monday of week + new \DateTime('Monday this week'), + //Iterate on each day + new \DateInterval('P1D'), + //End with next sunday and 4 weeks + new \DateTime('Monday this week + 5 week') + ); + + //Fetch sessions + $sessions = $doctrine->getRepository(Session::class)->findByDatePeriod($period); + + //Init calendar + $calendar = []; + + //Init month + $month = null; + + //Iterate on each day + foreach($period as $date) { + //Init day in calendar + $calendar[$Ymd = $date->format('Ymd')] = [ + 'title' => $date->format('d'), + 'class' => [], + 'sessions' => [] + ]; + //Append month for first day of month + if ($month != $date->format('m')) { + $month = $date->format('m'); + $calendar[$Ymd]['title'] .= '/'.$month; + } + //Deal with today + if ($date->format('U') == ($today = strtotime('today'))) { + $calendar[$Ymd]['title'] .= '/'.$month; + $calendar[$Ymd]['current'] = true; + $calendar[$Ymd]['class'][] = 'current'; + } + //Disable passed days + if ($date->format('U') < $today) { + $calendar[$Ymd]['disabled'] = true; + $calendar[$Ymd]['class'][] = 'disabled'; + } + //Set next month days + if ($date->format('m') > date('m')) { + $calendar[$Ymd]['next'] = true; + $calendar[$Ymd]['class'][] = 'next'; + } + //Iterate on each session to find the one of the day + foreach($sessions as $session) { + if (($sessionYmd = $session->getDate()->format('Ymd')) == $Ymd) { + //Count number of application + $count = count($session->getApplications()); + + //Compute classes + $class = []; + if ($session->getApplication()) { + $class[] = 'granted'; + } elseif ($count == 0) { + $class[] = 'orphaned'; + } elseif ($count > 1) { + $class[] = 'disputed'; + } else { + $class[] = 'pending'; + } + + //Add the session + $calendar[$Ymd]['sessions'][$session->getSlot()->getId().$session->getLocation()->getId()] = [ + 'id' => $session->getId(), + 'title' => ($count > 1?'['.$count.'] ':'').$session->getSlot()->getTitle().' '.$session->getLocation()->getTitle(), + 'class' => $class + ]; + } + } + + //Sort sessions + ksort($calendar[$Ymd]['sessions']); + } + + return $this->render('@RapsysAir/admin/index.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'calendar' => $calendar]); + } + + public function sessionAction(Request $request, $id) { + /*header('Content-Type: text/plain'); + var_dump($calendar); + exit;*/ + + //Get translator + $trans = $this->get('translator'); + + //Set section + $section = $trans->trans('Session %id%', ['%id%' => $id]); + + //Set title + $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title')); + + //Create the form according to the FormType created previously. + //And give the proper parameters + /*$form = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [ + // To set the action use $this->generateUrl('route_identifier') + 'action' => $this->generateUrl('rapsys_air_admin'), + 'method' => 'POST', + 'attr' => [ 'class' => 'form_col' ] + ]);*/ + + //Get doctrine + $doctrine = $this->getDoctrine(); + + //Fetch session + $session = $doctrine->getRepository(Session::class)->findOneById($id); + + return $this->render('@RapsysAir/admin/session.html.twig', ['title' => $title, 'section' => $section, /*'form' => $form->createView(),*/ 'session' => $session]); + } +} diff --git a/DataFixtures/AirFixtures.php b/DataFixtures/AirFixtures.php new file mode 100644 index 0000000..cfaaa62 --- /dev/null +++ b/DataFixtures/AirFixtures.php @@ -0,0 +1,246 @@ +container = $container; + } + + /** + * {@inheritDoc} + */ + public function load(\Doctrine\Common\Persistence\ObjectManager $manager) { + $encoder = $this->container->get('security.password_encoder'); + + //Title tree + $titleTree = array( + 'M.' => 'Monsieur', + 'Mlle' => 'Mademoiselle', + 'Mme' => 'Madame' + ); + + //Create titles + $titles = array(); + foreach($titleTree as $shortData => $titleData) { + $title = new Title(); + $title->setShort($shortData); + $title->setTitle($titleData); + $title->setCreated(new \DateTime('now')); + $title->setUpdated(new \DateTime('now')); + $manager->persist($title); + $titles[$shortData] = $title; + unset($title); + } + + //Group tree + $groupTree = array( + 'ROLE_USER', + 'ROLE_ADMIN', + 'ROLE_SUPER' + ); + + //Create groups + $groups = array(); + foreach($groupTree as $groupData) { + $group = new Group($groupData); + $group->setCreated(new \DateTime('now')); + $group->setUpdated(new \DateTime('now')); + $manager->persist($group); + $groups[$groupData] = $group; + unset($group); + } + + //Flush to get the ids + $manager->flush(); + + //User tree + $userTree = array( + array( + 'short' => 'M.', + 'group' => 'ROLE_SUPER', + 'mail' => 'airlibre@rapsys.eu', + 'pseudonym' => 'Rapsys', + 'forename' => 'Raphaël', + 'surname' => 'Gertz', + 'password' => 'test' + ), + array( + 'short' => 'M.', + 'group' => 'ROLE_ADMIN', + 'mail' => 'rannou402@orange.fr', + 'pseudonym' => 'Mitch', + 'forename' => 'Michel', + 'surname' => 'Rannou', + 'password' => 'test' + ), + array( + 'short' => 'Mlle', + 'group' => 'ROLE_ADMIN', + 'mail' => 'roxmaps@gmail.com', + 'pseudonym' => 'Roxana', + 'forename' => 'Roxana', + 'surname' => 'Prado', + 'password' => 'test' + ), + array( + 'short' => 'M.', + 'group' => 'ROLE_ADMIN', + 'mail' => 'majid.ghedjatti@gmail.com', + 'pseudonym' => 'El Guerrillero', + 'forename' => 'Majid', + 'surname' => 'Ghedjatti', + 'password' => 'test' + ), + array( + 'short' => 'M.', + 'group' => 'ROLE_ADMIN', + 'mail' => 'denis.courvoisier@wanadoo.fr', + 'pseudonym' => 'Sined', + 'forename' => 'Denis', + 'surname' => 'Courvoisier', + 'password' => 'test' + ), + array( + 'short' => 'M.', + 'group' => 'ROLE_ADMIN', + 'mail' => 'kastango13@gmail.com', + 'pseudonym' => 'Kastrat', + 'forename' => 'Kastrat', + 'surname' => 'Hasaj', + 'password' => 'test' + ), + ); + + //Create users + $users = array(); + foreach($userTree as $userData) { + $user = new User(); + $user->setMail($userData['mail']); + $user->setPseudonym($userData['pseudonym']); + $user->setForename($userData['forename']); + $user->setSurname($userData['surname']); + $user->setPassword($encoder->encodePassword($user, $userData['password'])); + $user->setActive(true); + $user->setTitle($titles[$userData['short']]); + $user->addGroup($groups[$userData['group']]); + $user->setCreated(new \DateTime('now')); + $user->setUpdated(new \DateTime('now')); + $manager->persist($user); + $users[] = $user; + unset($user); + } + + //Flush to get the ids + $manager->flush(); + + //Location tree + $locationTree = [ + [ + 'title' => 'Esplanade du Trocadéro', + 'address' => '1 Avenue Hussein 1er de Jordanie', + #75016 pour meteo-france, accuweather supporte 75116 + 'zipcode' => '75116', + 'city' => 'Paris', + 'latitude' => 48.8619, + 'longitude' => 2.2888 + ], + [ + 'title' => 'Opéra Garnier', + 'address' => 'Place de l\'Opéra', + 'zipcode' => '75009', + 'city' => 'Paris', + 'latitude' => 48.871365, + 'longitude' => 2.332026 + ], + [ + 'title' => 'Marché Saint Honoré', + 'address' => '1 Passage des Jacobins', + 'zipcode' => '75001', + 'city' => 'Paris', + 'latitude' => 48.8668, + 'longitude' => 2.331659 + ], + [ + 'title' => 'Jardin Tino-Rossi', + 'address' => '2 Quai Saint-Bernard', + 'zipcode' => '75005', + 'city' => 'Paris', + 'latitude' => 48.847736, + 'longitude' => 2.360953 + ], + [ + 'title' => 'Palais de Tokyo', + 'address' => '13 Avenue du Président Wilson', + 'zipcode' => '75116', + 'city' => 'Paris', + 'latitude' => 48.864567, + 'longitude' => 2.296892 + ] + ]; + + //Create locations + $locations = array(); + foreach($locationTree as $locationData) { + $location = new Location(); + $location->setTitle($locationData['title']); + $location->setAddress($locationData['address']); + $location->setZipcode($locationData['zipcode']); + $location->setCity($locationData['city']); + $location->setLatitude($locationData['latitude']); + $location->setLongitude($locationData['longitude']); + $location->setCreated(new \DateTime('now')); + $location->setUpdated(new \DateTime('now')); + $manager->persist($location); + $locations[$locationData['title']] = $location; + unset($location); + } + + //Flush to get the ids + $manager->flush(); + + //Slot tree + $slotTree = [ + [ + 'begin' => '14:00:00 UTC', + 'end' => '19:00:00 UTC' + ], + [ + 'begin' => '19:00:00 UTC', + 'end' => '23:00:00 UTC' + ], + [ + 'begin' => '23:00:00 UTC', + 'end' => '02:00:00 UTC' + ] + ]; + + //Create slots + $slots = array(); + foreach($slotTree as $slotData) { + $slot = new Slot(); + $slot->setBegin(new \DateTime($slotData['begin'])); + $slot->setEnd(new \DateTime($slotData['end'])); + $slot->setCreated(new \DateTime('now')); + $slot->setUpdated(new \DateTime('now')); + $manager->persist($slot); + $slots[$slot->getId()] = $slot; + unset($slot); + } + + //Flush to get the ids + $manager->flush(); + } +} diff --git a/DependencyInjection/RapsysAirExtension.php b/DependencyInjection/RapsysAirExtension.php new file mode 100644 index 0000000..5a2bdff --- /dev/null +++ b/DependencyInjection/RapsysAirExtension.php @@ -0,0 +1,46 @@ +load('services.yml'); + + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + //Set default config in parameter + if (!$container->hasParameter($alias = $this->getAlias())) { + $container->setParameter($alias, $config[$alias]); + } else { + $config[$alias] = $container->getParameter($alias); + } + + //Transform the one level tree in flat parameters + foreach($config[$alias] as $k => $v) { + //Set is as parameters + $container->setParameter($alias.'.'.$k, $v); + } + } + + /** + * {@inheritdoc} + */ + public function getAlias() { + return 'rapsys_air'; + } +} diff --git a/Entity/Application.php b/Entity/Application.php new file mode 100644 index 0000000..c157132 --- /dev/null +++ b/Entity/Application.php @@ -0,0 +1,187 @@ +votes = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** + * Get id + * + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * Set created + * + * @param \DateTime $created + * + * @return Application + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created + * + * @return \DateTime + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated + * + * @param \DateTime $updated + * + * @return Application + */ + public function setUpdated($updated) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated + * + * @return \DateTime + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * Add vote + * + * @param \Rapsys\AirBundle\Entity\Vote $vote + * + * @return Application + */ + public function addVote(\Rapsys\AirBundle\Entity\Vote $vote) + { + $this->votes[] = $vote; + + return $this; + } + + /** + * Remove vote + * + * @param \Rapsys\AirBundle\Entity\Vote $vote + */ + public function removeVote(\Rapsys\AirBundle\Entity\Vote $vote) + { + $this->votes->removeElement($vote); + } + + /** + * Get votes + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getVotes() + { + return $this->votes; + } + + /** + * Set session + * + * @param \Rapsys\AirBundle\Entity\Session $session + * + * @return Application + */ + public function setSession(\Rapsys\AirBundle\Entity\Session $session = null) + { + $this->session = $session; + + return $this; + } + + /** + * Get session + * + * @return \Rapsys\AirBundle\Entity\Session + */ + public function getSession() + { + return $this->session; + } + + /** + * Set user + * + * @param \Rapsys\AirBundle\Entity\User $user + * + * @return Application + */ + public function setUser(\Rapsys\AirBundle\Entity\User $user = null) + { + $this->user = $user; + + return $this; + } + + /** + * Get user + * + * @return \Rapsys\AirBundle\Entity\User + */ + public function getUser() + { + return $this->user; + } +} diff --git a/Entity/Group.php b/Entity/Group.php new file mode 100644 index 0000000..3ccf6ee --- /dev/null +++ b/Entity/Group.php @@ -0,0 +1,6 @@ +sessions = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** + * Get id + * + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * Set title + * + * @param string $title + * + * @return Location + */ + public function setTitle($title) + { + $this->title = $title; + + return $this; + } + + /** + * Get title + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Set address + * + * @param string $address + * + * @return Location + */ + public function setAddress($address) + { + $this->address = $address; + + return $this; + } + + /** + * Get address + * + * @return string + */ + public function getAddress() + { + return $this->address; + } + + /** + * Set zipcode + * + * @param string $zipcode + * + * @return Location + */ + public function setZipcode($zipcode) + { + $this->zipcode = $zipcode; + + return $this; + } + + /** + * Get zipcode + * + * @return string + */ + public function getZipcode() + { + return $this->zipcode; + } + + /** + * Set city + * + * @param string $city + * + * @return Location + */ + public function setCity($city) + { + $this->city = $city; + + return $this; + } + + /** + * Get city + * + * @return string + */ + public function getCity() + { + return $this->city; + } + + /** + * Set latitude + * + * @param string $latitude + * + * @return Location + */ + public function setLatitude($latitude) + { + $this->latitude = $latitude; + + return $this; + } + + /** + * Get latitude + * + * @return string + */ + public function getLatitude() + { + return $this->latitude; + } + + /** + * Set longitude + * + * @param string $longitude + * + * @return Location + */ + public function setLongitude($longitude) + { + $this->longitude = $longitude; + + return $this; + } + + /** + * Get longitude + * + * @return string + */ + public function getLongitude() + { + return $this->longitude; + } + + /** + * Set created + * + * @param \DateTime $created + * + * @return Location + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created + * + * @return \DateTime + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated + * + * @param \DateTime $updated + * + * @return Location + */ + public function setUpdated($updated) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated + * + * @return \DateTime + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * Add session + * + * @param \Rapsys\AirBundle\Entity\Session $session + * + * @return Location + */ + public function addSession(\Rapsys\AirBundle\Entity\Session $session) + { + $this->sessions[] = $session; + + return $this; + } + + /** + * Remove session + * + * @param \Rapsys\AirBundle\Entity\Session $session + */ + public function removeSession(\Rapsys\AirBundle\Entity\Session $session) + { + $this->sessions->removeElement($session); + } + + /** + * Get sessions + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getSessions() + { + return $this->sessions; + } +} + diff --git a/Entity/Session.php b/Entity/Session.php new file mode 100644 index 0000000..72d1f33 --- /dev/null +++ b/Entity/Session.php @@ -0,0 +1,281 @@ +applications = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** + * Get id + * + * @return integer + */ + public function getId() { + return $this->id; + } + + /** + * Set date + * + * @param \DateTime $date + * + * @return Session + */ + public function setDate($date) { + $this->date = $date; + + return $this; + } + + /** + * Get date + * + * @return \DateTime + */ + public function getDate() { + return $this->date; + } + + /** + * Set begin + * + * @param \DateTime $begin + * + * @return Session + */ + public function setBegin($begin) { + $this->begin = $begin; + + return $this; + } + + /** + * Get begin + * + * @return \DateTime + */ + public function getBegin() { + return $this->begin; + } + + /** + * Set end + * + * @param \DateTime $end + * + * @return Session + */ + public function setEnd($end) { + $this->end = $end; + + return $this; + } + + /** + * Get end + * + * @return \DateTime + */ + public function getEnd() { + return $this->end; + } + + /** + * Set created + * + * @param \DateTime $created + * + * @return Session + */ + public function setCreated($created) { + $this->created = $created; + + return $this; + } + + /** + * Get created + * + * @return \DateTime + */ + public function getCreated() { + return $this->created; + } + + /** + * Set updated + * + * @param \DateTime $updated + * + * @return Session + */ + public function setUpdated($updated) { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated + * + * @return \DateTime + */ + public function getUpdated() { + return $this->updated; + } + + /** + * Add application + * + * @param \Rapsys\AirBundle\Entity\Application $application + * + * @return Session + */ + public function addApplication(\Rapsys\AirBundle\Entity\Application $application) { + $this->applications[] = $application; + + return $this; + } + + /** + * Remove application + * + * @param \Rapsys\AirBundle\Entity\Application $application + */ + public function removeApplication(\Rapsys\AirBundle\Entity\Application $application) { + $this->applications->removeElement($application); + } + + /** + * Get applications + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getApplications() { + return $this->applications; + } + + /** + * Set location + * + * @param \Rapsys\AirBundle\Entity\Location $location + * + * @return Session + */ + public function setLocation(\Rapsys\AirBundle\Entity\Location $location = null) { + $this->location = $location; + + return $this; + } + + /** + * Get location + * + * @return \Rapsys\AirBundle\Entity\Location + */ + public function getLocation() { + return $this->location; + } + /** + * @var \Rapsys\AirBundle\Entity\Slot + */ + private $slot; + + + /** + * Set slot + * + * @param \Rapsys\AirBundle\Entity\Slot $slot + * + * @return Session + */ + public function setSlot(\Rapsys\AirBundle\Entity\Slot $slot = null) { + $this->slot = $slot; + + return $this; + } + + /** + * Get slot + * + * @return \Rapsys\AirBundle\Entity\Slot + */ + public function getSlot() { + return $this->slot; + } + + /** + * Set application + * + * @param \Rapsys\AirBundle\Entity\Application $application + * + * @return Session + */ + public function setApplication(\Rapsys\AirBundle\Entity\Application $application = null) { + $this->application = $application; + + return $this; + } + + /** + * Get application + * + * @return \Rapsys\AirBundle\Entity\Application + */ + public function getApplication() { + return $this->application; + } +} diff --git a/Entity/Slot.php b/Entity/Slot.php new file mode 100644 index 0000000..03bfd3f --- /dev/null +++ b/Entity/Slot.php @@ -0,0 +1,191 @@ +sessions = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** + * Get id + * + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * Set begin + * + * @param \DateTime $begin + * + * @return Slot + */ + public function setBegin($begin) + { + $this->begin = $begin; + + return $this; + } + + /** + * Get begin + * + * @return \DateTime + */ + public function getBegin() + { + return $this->begin; + } + + /** + * Set end + * + * @param \DateTime $end + * + * @return Slot + */ + public function setEnd($end) + { + $this->end = $end; + + return $this; + } + + /** + * Get end + * + * @return \DateTime + */ + public function getEnd() + { + return $this->end; + } + + /** + * Set created + * + * @param \DateTime $created + * + * @return Slot + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created + * + * @return \DateTime + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated + * + * @param \DateTime $updated + * + * @return Slot + */ + public function setUpdated($updated) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated + * + * @return \DateTime + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * Add session + * + * @param \Rapsys\AirBundle\Entity\Session $session + * + * @return Slot + */ + public function addSession(\Rapsys\AirBundle\Entity\Session $session) + { + $this->sessions[] = $session; + + return $this; + } + + /** + * Remove session + * + * @param \Rapsys\AirBundle\Entity\Session $session + */ + public function removeSession(\Rapsys\AirBundle\Entity\Session $session) + { + $this->sessions->removeElement($session); + } + + /** + * Get sessions + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getSessions() + { + return $this->sessions; + } + + public function getTitle() { + return $this->begin->format('H:i').'-'.$this->end->format('H:i'); + } +} diff --git a/Entity/Title.php b/Entity/Title.php new file mode 100644 index 0000000..54a6a60 --- /dev/null +++ b/Entity/Title.php @@ -0,0 +1,7 @@ +votes[] = $vote; + + return $this; + } + + /** + * Remove vote + * + * @param \Rapsys\AirBundle\Entity\Vote $vote + */ + public function removeVote(\Rapsys\AirBundle\Entity\Vote $vote) { + $this->votes->removeElement($vote); + } + + /** + * Get votes + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getVotes() { + return $this->votes; + } + + /** + * Add application + * + * @param \Rapsys\AirBundle\Entity\Application $application + * + * @return User + */ + public function addApplication(\Rapsys\AirBundle\Entity\Application $application) { + $this->applications[] = $application; + + return $this; + } + + /** + * Remove application + * + * @param \Rapsys\AirBundle\Entity\Application $application + */ + public function removeApplication(\Rapsys\AirBundle\Entity\Application $application) { + $this->applications->removeElement($application); + } + + /** + * Get applications + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getApplications() { + return $this->applications; + } +} diff --git a/Entity/Vote.php b/Entity/Vote.php new file mode 100644 index 0000000..7b2fb53 --- /dev/null +++ b/Entity/Vote.php @@ -0,0 +1,141 @@ +id; + } + + /** + * Set created + * + * @param \DateTime $created + * + * @return Vote + */ + public function setCreated($created) + { + $this->created = $created; + + return $this; + } + + /** + * Get created + * + * @return \DateTime + */ + public function getCreated() + { + return $this->created; + } + + /** + * Set updated + * + * @param \DateTime $updated + * + * @return Vote + */ + public function setUpdated($updated) + { + $this->updated = $updated; + + return $this; + } + + /** + * Get updated + * + * @return \DateTime + */ + public function getUpdated() + { + return $this->updated; + } + + /** + * Set application + * + * @param \Rapsys\AirBundle\Entity\Application $application + * + * @return Vote + */ + public function setApplication(\Rapsys\AirBundle\Entity\Application $application = null) + { + $this->application = $application; + + return $this; + } + + /** + * Get application + * + * @return \Rapsys\AirBundle\Entity\Application + */ + public function getApplication() + { + return $this->application; + } + + /** + * Set user + * + * @param \Rapsys\AirBundle\Entity\User $user + * + * @return Vote + */ + public function setUser(\Rapsys\AirBundle\Entity\User $user = null) + { + $this->user = $user; + + return $this; + } + + /** + * Get user + * + * @return \Rapsys\AirBundle\Entity\User + */ + public function getUser() + { + return $this->user; + } +} diff --git a/Form/ApplicationType.php b/Form/ApplicationType.php new file mode 100644 index 0000000..8439d29 --- /dev/null +++ b/Form/ApplicationType.php @@ -0,0 +1,39 @@ +add('location', EntityType::class, array('class' => 'RapsysAirBundle:Location', 'choice_label' => 'title', 'attr' => array('placeholder' => 'Your location'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your location'))))) + ->add('date', DateType::class, array('attr' => [ 'placeholder' => 'Your date', 'class' => 'date' ], 'html5' => true, 'input' => 'datetime', 'data' => new \DateTime('+7 day'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your date')), new Date(array('message' => 'Your date doesn\'t seems to be valid'))))) + ->add('slot', EntityType::class, array('class' => 'RapsysAirBundle:Slot', 'choice_label' => 'title', 'attr' => array('placeholder' => 'Your slot'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your slot'))))) + ->add('submit', SubmitType::class, array('label' => 'Send', 'attr' => array('class' => 'submit'))); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) { + $resolver->setDefaults(['error_bubbling' => true]); + } + + /** + * {@inheritdoc} + */ + public function getName() { + return 'rapsys_air_application'; + } +} diff --git a/Form/ContactType.php b/Form/ContactType.php new file mode 100644 index 0000000..e9a5ba1 --- /dev/null +++ b/Form/ContactType.php @@ -0,0 +1,40 @@ +add('name', TextType::class, array('attr' => array('placeholder' => 'Your name'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your name'))))) + ->add('subject', TextType::class, array('attr' => array('placeholder' => 'Subject'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your subject'))))) + ->add('mail', EmailType::class, array('attr' => array('placeholder' => 'Your mail address'), 'constraints' => array(new NotBlank(array('message' => 'Please provide a valid mail')), new Email(array('message' => 'Your mail doesn\'t seems to be valid'))))) + ->add('message', TextareaType::class, array('attr' => array('placeholder' => 'Your message here', 'cols' => 50, 'rows' => 15), 'constraints' => array(new NotBlank(array('message' => 'Please provide your message'))))) + ->add('submit', SubmitType::class, array('label' => 'Send', 'attr' => array('class' => 'submit'))); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) { + $resolver->setDefaults(['error_bubbling' => true]); + } + + /** + * {@inheritdoc} + */ + public function getName() { + return 'contact_form'; + } +} diff --git a/RapsysAirBundle.php b/RapsysAirBundle.php new file mode 100644 index 0000000..06f1b37 --- /dev/null +++ b/RapsysAirBundle.php @@ -0,0 +1,9 @@ +getEntityManager() + ->createQuery('SELECT a FROM RapsysAirBundle:Application a WHERE (a.session = :session AND a.user = :user)') + ->setParameter('session', $session) + ->setParameter('user', $user) + ->getSingleResult(); + + //Send result + return $ret; + } +} diff --git a/Repository/SessionRepository.php b/Repository/SessionRepository.php new file mode 100644 index 0000000..e295bfd --- /dev/null +++ b/Repository/SessionRepository.php @@ -0,0 +1,45 @@ +getEntityManager() + ->createQuery('SELECT s FROM RapsysAirBundle:Session s WHERE (s.location = :location AND s.slot = :slot AND s.date = :date)') + ->setParameter('location', $location) + ->setParameter('slot', $slot) + ->setParameter('date', $date) + ->getSingleResult(); + + //Send result + return $ret; + } + + /** + * Find sessions by date period + * + * @param $period The date period + */ + public function findByDatePeriod($period) { + //Fetch sessions + $ret = $this->getEntityManager() + ->createQuery('SELECT s FROM RapsysAirBundle:Session s WHERE s.date BETWEEN :begin AND :end') + ->setParameter('begin', $period->getStartDate()) + ->setParameter('end', $period->getEndDate()) + ->getResult(); + + //Send result + return $ret; + } +} diff --git a/Resources/config/doctrine/Application.orm.yml b/Resources/config/doctrine/Application.orm.yml new file mode 100644 index 0000000..aaf461f --- /dev/null +++ b/Resources/config/doctrine/Application.orm.yml @@ -0,0 +1,27 @@ +Rapsys\AirBundle\Entity\Application: + type: entity + repositoryClass: Rapsys\AirBundle\Repository\ApplicationRepository + table: applications + id: + id: + type: integer + generator: + strategy: AUTO + options: + unsigned: true + fields: + created: + type: datetime + updated: + type: datetime + manyToOne: + session: + targetEntity: Rapsys\AirBundle\Entity\Session + inversedBy: applications + user: + targetEntity: Rapsys\AirBundle\Entity\User + inversedBy: applications + oneToMany: + votes: + targetEntity: Rapsys\AirBundle\Entity\Vote + mappedBy: application diff --git a/Resources/config/doctrine/Group.orm.yml b/Resources/config/doctrine/Group.orm.yml new file mode 100644 index 0000000..57f70a9 --- /dev/null +++ b/Resources/config/doctrine/Group.orm.yml @@ -0,0 +1,8 @@ +Rapsys\AirBundle\Entity\Group: + type: entity + #repositoryClass: Rapsys\AirBundle\Repository\GroupRepository + table: groups + manyToMany: + users: + targetEntity: Rapsys\AirBundle\Entity\User + mappedBy: groups diff --git a/Resources/config/doctrine/Location.orm.yml b/Resources/config/doctrine/Location.orm.yml new file mode 100644 index 0000000..86d86db --- /dev/null +++ b/Resources/config/doctrine/Location.orm.yml @@ -0,0 +1,69 @@ +Rapsys\AirBundle\Entity\Location: + type: entity + #repositoryClass: Rapsys\AirBundle\Repository\LocationRepository + table: locations + id: + id: + type: integer + generator: + strategy: AUTO + options: + unsigned: true + fields: + title: + type: string + length: 24 + address: + type: string + length: 32 + zipcode: + type: string + length: 5 + city: + type: string + length: 64 + latitude: + type: decimal + precision: 8 + scale: 6 + longitude: + type: decimal + precision: 9 + scale: 6 + created: + type: datetime + updated: + type: datetime + oneToMany: + sessions: + targetEntity: Rapsys\AirBundle\Entity\Session + mappedBy: location + +# manyToOne: +# title: +# targetEntity: Rapsys\UserBundle\Entity\Title +# inversedBy: users +# manyToMany: +# groups: +# targetEntity: Rapsys\UserBundle\Entity\Group +# inversedBy: users +# joinTable: +# name: groups_users +# +# manyToOne: +# site: +# targetEntity: Rapsys\BlogBundle\Entity\Site +# inversedBy: articles +# author: +# targetEntity: Rapsys\BlogBundle\Entity\Author +# inversedBy: articles +# manyToMany: +# keywords: +# targetEntity: Rapsys\BlogBundle\Entity\Keyword +# inversedBy: articles +# joinTable: +# name: articles_keywords +# oneToMany: +# article_translations: +# targetEntity: Rapsys\BlogBundle\Entity\ArticleTranslation +# mappedBy: article diff --git a/Resources/config/doctrine/Session.orm.yml b/Resources/config/doctrine/Session.orm.yml new file mode 100644 index 0000000..9c89adb --- /dev/null +++ b/Resources/config/doctrine/Session.orm.yml @@ -0,0 +1,41 @@ +Rapsys\AirBundle\Entity\Session: + type: entity + repositoryClass: Rapsys\AirBundle\Repository\SessionRepository + table: sessions + id: + id: + type: integer + generator: + strategy: AUTO + options: + unsigned: true + fields: + date: + type: date + begin: + type: time + nullable: true + end: + type: time + nullable: true + created: + type: datetime + updated: + type: datetime + oneToOne: + application: + targetEntity: Rapsys\AirBundle\Entity\Application + manyToOne: + location: + targetEntity: Rapsys\AirBundle\Entity\Location + inversedBy: sessions + slot: + targetEntity: Rapsys\AirBundle\Entity\Slot + inversedBy: sessions + oneToMany: + applications: + targetEntity: Rapsys\AirBundle\Entity\Application + mappedBy: session + uniqueConstraints: + date_location_slot: + columns: [ date, location_id, slot_id ] diff --git a/Resources/config/doctrine/Slot.orm.yml b/Resources/config/doctrine/Slot.orm.yml new file mode 100644 index 0000000..c4ff511 --- /dev/null +++ b/Resources/config/doctrine/Slot.orm.yml @@ -0,0 +1,24 @@ +Rapsys\AirBundle\Entity\Slot: + type: entity + #repositoryClass: Rapsys\AirBundle\Repository\SlotRepository + table: slots + id: + id: + type: integer + generator: + strategy: AUTO + options: + unsigned: true + fields: + begin: + type: time + end: + type: time + created: + type: datetime + updated: + type: datetime + oneToMany: + sessions: + targetEntity: Rapsys\AirBundle\Entity\Session + mappedBy: slot diff --git a/Resources/config/doctrine/Title.orm.yml b/Resources/config/doctrine/Title.orm.yml new file mode 100644 index 0000000..d68aa60 --- /dev/null +++ b/Resources/config/doctrine/Title.orm.yml @@ -0,0 +1,8 @@ +Rapsys\AirBundle\Entity\Title: + type: entity + #repositoryClass: Rapsys\AirBundle\Repository\TitleRepository + table: titles + oneToMany: + users: + targetEntity: User + mappedBy: title diff --git a/Resources/config/doctrine/User.orm.yml b/Resources/config/doctrine/User.orm.yml new file mode 100644 index 0000000..4df938e --- /dev/null +++ b/Resources/config/doctrine/User.orm.yml @@ -0,0 +1,27 @@ +Rapsys\AirBundle\Entity\User: + type: entity + #repositoryClass: Rapsys\AirBundle\Repository\UserRepository + table: users + oneToMany: + votes: + targetEntity: Rapsys\AirBundle\Entity\Vote + mappedBy: user + applications: + targetEntity: Rapsys\AirBundle\Entity\Application + mappedBy: user +# manyToMany: +# groups: +# targetEntity: Group +# inversedBy: users +# joinTable: +# name: groups_users + associationOverride: + groups: + joinTable: + name: groups_users + joinColumns: + id: + name: user_id + inverseJoinColumns: + id: + name: group_id diff --git a/Resources/config/doctrine/Vote.orm.yml b/Resources/config/doctrine/Vote.orm.yml new file mode 100644 index 0000000..ee8e2ea --- /dev/null +++ b/Resources/config/doctrine/Vote.orm.yml @@ -0,0 +1,23 @@ +Rapsys\AirBundle\Entity\Vote: + type: entity + #repositoryClass: Rapsys\AirBundle\Repository\VoteRepository + table: votes + id: + id: + type: integer + generator: + strategy: AUTO + options: + unsigned: true + fields: + created: + type: datetime + updated: + type: datetime + manyToOne: + application: + targetEntity: Rapsys\AirBundle\Entity\Application + inversedBy: votes + user: + targetEntity: Rapsys\AirBundle\Entity\User + inversedBy: votes diff --git a/Resources/config/routing.yml b/Resources/config/routing.yml new file mode 100644 index 0000000..dd63f57 --- /dev/null +++ b/Resources/config/routing.yml @@ -0,0 +1,17 @@ +rapsys_air_homepage: + path: / + defaults: { _controller: RapsysAirBundle:Default:index } + +rapsys_air_admin: + path: /admin + defaults: { _controller: RapsysAirBundle:Default:admin } + +rapsys_air_contact: + path: /contact + defaults: { _controller: RapsysAirBundle:Default:contact } + +rapsys_air_session: + path: /admin/session/{id} + defaults: { _controller: RapsysAirBundle:Default:session } + requirements: + id: '\d+' diff --git a/Resources/config/services.yml b/Resources/config/services.yml new file mode 100644 index 0000000..9f2f696 --- /dev/null +++ b/Resources/config/services.yml @@ -0,0 +1,15 @@ +services: + rapsys_air.twig.file_get_contents: + class: Rapsys\AirBundle\Twig\FileGetContentsExtension + tags: [ twig.extension ] + rapsys_air.twig.base64: + class: Rapsys\AirBundle\Twig\Base64Extension + tags: [ twig.extension ] + rapsys_air.twig.bb2html: + class: Rapsys\AirBundle\Twig\Bb2htmlExtension + tags: [ twig.extension ] + Rapsys\AirBundle\DataFixtures\AirFixtures: + tags: [ doctrine.fixture.orm ] +# rapsys_air.example: +# class: Rapsys\AirBundle\Example +# arguments: ["@service_id", "plain_value", "%parameter%"] diff --git a/Resources/public/css/reset.css b/Resources/public/css/reset.css new file mode 100644 index 0000000..c59ac50 --- /dev/null +++ b/Resources/public/css/reset.css @@ -0,0 +1,45 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video, input, textarea, button, select, option { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { + display: block; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +blockquote:before, blockquote:after, q:before, q:after { + content: ''; + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/Resources/public/css/screen.css b/Resources/public/css/screen.css new file mode 100644 index 0000000..5477726 --- /dev/null +++ b/Resources/public/css/screen.css @@ -0,0 +1,473 @@ +/* Reset link */ +a { + text-decoration: none; + color: #066; +} + +a:hover { + text-decoration: underline solid #00c3f9; +} + +h1::first-letter, +h2::first-letter, +h3::first-letter, +h4::first-letter, +h5::first-letter, +h6::first-letter, +a::first-letter { + color: #00c3f9; +} + +/* Default styling */ +h1 { + font-size: 2rem; + margin: 1.34rem 0; +} + +h2 { + font-size: 1.5rem; + margin: 1.245rem 0; +} + +h3 { + font-size: 1.17rem; + margin: 1.17rem 0; +} + +h4 { + font-size: 1rem; + margin: 1.33rem 0; +} + +h5 { + font-size: .83rem; + margin: 1.386rem 0; +} + +h6 { + font-size: .67rem; + margin: 1.561rem 0; +} + +p { +} + +body { + display: flex; + flex-flow: column wrap; + color: #066; +} + +/* Header */ +#header { + border: .1rem solid #00c3f9; + border-top: 0; + border-radius: 0 0 .5rem .5rem; + margin: .5rem; + margin-top: 0; + padding: .5rem; + left: 0; + right: 0; + display: flex; + justify-content: space-between; + min-width: 180px; +} + +#header h1 { + order: 0; + padding: 0; + margin: 0; + vertical-align: middle; + white-space: nowrap; +} + +#header h1 a { + display: flex; +} + +/*#header h2 { + order: 1; + font-size: 1.5rem; + margin: 0; + white-space: nowrap; +} + +#header h2:before { + content: ">\00a0"; +}*/ + +#header nav { + order: 3; + margin-left: auto; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; +} + +#header nav h2 { + display: none; +} + +#header nav a { + text-align: center; + border-radius: .25rem; + padding: .375rem .5rem .25rem .5rem; + margin: 0 0 .1rem .5rem; + border: .1rem solid #00c3f9; + font-weight: bold; + background-color: #cff; +} + +/* Message */ +div.error::before, +div.error::after { + content: "⚠"; + line-height: 100%; + margin: auto 0; +} + +div.error { + display: flex; + flex-direction: row; + justify-content: space-between; + border: .05rem solid #c33333; + background-color: #f9c3c3; + color: #c33333; + font-size: .9rem; + padding: .2rem; + border-radius: .2rem; + text-align: center; +} + +div.flash { + margin: 0 .5rem .5rem; +} + +/*ul#error::before, +ul#error::after, +ul.error::before, +ul.error::after, +ul#notice::before, +ul#notice::after { + content: "⚠"; + padding: .1rem .5rem 0 .5rem; + position: absolute; +} + +ul#error::before, +ul#error::after { + padding-top: .2rem; +} + +ul#notice::before, +ul#notice::after { + content: "ℹ"; + padding-top: .3rem; +} + +ul#notice::after, +ul#error::after { + margin-left: 37.8rem; +} + +ul.error::after { + margin-left: 34rem; +} + +ul#notice, +ul#error, +ul.error { + display: flex; + flex-direction: column; + justify-content: center; + box-sizing: border-box; + text-align: center; + border: .05rem solid #c33333; + background-color: #f9c3c3; + color: #c33333; + font-size: .9rem; + padding: .2rem; + border-radius: .2rem; + width: 40rem; + margin: 0 auto .5rem auto; +} + +ul.error { + width: 36rem; + margin: .2rem 0 0 0; +} + +ul#notice { + border: .05rem solid #3333c3; + background-color: #c3c3f9; + color: #3333c3; +} + +ul.error { + margin-top: .2rem; +}*/ + +/* Content */ +#form, +#content, +#dashboard { + border: .1rem solid #00c3f9; + border-radius: .5rem; + margin: .5rem; + margin-top: 0; + overflow: hidden; + padding: .5rem; +} + +section h2 { + background-color: #cff; + border-bottom: .1rem solid #00c3f9; + margin: -.5rem -.5rem .5rem -.5rem; + padding: .5rem; + padding-bottom: .4rem; +} + +/* Form */ +form { + display: flex; + flex-direction: column; + border: .05rem solid #00c3f9; + border-radius: .2rem; + padding: .5rem; +} + +form section { + margin-bottom: 1rem; +} + +form section:only-child, +form section:last-child, +form section:last-of-type { + margin-bottom: .5rem; +} + +form section section, +form section section:only-child, +form section section:last-child, +form section section:last-of-type { + width: 50%; + margin-bottom: 0; +} + +form div { + display: flex; + flex-direction: row; + justify-content: space-around; + margin-bottom: .5rem; +} + +form div:only-child, +form div:last-child, +form div:last-of-type { + margin-bottom: 0; +} + +form section div.error { + margin: 0 1rem; +} + +form section section div.error { + margin: .25rem 0 0 0; +} + +label { + min-width: 5rem; + font-size: .9rem; + padding: .2rem 0; + text-align: right; + white-space: nowrap; +} + +button, +input, +select, +textarea { + box-sizing: border-box; + width: 100%; + padding: .1rem; + border: .05rem solid #00c3f9; + border-radius: .2rem; + font-size: .8rem; + color: #066; +} + +button.submit { + width: 25%; + min-width: 8rem; + margin: 0 auto; + padding: .2rem .1rem; +} + +/* Vertical form */ +.form_col { + margin-left: .5rem; + width: 10rem; +} + +.form_col div { + flex-direction: column; +} + +.form_col div.error { + flex-direction: row; +} + +.form_col label { + text-align: center; +} + +.form_col section section, +.form_col section section:only-child, +.form_col section section:last-child, +.form_col section section:last-of-type { + width: auto; +} + +.form_col div.date { + flex-direction: row; + justify-content: space-between; +} + +/* Dashboard */ +#dashboard .panel { + display: flex; + flex-direction: row; + flex-wrap: wrap; + place-content: space-between; +} + +#dashboard .grid { + display: table; + border: .05rem solid #00c3f9; + flex-grow: 1; + border-radius: .2rem; /* marche pas sur chrome */ + table-layout: fixed; + width: calc(100% - 12rem); + border-collapse: collapse; +} + +#dashboard .cell { + display: table-cell; + text-align: left; + border: .05rem solid #00c3f9; + font-size: initial; + height: 8rem; +} + +#dashboard dl.cell { + height: 3rem; +} + +#dashboard .cell h3 { + font-size: 1rem; + padding: .25rem; + margin: 0; +} + +#dashboard .cell dd { + text-align: center; +} + +#dashboard .seventh { + width: calc(100% / 7); +} + +#dashboard .disabled { + color: #acc; + background-color: #bee; +} + +#dashboard .current { + background-color: #cff; +} + +#dashboard .next { + background-color: #eff; +} + +#dashboard .session { + border-radius: .2rem; + border: .1rem solid #00c3f9; + font-size: .8rem; + padding: .2rem; + margin: 0 .1rem .1rem .1rem; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +#dashboard .pending { + background-color: #ccc; +} + +#dashboard .granted { + background-color: #cff; + /*background-color: #33b679; + border-color: #33b679;*/ +} + +#dashboard .disputed { + background-color: #fcc; +} + +#dashboard .orphaned { + background-color: #fc9; +} + +/* Footer */ +#footer { + border: .1rem solid #00c3f9; + border-radius: .5rem; + margin: .5rem; + margin-top: 0; + padding: .5rem; + text-align: center; + font-size: .8rem; + display: flex; + justify-content: space-between; + background-color: #cff; +} + +#footer details { + font-weight: bold; +} + +#footer summary::after { + display: none; +} + +#footer summary::-webkit-details-marker { + display: none; +} + +/* viewport responsive hack */ +@media ( max-width: 650px ) { + #header { + flex-wrap: wrap; + } + + #dashboard .panel { + place-content: center; + flex-direction: column; + } + + #dashboard .grid { + width: 100%; + } + + #dashboard div.grid { + display: grid; + } + + .form_col { + margin: .5rem auto 0 auto; + } +} + diff --git a/Resources/public/ico/favicon.ico b/Resources/public/ico/favicon.ico new file mode 100644 index 0000000..fb66588 Binary files /dev/null and b/Resources/public/ico/favicon.ico differ diff --git a/Resources/public/png/apple.png b/Resources/public/png/apple.png new file mode 100644 index 0000000..da559cf Binary files /dev/null and b/Resources/public/png/apple.png differ diff --git a/Resources/public/png/favicon.png b/Resources/public/png/favicon.png new file mode 100644 index 0000000..85f7b97 Binary files /dev/null and b/Resources/public/png/favicon.png differ diff --git a/Resources/public/png/logo.png b/Resources/public/png/logo.png new file mode 100644 index 0000000..b57be8c Binary files /dev/null and b/Resources/public/png/logo.png differ diff --git a/Resources/public/svg/favicon.svg b/Resources/public/svg/favicon.svg new file mode 100644 index 0000000..1e196c6 --- /dev/null +++ b/Resources/public/svg/favicon.svg @@ -0,0 +1,95 @@ + + + + + Open Air Logo + + + + + + + + + + + + + image/svg+xml + + Open Air Logo + + + + + + + diff --git a/Resources/public/svg/logo.svg b/Resources/public/svg/logo.svg new file mode 100644 index 0000000..159107f --- /dev/null +++ b/Resources/public/svg/logo.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + pen + + + A + ir + + diff --git a/Resources/public/xcf/openair.xcf b/Resources/public/xcf/openair.xcf new file mode 100644 index 0000000..ebe102b Binary files /dev/null and b/Resources/public/xcf/openair.xcf differ diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml new file mode 100644 index 0000000..40c37fe --- /dev/null +++ b/Resources/translations/messages.fr.yml @@ -0,0 +1,60 @@ +'Outdoor space reservation system': 'Système de réservation d''espace en plein air' +'Open Air': 'Air libre' +Navigation: Navigation +About: 'À propos' +Index: Accueil +Admin: Administration +Contact: Contact +'Raphaël Gertz all rights reserved': 'Raphaël Gertz tous droits réservés' +'Copyright 2018': 'Droit d''auteur 2018' +Send: Envoyer +Subject: Sujet +'Your name': 'Votre nom' +'Your mail address': 'Votre courriel' +'Your message has been sent': 'Votre message a bien été envoyé' +'Your message here': 'Votre message ici' +'Your password': 'Votre mot de passe' +Logout: Déconnection +Register: Enregistrement +Login: Identification +Recover: Récupération +Dashboard: Tableau de bord +'Hi, %name%': 'Salut, %name%' +'Subject:': 'Sujet :' +'Name': 'Nom' +'Message': 'Message' +'Title': 'Civilité' +'Your title': 'Votre civilité' +'Forename': 'Prénom' +'Your forename': 'Votre prénom' +'Surname': 'Nom' +'Your surname': 'Votre nom' +'Pseudonym': 'Pseudonyme' +'Your pseudonym': 'Votre pseudonyme' +'Mail': 'Courriel' +'Password': 'Mot de passe' +'Confirm password': 'Confirmation' +'Your password confirmation': 'Votre confirmation de mot de passe' +'Welcome to %title%': 'Bienvenue sur %title%' +'Thanks so much for joining us, from now on, you can reserve your %title% spaces.': 'Merci de nous avoir rejoint, à partir de maintenant, vous pouvez réserver vos espaces à l''%title%.' +'Your account has been created': 'Votre compte a bien été créé' +'Invalid credentials.': 'Identifiants invalides' +'Thanks so much for joining us, to recover your account you can follow this link: %url%': 'Merci de nous avoir rejoint, pour récupérer votre compte vous pouvez suivre ce lien : %url%' +'Your password is updated and an account recover message has been sent': 'Votre mot de passe est modifié et un message de récupération de compte a été envoyé' +'Unable to find account': 'Impossible de trouver le compte' +'Account already exists: %mail%': 'Le compte existe déjà : %mail%' +'Your recover account message has been sent': 'Votre message de récupération de compte a été envoyé' +'To recover your account click here': 'Pour récupérer votre compte cliquez ici' +'Recover account on %title%': 'Récupération de compte sur %title%' +'Account recovered on %title%': 'Compte récupéré sur %title%' +'Your account password has been changed, to recover your account you can follow this link: %url%': 'Votre mot de passe a été changé, pour récupérer votre compte vous pouvez suivre ce lien : %url%' +'Authentication request could not be processed due to a system problem.': 'Authentification impossible suite à un problème système' +Location: Emplacement +Your location: Votre emplacement +Date: Date +Your date: Votre date +Slot: Créneau +Your slot: Votre créneau +'Application request the %date% for %location% on the slot %slot% saved': 'Réservation le %date% pour %location% sur le créneau %slot% enregistrée' +#'Application request the %date% for %location% on the slot %slot% already exists': 'Réservation le %date% pour %location% sur le créneau %slot% déjà existante' +'Application already exists': 'Réservation déjà existante' diff --git a/Resources/translations/validators.fr.yml b/Resources/translations/validators.fr.yml new file mode 100644 index 0000000..e945217 --- /dev/null +++ b/Resources/translations/validators.fr.yml @@ -0,0 +1,11 @@ +'Please provide your name': 'Veuillez fournir votre nom' +'Please provide your mail': 'Veuillez fournir votre courriel' +'Please provide a valid mail': 'Veuillez fournir un courriel valide' +'Please provide your pseudonym': 'Veuillez fournir votre pseudonyme' +'Please provide your forename': 'Veuillez fournir votre prénom' +'Please provide your surname': 'Veuillez fournir votre nom' +'Please provide your password': 'Veuillez fournir votre mot de passe' +'Please provide your subject': 'Veuillez fournir votre sujet' +'Please provide your message': 'Veuillez fournir votre message' +'The password and confirmation must match': 'Le mot de passe doit correspondre à la confirmation' +'Your mail doesn''t seems to be valid': 'Votre courriel ne semble pas valable' diff --git a/Resources/views/admin/index.html.twig b/Resources/views/admin/index.html.twig new file mode 100644 index 0000000..687e217 --- /dev/null +++ b/Resources/views/admin/index.html.twig @@ -0,0 +1,57 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{% trans %}Dashboard{% endtrans %}

+
+ {% if calendar is defined and calendar %} + + + + {% for date, day in calendar %} + + {% if loop.index % 7 == 0 and not loop.last %} + + + {% endif %} + {% endfor %} + + +
+

{{ day.title }}

+ {% if day.sessions is not empty %} + + {% endif %} +
+ {% endif %} +
+ {{ form_start(form) }} + +
{{ form_errors(form) }}
+ +
+ {{ form_row(form.location) }} + + {{ form_row(form.date) }} + + {{ form_row(form.slot) }} +
+ + {{ form_row(form.submit) }} + + {# Render CSRF token etc .#} +
+ {{ form_rest(form) }} +
+ + {{ form_end(form) }} +
+
+ {# dump(calendar) #} +
+{% endblock %} diff --git a/Resources/views/admin/index.html.twig.toto b/Resources/views/admin/index.html.twig.toto new file mode 100644 index 0000000..d529910 --- /dev/null +++ b/Resources/views/admin/index.html.twig.toto @@ -0,0 +1 @@ +|length > 21 ? session.title|slice(0, 21) ~ '...' : session.title diff --git a/Resources/views/admin/session.html.twig b/Resources/views/admin/session.html.twig new file mode 100644 index 0000000..ef61643 --- /dev/null +++ b/Resources/views/admin/session.html.twig @@ -0,0 +1,31 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{{ section }}

+
+
+
+

{% trans %}Location{% endtrans %}

+
{{ session.location.getTitle() }}
+
+
+

{% trans %}Date{% endtrans %}

+
{{ session.date.format('Y-m-d') }}
+
+
+

{% trans %}Slot{% endtrans %}

+
{{ session.slot.getTitle() }}
+
+
+

{% trans %}Application{% endtrans %}

+ {% if session.application is null %} +
{% trans %}None{% endtrans %}
+ {% else %} +
{{ session.application.getTitle() }}
+ {% endif %} +
+
+
+ {{ dump(session) }} +
+{% endblock %} diff --git a/Resources/views/base.html.twig b/Resources/views/base.html.twig new file mode 100644 index 0000000..a95e21a --- /dev/null +++ b/Resources/views/base.html.twig @@ -0,0 +1,78 @@ + + + + + {% block title %}{{ title }}{% endblock %} + + {% block stylesheet %} + {% stylesheet '//fonts.googleapis.com/css?family=Irish+Grover' '//fonts.googleapis.com/css?family=La+Belle+Aurore' '@RapsysAirBundle/Resources/public/css/{reset,screen}.css' %} + + {% endstylesheet %} + {% endblock %} + + + + + {% block body %} + + {% block header %} + + {% endblock %} + + {# pass an array argument to get the messages of those types (['warning', 'error']) #} + {% for label, messages in app.flashes %} + {% if messages %} +
+ +
+ {% endif %} + {% endfor %} + + {% block sidebar %}{% endblock %} + + {% block content %}
{% endblock %} + + {% block footer %} + + {% endblock %} + + {% endblock %} + diff --git a/Resources/views/form/contact.html.twig b/Resources/views/form/contact.html.twig new file mode 100644 index 0000000..b75b91b --- /dev/null +++ b/Resources/views/form/contact.html.twig @@ -0,0 +1,34 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{{ section }}

+ {% if sent %} +

{% trans %}Your message has been sent{% endtrans %}

+ {% else %} +
+ {{ form_start(form) }} + +
{{ form_errors(form) }}
+ +
+ {{ form_row(form.subject) }} + + {{ form_row(form.name) }} + + {{ form_row(form.mail) }} + + {{ form_row(form.message) }} +
+ + {{ form_row(form.submit) }} + + {# Render CSRF token etc .#} +
+ {{ form_rest(form) }} +
+ + {{ form_end(form) }} +
+ {% endif %} +
+{% endblock %} diff --git a/Resources/views/form/form_div_layout.html.twig b/Resources/views/form/form_div_layout.html.twig new file mode 100644 index 0000000..7f73c51 --- /dev/null +++ b/Resources/views/form/form_div_layout.html.twig @@ -0,0 +1,417 @@ +{# Widgets #} + +{%- block form_widget -%} + {% if compound %} + {{- block('form_widget_compound') -}} + {% else %} + {{- block('form_widget_simple') -}} + {% endif %} +{%- endblock form_widget -%} + +{%- block form_widget_simple -%} + {%- set type = type|default('text') -%} + +{%- endblock form_widget_simple -%} + +{%- block form_widget_compound -%} +
+ {%- if form is rootform -%} + {{ form_errors(form) }} + {%- endif -%} + {{- block('form_rows') -}} + {{- form_rest(form) -}} +
+{%- endblock form_widget_compound -%} + +{%- block collection_widget -%} + {% if prototype is defined %} + {%- set attr = attr|merge({'data-prototype': form_row(prototype) }) -%} + {% endif %} + {{- block('form_widget') -}} +{%- endblock collection_widget -%} + +{%- block textarea_widget -%} + +{%- endblock textarea_widget -%} + +{%- block choice_widget -%} + {% if expanded %} + {{- block('choice_widget_expanded') -}} + {% else %} + {{- block('choice_widget_collapsed') -}} + {% endif %} +{%- endblock choice_widget -%} + +{%- block choice_widget_expanded -%} +
+ {%- for child in form %} + {{- form_widget(child) -}} + {{- form_label(child, null, {translation_domain: choice_translation_domain}) -}} + {% endfor -%} +
+{%- endblock choice_widget_expanded -%} + +{%- block choice_widget_collapsed -%} + {%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%} + {% set required = false %} + {%- endif -%} + +{%- endblock choice_widget_collapsed -%} + +{%- block choice_widget_options -%} + {% for group_label, choice in options %} + {%- if choice is iterable -%} + + {% set options = choice %} + {{- block('choice_widget_options') -}} + + {%- else -%} + + {%- endif -%} + {% endfor %} +{%- endblock choice_widget_options -%} + +{%- block checkbox_widget -%} + +{%- endblock checkbox_widget -%} + +{%- block radio_widget -%} + +{%- endblock radio_widget -%} + +{%- block datetime_widget -%} + {% if widget == 'single_text' %} + {{- block('form_widget_simple') -}} + {%- else -%} +
+ {{- form_errors(form.date) -}} + {{- form_errors(form.time) -}} + {{- form_widget(form.date) -}} + {{- form_widget(form.time) -}} +
+ {%- endif -%} +{%- endblock datetime_widget -%} + +{%- block date_widget -%} + {%- if widget == 'single_text' -%} + {{ block('form_widget_simple') }} + {%- else -%} +
+ {{- date_pattern|replace({ + '{{ year }}': form_widget(form.year), + '{{ month }}': form_widget(form.month), + '{{ day }}': form_widget(form.day), + })|raw -}} +
+ {%- endif -%} +{%- endblock date_widget -%} + +{%- block time_widget -%} + {%- if widget == 'single_text' -%} + {{ block('form_widget_simple') }} + {%- else -%} + {%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%} +
+ {{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %} +
+ {%- endif -%} +{%- endblock time_widget -%} + +{%- block dateinterval_widget -%} + {%- if widget == 'single_text' -%} + {{- block('form_widget_simple') -}} + {%- else -%} +
+ {{- form_errors(form) -}} + + + + {%- if with_years %}{% endif -%} + {%- if with_months %}{% endif -%} + {%- if with_weeks %}{% endif -%} + {%- if with_days %}{% endif -%} + {%- if with_hours %}{% endif -%} + {%- if with_minutes %}{% endif -%} + {%- if with_seconds %}{% endif -%} + + + + + {%- if with_years %}{% endif -%} + {%- if with_months %}{% endif -%} + {%- if with_weeks %}{% endif -%} + {%- if with_days %}{% endif -%} + {%- if with_hours %}{% endif -%} + {%- if with_minutes %}{% endif -%} + {%- if with_seconds %}{% endif -%} + + + + {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} +
+ {%- endif -%} +{%- endblock dateinterval_widget -%} + +{%- block number_widget -%} + {# type="number" doesn't work with floats #} + {%- set type = type|default('text') -%} + {{ block('form_widget_simple') }} +{%- endblock number_widget -%} + +{%- block integer_widget -%} + {%- set type = type|default('number') -%} + {{ block('form_widget_simple') }} +{%- endblock integer_widget -%} + +{%- block money_widget -%} + {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }} +{%- endblock money_widget -%} + +{%- block url_widget -%} + {%- set type = type|default('url') -%} + {{ block('form_widget_simple') }} +{%- endblock url_widget -%} + +{%- block search_widget -%} + {%- set type = type|default('search') -%} + {{ block('form_widget_simple') }} +{%- endblock search_widget -%} + +{%- block percent_widget -%} + {%- set type = type|default('text') -%} + {{ block('form_widget_simple') }} % +{%- endblock percent_widget -%} + +{%- block password_widget -%} + {%- set type = type|default('password') -%} + {{ block('form_widget_simple') }} +{%- endblock password_widget -%} + +{%- block hidden_widget -%} + {%- set type = type|default('hidden') -%} + {{ block('form_widget_simple') }} +{%- endblock hidden_widget -%} + +{%- block email_widget -%} + {%- set type = type|default('email') -%} + {{ block('form_widget_simple') }} +{%- endblock email_widget -%} + +{%- block range_widget -%} + {% set type = type|default('range') %} + {{- block('form_widget_simple') -}} +{%- endblock range_widget %} + +{%- block button_widget -%} + {%- if label is empty -%} + {%- if label_format is not empty -%} + {% set label = label_format|replace({ + '%name%': name, + '%id%': id, + }) %} + {%- elseif label is same as(false) -%} + {% set translation_domain = false %} + {%- else -%} + {% set label = name|humanize %} + {%- endif -%} + {%- endif -%} + +{%- endblock button_widget -%} + +{%- block submit_widget -%} + {%- set type = type|default('submit') -%} + {{ block('button_widget') }} +{%- endblock submit_widget -%} + +{%- block reset_widget -%} + {%- set type = type|default('reset') -%} + {{ block('button_widget') }} +{%- endblock reset_widget -%} + +{%- block tel_widget -%} + {%- set type = type|default('tel') -%} + {{ block('form_widget_simple') }} +{%- endblock tel_widget -%} + +{%- block color_widget -%} + {%- set type = type|default('color') -%} + {{ block('form_widget_simple') }} +{%- endblock color_widget -%} + +{# Labels #} + +{%- block form_label -%} + {% if label is not same as(false) -%} + {% if not compound -%} + {% set label_attr = label_attr|merge({'for': id}) %} + {%- endif -%} + {% if required -%} + {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} + {%- endif -%} + {% if label is empty -%} + {%- if label_format is not empty -%} + {% set label = label_format|replace({ + '%name%': name, + '%id%': id, + }) %} + {%- else -%} + {% set label = name|humanize %} + {%- endif -%} + {%- endif -%} + <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}> + {%- if translation_domain is same as(false) -%} + {{- label -}} + {%- else -%} + {{- label|trans({}, translation_domain) -}} + {%- endif -%} + + {%- endif -%} +{%- endblock form_label -%} + +{%- block button_label -%}{%- endblock -%} + +{# Rows #} + +{%- block repeated_row -%} + {# + No need to render the errors here, as all errors are mapped + to the first child (see RepeatedTypeValidatorExtension). + #} + {{- block('form_rows') -}} +{%- endblock repeated_row -%} + +{%- block form_row -%} +
+ {{- form_label(form) -}} +
+ {{- form_widget(form) -}} + {%- if errors|length > 0 -%} +
+ {{- form_errors(form) -}} +
+ {%- endif -%} +
+
+{%- endblock form_row -%} + +{%- block button_row -%} +
+ {{- form_widget(form) -}} +
+{%- endblock button_row -%} + +{%- block hidden_row -%} + {{ form_widget(form) }} +{%- endblock hidden_row -%} + +{# Misc #} + +{%- block form -%} + {{ form_start(form) }} + {{- form_widget(form) -}} + {{ form_end(form) }} +{%- endblock form -%} + +{%- block form_start -%} + {%- do form.setMethodRendered() -%} + {% set method = method|upper %} + {%- if method in ["GET", "POST"] -%} + {% set form_method = method %} + {%- else -%} + {% set form_method = "POST" %} + {%- endif -%} +
+ {%- if form_method != method -%} + + {%- endif -%} +{%- endblock form_start -%} + +{%- block form_end -%} + {%- if not render_rest is defined or render_rest -%} + {{ form_rest(form) }} + {%- endif -%} +
+{%- endblock form_end -%} + +{%- block form_errors -%} + {%- if errors|length > 0 -%} + + {%- endif -%} +{%- endblock form_errors -%} + +{%- block form_rest -%} + {% for child in form -%} + {% if not child.rendered %} + {{- form_row(child) -}} + {% endif %} + {%- endfor -%} + + {% if not form.methodRendered and form is rootform %} + {%- do form.setMethodRendered() -%} + {% set method = method|upper %} + {%- if method in ["GET", "POST"] -%} + {% set form_method = method %} + {%- else -%} + {% set form_method = "POST" %} + {%- endif -%} + + {%- if form_method != method -%} + + {%- endif -%} + {% endif -%} +{% endblock form_rest %} + +{# Support #} + +{%- block form_rows -%} + {% for child in form %} + {{- form_row(child) -}} + {% endfor %} +{%- endblock form_rows -%} + +{%- block widget_attributes -%} + id="{{ id }}" name="{{ full_name }}" + {%- if disabled %} disabled="disabled"{% endif -%} + {%- if required %} required="required"{% endif -%} + {{ block('attributes') }} +{%- endblock widget_attributes -%} + +{%- block widget_container_attributes -%} + {%- if id is not empty %}id="{{ id }}"{% endif -%} + {{ block('attributes') }} +{%- endblock widget_container_attributes -%} + +{%- block button_attributes -%} + id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%} + {{ block('attributes') }} +{%- endblock button_attributes -%} + +{% block attributes -%} + {%- for attrname, attrvalue in attr -%} + {{- " " -}} + {%- if attrname in ['placeholder', 'title'] -%} + {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}" + {%- elseif attrvalue is same as(true) -%} + {{- attrname }}="{{ attrname }}" + {%- elseif attrvalue is not same as(false) -%} + {{- attrname }}="{{ attrvalue }}" + {%- endif -%} + {%- endfor -%} +{%- endblock attributes -%} diff --git a/Resources/views/form/login.html.twig b/Resources/views/form/login.html.twig new file mode 100644 index 0000000..d680b2d --- /dev/null +++ b/Resources/views/form/login.html.twig @@ -0,0 +1,32 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{% trans %}Login{% endtrans %}

+
+ {{ form_start(form) }} + +
{{ form_errors(form) }}
+ +
+ {{ form_row(form.mail) }} + + {{ form_row(form.password) }} + + {% if error %} + + {% endif %} +
+ + {{ form_row(form.submit) }} + + {# Render CSRF token etc .#} +
+ {{ form_rest(form) }} +
+ + {{ form_end(form) }} +
+
+{% endblock %} diff --git a/Resources/views/form/recover.html.twig b/Resources/views/form/recover.html.twig new file mode 100644 index 0000000..63f948d --- /dev/null +++ b/Resources/views/form/recover.html.twig @@ -0,0 +1,28 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{% trans %}Recover{% endtrans %}

+ {% if sent %} +

{% trans %}Your recover account message has been sent{% endtrans %}

+ {% else %} +
+ {{ form_start(form) }} + +
{{ form_errors(form) }}
+ +
+ {{ form_row(form.mail) }} +
+ + {{ form_row(form.submit) }} + + {# Render CSRF token etc .#} +
+ {{ form_rest(form) }} +
+ + {{ form_end(form) }} +
+ {% endif %} +
+{% endblock %} diff --git a/Resources/views/form/recover_mail.html.twig b/Resources/views/form/recover_mail.html.twig new file mode 100644 index 0000000..74b2dd7 --- /dev/null +++ b/Resources/views/form/recover_mail.html.twig @@ -0,0 +1,30 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{% trans %}Recover{% endtrans %}

+ {% if sent %} +

{% trans %}Your password is updated and an account recover message has been sent{% endtrans %}

+ {% elseif notfound %} +

{% trans %}Unable to find account{% endtrans %}

+ {% else %} +
+ {{ form_start(form) }} + +
{{ form_errors(form) }}
+ +
+ {{ form_row(form.password) }} +
+ + {{ form_row(form.submit) }} + + {# Render CSRF token etc .#} +
+ {{ form_rest(form) }} +
+ + {{ form_end(form) }} +
+ {% endif %} +
+{% endblock %} diff --git a/Resources/views/form/register.html.twig b/Resources/views/form/register.html.twig new file mode 100644 index 0000000..ca69b5e --- /dev/null +++ b/Resources/views/form/register.html.twig @@ -0,0 +1,42 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{{ title|trans }}

+ {% if sent %} +

{% trans %}Your account has been created{% endtrans %}

+ {% else %} +
+ {{ form_start(form) }} + +
{{ form_errors(form) }}
+ +
+ {{ form_row(form.mail) }} + + {{ form_row(form.password.first) }} + + {{ form_row(form.password.second) }} +
+ +
+ {{ form_row(form.title) }} + + {{ form_row(form.forename) }} + + {{ form_row(form.surname) }} + + {{ form_row(form.pseudonym) }} +
+ + {{ form_row(form.submit) }} + + {# Render CSRF token etc .#} +
+ {{ form_rest(form) }} +
+ + {{ form_end(form) }} +
+ {% endif %} +
+{% endblock %} diff --git a/Resources/views/mail/contact.html.twig b/Resources/views/mail/contact.html.twig new file mode 100644 index 0000000..7fe13ff --- /dev/null +++ b/Resources/views/mail/contact.html.twig @@ -0,0 +1,43 @@ + + + + + + {{ subject }} + + + + + + + + +
{{ title|trans }}

{{ title|trans }}

+ + + + + + +
  +

{% trans %}Hi,{% endtrans %} {{ contact_name }}

+

{% trans %}Subject:{% endtrans %} {{ subject }}

+

{{ message|nl2br }}

+
 
+ + + + + + + diff --git a/Resources/views/mail/generic.html.twig b/Resources/views/mail/generic.html.twig new file mode 100644 index 0000000..5e6da39 --- /dev/null +++ b/Resources/views/mail/generic.html.twig @@ -0,0 +1,49 @@ + + + + + + {{ title }} + + + + + + + + +
{{ title }}

{{ title }}

+ + + + + + +
  +

{{ subtitle }}

+ {% if subject %} +

{% trans %}Subject:{% endtrans %} {{ subject }}

+ {% endif %} + {% if raw is defined %} +

{{ raw|raw }}

+ {% else %} +

{{ message|nl2br }}

+ {% endif %} +
 
+ + + + + + + diff --git a/Resources/views/mail/register.html.twig b/Resources/views/mail/register.html.twig new file mode 100644 index 0000000..8a6c0d3 --- /dev/null +++ b/Resources/views/mail/register.html.twig @@ -0,0 +1,43 @@ + + + + + + {{ 'Welcome to %title%'|trans({'%title%': title}) }} + + + + + + + + +
{{ title|trans }}

{{ title|trans }}

+ + + + + + +
  +

{% trans %}Hi,{% endtrans %} {{ contact_name }}

+

{% trans %}Subject:{% endtrans %} {{ 'Welcome to %title%'|trans({'%title%': title|trans}) }}

+

{{ 'Thanks so much for joining us, from now you can reserver your %title% spaces.'|trans({'%title%': title|trans}) }}

+
 
+ + + + + + + diff --git a/Resources/views/page/index.html.twig b/Resources/views/page/index.html.twig new file mode 100644 index 0000000..f0997a7 --- /dev/null +++ b/Resources/views/page/index.html.twig @@ -0,0 +1,7 @@ +{% extends '@RapsysAir/base.html.twig' %} +{% block content %} +
+

{{ section }}

+

{% trans %}Outdoor space reservation system{% endtrans %}

+
+{% endblock %} diff --git a/Tests/Controller/DefaultControllerTest.php b/Tests/Controller/DefaultControllerTest.php new file mode 100644 index 0000000..fed9e42 --- /dev/null +++ b/Tests/Controller/DefaultControllerTest.php @@ -0,0 +1,17 @@ +request('GET', '/'); + + $this->assertContains('Hello World', $client->getResponse()->getContent()); + } +} diff --git a/Twig/Base64Extension.php b/Twig/Base64Extension.php new file mode 100644 index 0000000..8272989 --- /dev/null +++ b/Twig/Base64Extension.php @@ -0,0 +1,12 @@ + array('type' => BBCODE_TYPE_ROOT), + 'code' => array( + 'type' => BBCODE_TYPE_OPTARG, + 'open_tag' => '
',
+								'close_tag' => '
', + 'default_arg' => '{CONTENT}' + ), + 'ul' => array( + 'type' => BBCODE_TYPE_NOARG, + 'open_tag' => '', + 'childs' => 'li' + ), + 'li' => array( + 'type' => BBCODE_TYPE_NOARG, + 'open_tag' => '
  • ', + 'close_tag' => '
  • ', + 'parent' => 'ul', + 'childs' => 'url' + ), + 'url' => array( + 'type' => BBCODE_TYPE_OPTARG, + 'open_tag' => '', + 'close_tag' => '', + 'default_arg' => '{CONTENT}', + 'parent' => 'p,li' + ) + ) + ); + $text = nl2br(bbcode_parse($ctx, htmlspecialchars($text))); + if (preg_match_all('#\]*\>(.*?)\#s', $text, $matches) && !empty($matches[1])) { + foreach($matches[1] as $string) { + $text = str_replace($string, str_replace('
    ', '', $string), $text); + } + } + if (preg_match_all('#\]*\>(.*?)\#s', $text, $matches) && !empty($matches[1])) { + foreach($matches[1] as $string) { + $text = str_replace($string, str_replace('
    ', '', $string), $text); + } + } + $text = preg_replace( + array('#(
    (\r?\n?))*(
    (\r?\n?))*#', '#(
    (\r?\n?))*(
    (\r?\n?))*#', '#(
    (\r?\n?)){2,}#'), + array('

    \2\2

    ', '

    \2\2

    ', '

    \2

    '), + $text + ); + return $text; + }, + array('is_safe' => array('html')) + ) + ); + } +} diff --git a/Twig/FileGetContentsExtension.php b/Twig/FileGetContentsExtension.php new file mode 100644 index 0000000..ac4ab2a --- /dev/null +++ b/Twig/FileGetContentsExtension.php @@ -0,0 +1,11 @@ +