* 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:
parent
4c2fb2fd08
commit
20beca7c4d
25 changed files with 564 additions and 112 deletions
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -174,4 +174,11 @@ class TravelCountry
|
|||
{
|
||||
return $this->programs;
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
54
trunk/src/AppBundle/Form/SearchRequestType.php
Normal file
54
trunk/src/AppBundle/Form/SearchRequestType.php
Normal 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;
|
||||
}
|
||||
}
|
||||
29
trunk/src/AppBundle/Form/StDateType.php
Normal file
29
trunk/src/AppBundle/Form/StDateType.php
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
BIN
trunk/src/AppBundle/Resources/public/images/no-picture.png
Normal file
BIN
trunk/src/AppBundle/Resources/public/images/no-picture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
82
trunk/src/AppBundle/Resources/public/js/travelProgram.js
Normal file
82
trunk/src/AppBundle/Resources/public/js/travelProgram.js
Normal 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');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -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
|
||||
));
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue