* Sidebar-Suchmaske

* Letzter Breadcrum-Eintrag ist kein Link
* Sonstige Links im Layout (Impressum, etc.)
* Vorschaubox-Anpassungen: page.box_body wurde nicht berücksichtigt; page.box_image_url wird jetzt gegenüber travelProgram.previewImage bevorzugt; Standard-Vorschaubild geändert
* page.pagetitle gegenüber page.title als Seitenüberschrift bevorzugen
* Fertigstellung Reiseprogrammseite; zu Tab-Inhalt scrollen; Bei Klick auf Buchen-Knopf zu Termintabelle scrollen (auch von der Suchseite aus)
* Aufteilung der Vorschau-Boxen in vermittelte und nicht-vermittelte Reisen, falls es beide gibt
* Falls page.real_path_url gesetzt wird => Eine Seite kann nicht mehr über den slug-Pfad (<eltern-seite>/<seite>) aufgerufen werden (Sonst gäbe es mehrere URLs für die gleiche Seite)

git-svn-id: http://78.47.251.156/svn/dev/sterntours-3@3295 f459cee4-fb09-11de-96c3-f9c5f16c3c76
This commit is contained in:
uli 2017-02-17 08:24:48 +00:00
parent 4c2fb2fd08
commit 20beca7c4d
25 changed files with 564 additions and 112 deletions

View file

@ -83,7 +83,7 @@ class BookingController extends Controller
if ($action == '/buchen')
{
$breadcrumbEntries = Util::createBreadcrumb($travelProgramPage);
$breadcrumbEntries[] = new BreadcrumbEntry('Buchen', $travelProgramPage->getUrlPath() .'/buchen');
$breadcrumbEntries[] = new BreadcrumbEntry('Buchen');
if ($request->getMethod() == 'POST' && $form->isValid())
{

View file

@ -2,8 +2,10 @@
namespace AppBundle\Controller;
use AppBundle\Entity\BreadcrumbEntry;
use AppBundle\Entity\Page;
use AppBundle\Entity\TravelProgram;
use AppBundle\Form\SearchRequestType;
use AppBundle\Util;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query\Expr;
@ -74,10 +76,35 @@ class DefaultController extends Controller
$childPages =
$this->getEntityManager()->getRepository('AppBundle:Page')->getChildrenWithTravelProgramsAndDates($page);
$nonMediated = [];
$mediated = [];
foreach ($childPages as $childPage)
{
if ($childPage->getStatus() == 1 && $childPage->getTravelProgram() &&
$childPage->getTravelProgram()->getIsMediated())
{
$mediated[] = $childPage;
}
else
{
$nonMediated[] = $childPage;
}
}
// We only need a separation if there are mediated AND non mediated travel programs
if (empty($nonMediated) && !empty($mediated))
{
$childPages = $mediated;
}
else
{
$childPages = $nonMediated;
}
return $this->render('default/pages/travelProgramOverview.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'page' => $page,
'child_pages' => $childPages
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'page' => $page,
'child_pages' => $childPages,
'mediated_child_pages' => $mediated,
]);
}
@ -98,28 +125,38 @@ class DefaultController extends Controller
*/
public function searchAction(Request $request)
{
$stopwatch = $this->get('debug.stopwatch');
$em = $this->getEntityManager();
$destinationIds = null;
$destination = $em->getRepository('AppBundle:TravelCountry')->find($request->query->get('c'));
if ($destination)
{
$destinationsIds = [$destination->getId()];
}
$startDate = $request->query->has('b')
? \DateTime::createFromFormat('d.m.Y', $request->query->get('b'))
: new \DateTime();
$endDate = \DateTime::createFromFormat('d.m.Y', $request->query->get('e'));
$form = $this->createForm(SearchRequestType::class);
$form->handleRequest($request);
$stopwatch->start('search');
$r = $this->getDoctrine()->getRepository('AppBundle:TravelPeriod')->getTravelProgramsWithTravelDatesForTimePeriod(
$startDate, $endDate, $destinationIds, true);
$stopwatch->stop('search');
if ($form->isValid())
{
$data = $form->getData();
$destinationIds = [];
if (!empty($data['c']))
{
$destinationIds = [$data['c']->getId()];
}
if (!empty($destinationIds) && !empty($data['c2']))
{
$destinationIds[] = $data['c2']->getId();
}
$r = $this->getDoctrine()->getRepository('AppBundle:TravelPeriod')->getTravelProgramsWithTravelDatesForTimePeriod(
$data['b'], $data['e'], $destinationIds, count($destinationIds) > 1);
}
else
{
$r = [];
}
return $this->render('default/pages/search.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'travel_programs' => $r
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'breadcrumb_entries' => [new BreadcrumbEntry('Suchen')],
'search_form' => $form->createView(),
'travel_programs' => $r,
]);
}
@ -139,8 +176,8 @@ class DefaultController extends Controller
->execute()
;
return $this->render('default/components/header.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'nav_pages' => $navPages
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'nav_pages' => $navPages,
]);
}
@ -148,7 +185,7 @@ class DefaultController extends Controller
{
return $this->render('default/components/breadcrumb.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'breadcrumb_entries' => Util::createBreadcrumb($page)
'breadcrumb_entries' => Util::createBreadcrumb($page),
]);
}
@ -200,6 +237,32 @@ class DefaultController extends Controller
return $this->render('default/components/sidebar/navSidebarWidget.html.twig', $view);
}
public function searchSidebarWidgetAction(Page $page)
{
$combinedDestination = null;
if ($page->getTravelProgram())
{
$countries = $page->getTravelProgram()->getCountries();
$destination = $countries->first();
if (count($countries) > 1)
{
$combinedDestination = $countries[1];
}
}
else
{
$destination = $page->getCountry();
}
return $this->render('default/components/sidebar/searchSidebarWidget.html.twig', [
'search_form' => $this->createForm(SearchRequestType::class, [
'b' => new \DateTime('+5 day'),
'e' => new \DateTime('+19 day'),
'c' => $destination,
'c2' => $combinedDestination,
])->createView()
]);
}
/*
Suche Kindknoten
Für jeden Kindknoten

View file

@ -18,7 +18,7 @@ class BreadcrumbEntry
* @param $title
* @param $url
*/
public function __construct($title, $url)
public function __construct($title, $url = null)
{
$this->title = $title;
$this->url = $url;

View file

@ -174,4 +174,11 @@ class TravelCountry
{
return $this->programs;
}
function __toString()
{
return $this->name;
}
}

View file

@ -792,7 +792,7 @@ class TravelProgram
/**
* Get showMap
*
* @return boolean
* @return int 1 for mapHtml, 2 for mapImage
*/
public function getShowMap()
{
@ -1365,7 +1365,7 @@ class TravelProgram
/**
* Get countries
*
* @return \Doctrine\Common\Collections\Collection
* @return \AppBundle\Entity\TravelCountry[]|\Doctrine\Common\Collections\Collection
*/
public function getCountries()
{
@ -1551,4 +1551,9 @@ class TravelProgram
{
return $this->page;
}
public function getHasMap()
{
return ($this->showMap ?? 0) > 0 && ($this->mapHtml or $this->mapHtml);
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
* @date 02/16/2017
*/
namespace AppBundle\Form;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SearchRequestType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setMethod('GET');
$builder
->add('b', StDateType::class, ['required' => false])
->add('e', StDateType::class, ['required' => false])
->add('c', EntityType::class, [
'required' => false,
'placeholder' => 'beliebiges Reiseziel',
'class' => 'AppBundle\Entity\TravelCountry',
])
->add('c2', EntityType::class, [
'required' => false,
'placeholder' => 'Bitte wählen (optional)',
'class' => 'AppBundle\Entity\TravelCountry',
])
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => false,
));
}
public function getBlockPrefix()
{
return null;
}
}

View file

@ -0,0 +1,29 @@
<?php
/**
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
* @date 02/16/2017
*/
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class StDateType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'placeholder' => 'TT.MM.JJJJ',
'widget' => 'single_text',
'format' => 'dd.MM.yyyy'
]);
}
public function getParent()
{
return DateType::class;
}
}

View file

@ -16,6 +16,7 @@ use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class KernelControllerListener
{
@ -89,6 +90,15 @@ class KernelControllerListener
$node = $childNode;
++$i;
}
if ($node && $node->getRealUrlPath() && $node->getRealUrlPath() != '/'. $path)
{
// If there realUrlPath is set and the slug path differs from realUrlPath, then the slug path is
// not a valid URL. Otherwise, there would be two different URLs representing the same page.
$event->setController(function() {
throw new NotFoundHttpException('Invalid URL');
});
return;
}
}
if (!$node)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,82 @@
$(document).ready(function() {
function scrollToTabContent(tabSelector)
{
$(document.body).animate({
scrollTop: $(tabSelector).offset().top - 220
}, 1000);
}
function activateTravelDatesTab()
{
$('[href=\'#travel-dates-content-tab\']').tab('show');
scrollToTabContent('#travel-dates-content-tab');
}
$('.nav-tabs > li > a').click(function() {
scrollToTabContent($(this).attr('href'));
});
$('.st-slider-booking-btn').click(activateTravelDatesTab);
if (location.hash === '#travel-dates-content-tab')
{
activateTravelDatesTab();
}
var videos$ = $('a[id^="video_"]');
videos$.each(function() {
var el$ = $(this);
var text = el$.text();
var length = text.length - 11;
var caption = text.substring(0, length);
var expl = this.id.substring(6, this.id.length);
$('<iframe />')
.attr({
width: 680,
height: 466,
src: '//www.youtube.com/embed/'+ expl,
frameborder: 0,
allowfullscreen: true,
'data-st-video': this.id
})
.addClass('st-collapsed')
.hide()
.insertAfter(this)
;
el$
.css('background-image', 'url(/images/st2/icons/arrowup.gif)')
.text(caption + ' einblenden')
.attr('href', 'javascript:void(0);')
;
});
videos$.click(function() {
var el$ = $(this);
var video$ = $('[data-st-video='+ this.id +']');
var text = el$.text();
var length = text.length - 11;
var caption = text.substring(0, length);
if (el$.hasClass('st-collapsed'))
{
video$.slideDown('slow');
el$.text(caption + ' ausblenden');
el$.removeClass('st-collapsed');
}
else
{
video$.slideUp(400);
el$.text(caption + ' einblenden');
el$.addClass('st-collapsed');
}
});
});

View file

@ -17,27 +17,40 @@ class AppExtension extends \Twig_Extension
$this->environment = $env;
}
public function getFilters()
{
return [
'stripslashes' => new \Twig_SimpleFilter('stripslashes', [$this, 'stripslashesFilter'], [
'is_safe' => ['html']
]),
];
}
public function getFunctions()
{
return array(
'form_field' => new \Twig_SimpleFunction('form_field', array($this, 'formField'), array(
'is_safe' => array('html')
)),
'form_field_pho' => new \Twig_SimpleFunction('form_field_pho', array($this, 'formFieldPho'), array(
'is_safe' => array('html')
)),
);
return [
'form_field' => new \Twig_SimpleFunction('form_field', [$this, 'formField'], [
'is_safe' => ['html']
]),
'form_field_pho' => new \Twig_SimpleFunction('form_field_pho', [$this, 'formFieldPho'], [
'is_safe' => ['html']
]),
];
}
public function stripslashesFilter($v)
{
return stripslashes($v);
}
public function formField($form, $label = null, $opt = null)
{
$this->template = $this->environment->loadTemplate( '::default/form/helpers.html.twig' );
return $this->template->renderBlock('form_field', array(
return $this->template->renderBlock('form_field', [
'form' => $form,
'label' => $label,
'opt' => $opt
));
]);
}
/**
@ -53,11 +66,11 @@ class AppExtension extends \Twig_Extension
{
$this->template = $this->environment->loadTemplate( '::default/form/helpers.html.twig' );
return $this->template->renderBlock('form_field_pho', array(
return $this->template->renderBlock('form_field_pho', [
'form' => $form,
'label' => $label,
'opt' => $opt
));
]);
}
/**