Final gallery crap

This commit is contained in:
R. Eric Wheeler 2017-05-06 18:25:42 -07:00
parent 92a9858d7b
commit 6f0be81406
12 changed files with 338 additions and 104 deletions

View File

@ -0,0 +1,39 @@
{% extends 'base.html.twig' %}
{% block body %}
<p class="uk-text-lead uk-text-center">
We are sorry, but we are in maintenance mode.
</p>
<p class="uk-text-center">
We are busy upgrading the system and will be back shortly.<br />
Thank you for your patience!
</p>
<p class="uk-margin-remove-top uk-text-center uk-404 uk-doughnut">
<span class="uk-spin uk-background-cover uk-inline"></span>
</p>
<progress id="progressbar" class="uk-progress uk-width-1-2@m uk-width-1-1@s uk-align-center" value="10" max="100"></progress>
{% endblock %}
{% block javascripts %}
<script>
jQuery(function () {
var animate = setInterval(function () {
var progress = jQuery('progress');
progress && (progress.val(progress.val() + 10) );
if (!progress || progress.val() >= progress.attr('max')) {
for(i=progress.attr('max');i>0;i--) {
progress.val(i);
}
}
}, 1000);
});
</script>
{% endblock %}

View File

@ -8,6 +8,11 @@
<li><a href="{{ path('sikofitt_doughnutwedding_default_ourstory') }}"><span class="uk-margin-small-right" uk-icon="icon: heart"></span> Our Story</a></li>
<li><a href="{{ path('fos_user_profile_edit') }}"><span class="uk-margin-small-right" uk-icon="icon: bolt"></span> RSVP</a></li>
<li><a href="{{ path('sikofitt_doughnutwedding_gallery_index') }}"><span class="uk-margin-small-right" uk-icon="icon: image"></span> Gallery</a></li>
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
<li><a href="{{ path('sikofitt_doughnutwedding_gallery_upload') }}">
<span class="uk-margin-small-right" uk-icon="icon: cloud-upload"></span> Upload Photo</a>
</li>
{% endif %}
<li><a href="{{ path('sikofitt_doughnutwedding_default_location') }}"><span class="uk-margin-small-right" uk-icon="icon: location"></span> Location</a></li>
<li><a href="{{ path('sikofitt_doughnutwedding_default_contact') }}"><span class="uk-margin-small-right" uk-icon="icon: mail"></span> Get In Touch</a></li>

View File

@ -13,6 +13,7 @@ parameters:
google.application_name: 'doughnut-wedding'
katrina.email: katrina.a.johnson@gmail.com
eric.email: sikofitt@gmail.com
maintenance: false
framework:
cache:
app: cache.adapter.redis

View File

@ -38,7 +38,11 @@ services:
class: \Google_Service_Storage
factory: ['Sikofitt\DoughnutWeddingBundle\Factory\GoogleCloudStorageServiceFactory', createGoogleCloudService]
arguments: ['%google.credentials_file%', '%google.client_id%', '%google.application_name%']
doughnutwedding.event.check_maintenance_mode:
class: Sikofitt\DoughnutWeddingBundle\EventListener\CheckForMaintenanceModeListenerEvent
arguments: ['@service_container', '@security.token_storage']
tags:
- { name: kernel.event_listener, event: kernel.request }
doughnutwedding.event.check_email_on_reset_event:
class: Sikofitt\DoughnutWeddingBundle\EventListener\CheckThatEmailAndUserNameExistOnResetRequest
arguments: ['@router', '@templating.engine.twig']

View File

@ -22,19 +22,28 @@ namespace Sikofitt\DoughnutWeddingBundle\Controller;
use Pagerfanta\Adapter\ArrayAdapter;
use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sikofitt\DoughnutWeddingBundle\Entity\Image;
use Sikofitt\DoughnutWeddingBundle\Entity\ImageComment;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\{
Method,
Route
};
use Sikofitt\DoughnutWeddingBundle\Entity\{
Image,
ImageComment,
User
};
use Sikofitt\DoughnutWeddingBundle\Form\GalleryUploadType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\{
JsonResponse,
RedirectResponse,
Request,
Response
};
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\{
Core\Authentication\Token\TokenInterface,
Csrf\CsrfToken
};
/**
* Class ImageController.
@ -47,9 +56,12 @@ class GalleryController extends Controller
* @Route("/")
* @Method({"GET"})
*/
public function indexAction(Request $request) : Response
public function indexAction(Request $request): Response
{
$images = $this->get('doctrine.orm.default_entity_manager')->getRepository('SikofittDoughnutWeddingBundle:Image')->findAll();
$images = $this
->get('doctrine.orm.entity_manager')
->getRepository('SikofittDoughnutWeddingBundle:Image')
->findAllSortedByUpdatedAtDesc();
$chunks = array_chunk($images, 12);
$adapter = new ArrayAdapter($images);
@ -72,7 +84,10 @@ class GalleryController extends Controller
*/
public function pageAction(Request $request, int $number)
{
$images = $this->get('doctrine.orm.default_entity_manager')->getRepository('SikofittDoughnutWeddingBundle:Image')->findAll();
$images = $this
->get('doctrine.orm.entity_manager')
->getRepository('SikofittDoughnutWeddingBundle:Image')
->findAllSortedByUpdatedAtDesc();
$adapter = new ArrayAdapter($images);
$pager = new Pagerfanta($adapter);
@ -80,7 +95,10 @@ class GalleryController extends Controller
$pager->setMaxPerPage(12);
$pager->setCurrentPage($number);
return $this->render('SikofittDoughnutWeddingBundle:Image:index.html.twig', ['images' => $chunks[$number - 1], 'pager' => $pager]);
return $this->render('SikofittDoughnutWeddingBundle:Image:index.html.twig', [
'images' => $chunks[$number - 1] ?? $images,
'pager' => $pager,
]);
}
/**
@ -105,9 +123,19 @@ class GalleryController extends Controller
$em->persist($image);
$em->flush();
$baseName = $image->getImageFile()->getBasename('.'.$image->getImageFile()->getExtension());
$baseName = $image
->getImageFile()
->getBasename(
sprintf('.%s', $image->getImageFile()->getExtension())
);
return new RedirectResponse($this->get('router')->generate('view_gallery_image_by_hash', ['imageHash' => $baseName]));
return new RedirectResponse(
$this
->get('router')
->generate('view_gallery_image_by_hash', [
'imageHash' => $baseName,
])
);
}
return $this->render('SikofittDoughnutWeddingBundle:Image:upload.html.twig', [
@ -122,20 +150,34 @@ class GalleryController extends Controller
public function ajaxCommentAction(Request $request): JsonResponse
{
if (false === $request->getSession()->has('_security_secured_area')) {
return new JsonResponse(['status' => 403, 'message' => 'You must be logged in to post a comment'], 403);
return new JsonResponse([
'status' => 403,
'message' => 'You must be logged in to post a comment',
], 403);
}
/** @var \Symfony\Component\Security\Core\Authentication\Token\TokenInterface $data */
$data = unserialize($request->getSession()->get('_security_secured_area'), [TokenInterface::class]);
$data = unserialize(
$request->getSession()->get('_security_secured_area'), [
TokenInterface::class,
]);
$tokenManager = $this->get('security.csrf.token_manager');
$fileName = $request->request->get('file');
$token = $request->request->get('_token');
$csrfToken = new CsrfToken($fileName, $token);
if (false === $tokenManager->isTokenValid($csrfToken)) {
return new JsonResponse(['status' => Response::HTTP_EXPECTATION_FAILED, 'message' => 'Invalid Token'], Response::HTTP_EXPECTATION_FAILED);
}
if (false === $data->getUser() instanceof User) {
return new JsonResponse([
'status' => 403,
'message' => 'You must be logged in to post a comment',
], 403);
}
$em = $this->get('doctrine.orm.entity_manager');
$user = $em
->getRepository('SikofittDoughnutWeddingBundle:User')
@ -155,6 +197,7 @@ class GalleryController extends Controller
->setIsChild(false)
->setCreated(new \DateTime('now'))
->setChildComments(null);
$em->persist($newComment);
$em->flush();
@ -187,13 +230,17 @@ class GalleryController extends Controller
->get('doctrine.orm.entity_manager')
->createQueryBuilder()
->select('i')
->from('Sikofitt\DoughnutWeddingBundle\Entity\Image', 'i')
->from(Image::class, 'i')
->where('i.imageName LIKE :imageHash')
->setParameter('imageHash', $imageHash.'%')
->getQuery()->getOneOrNullResult();
->getQuery()
->getOneOrNullResult();
if (null !== $image) {
return $this->render('@SikofittDoughnutWedding/Image/view_image.html.twig',
['image' => $image]);
return $this
->render('@SikofittDoughnutWedding/Image/view_image.html.twig', [
'image' => $image,
]);
}
throw new NotFoundHttpException();
@ -232,6 +279,8 @@ class GalleryController extends Controller
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @param string $category
* @param int $number
* The current page
*
* @return Response
*/

View File

@ -313,6 +313,11 @@ class Image
*/
public function setTags($tags): Image
{
foreach ($tags as $key => $value) {
if (null === $value || '' === $value) {
unset($tags[$key]);
}
}
$this->tags = $tags;
return $this;
@ -321,10 +326,18 @@ class Image
/**
* Get tags.
*
* @return array
* @return array|string
*/
public function getTags()
{
if (true === is_array($this->tags)) {
foreach ((array) $this->tags as $key => $value) {
if (null === $value || '' === $value) {
unset($this->tags[$key]);
}
}
}
return $this->tags;
}
@ -335,7 +348,7 @@ class Image
*
* @return Image
*/
public function setCategory($category)
public function setCategory($category): ?Image
{
$this->category = $category;
@ -347,7 +360,7 @@ class Image
*
* @return string
*/
public function getCategory()
public function getCategory(): ?string
{
return $this->category;
}

View File

@ -0,0 +1,67 @@
<?php
/*
* doughnutwedding.com
* Copyright (C) 2017 http://doughnutwedding.com eric@doughnutwedding.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Sikofitt\DoughnutWeddingBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class CheckForMaintenanceModeListenerEvent
{
private $container;
private $token;
public function __construct(ContainerInterface $container, TokenStorageInterface $token)
{
$this->container = $container;
$this->token = $token;
}
public function onKernelRequest(GetResponseEvent $event)
{
$maintenance = (bool) $this->container->getParameter('maintenance');
if (null === $maintenance || false === $maintenance) {
return;
}
$authToken = $this->token->getToken();
if (
null !== $authToken &&
true === $this->container
->get('security.authorization_checker')
->isGranted('ROLE_ADMIN', $authToken)
) {
$event
->getRequest()
->getSession()
->getFlashBag()
->set('warning', 'Maintenance mode is on.');
return;
}
$event->setResponse(new Response($this->container->get('twig')
->render('maintenance.html.twig')));
}
}

View File

@ -25,56 +25,69 @@ use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Form\Type\VichImageType;
class GalleryUploadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$image = new Assert\Image();
$builder->add('imageFile', VichImageType::class, [
'label_attr' => [
'class' => 'uk-form-label uk-hidden',
'class' => 'uk-form-label uk-visible@m',
'id' => 'file-field-label',
'style' => 'margin-right:14px;',
],
'attr' => [
'class' => 'uk-padding-small',
'accept' => '.jpg,.jpeg,.png,.gif,.tiff',
],
'constraints' => [
new Assert\Image(),
],
])
->add('description', TextareaType::class, [
'required' => false,
'label' => 'Description of image.',
'attr' => [
'rows' => 4,
'class' => 'uk-textarea uk-form-large uk-padding-small',
],
'label_attr' => [
'class' => 'uk-form-label',
],
])
->add('tags', CollectionType::class, [
'required' => false,
'entry_type' => TextType::class,
'entry_options' => [
->add('description', TextareaType::class, [
'required' => false,
'label' => 'Description of image.',
'attr' => [
'class' => 'uk-input uk-form-large uk-width-medium',
'rows' => 4,
'class' => 'uk-textarea uk-form-large uk-padding-small uk-margin-small-bottom',
'placeholder' => 'Description of image',
],
],
'allow_add' => true,
'allow_delete' => true,
'label_attr' => [
'class' => 'uk-form-label',
],
'attr' => [
'class' => 'uk-input uk-form-large uk-padding-small',
],
])
->add('category', TextType::class, [
'required' => false,
'label_attr' => [
'class' => 'uk-form-label',
],
'attr' => [
'class' => 'uk-input uk-form-large uk-padding-small',
],
]);
'label_attr' => [
'class' => 'uk-form-label uk-visible@m',
],
])
->add('tags', CollectionType::class, [
'required' => false,
'entry_type' => TextType::class,
'entry_options' => [
'attr' => [
'class' => 'uk-input uk-form-large uk-width-medium uk-margin-small-bottom',
'placeholder' => 'Enter tag',
],
],
'allow_add' => true,
'allow_delete' => true,
'label_attr' => [
'class' => 'uk-form-label uk-visible@m',
],
'attr' => [
'class' => 'uk-input uk-form-large uk-padding-small',
],
])
->add('category', TextType::class, [
'required' => false,
'label_attr' => [
'class' => 'uk-form-label uk-visible@m',
],
'attr' => [
'class' => 'uk-input uk-form-large uk-padding-small uk-margin-small-bottom',
'placeholder' => 'Add category',
],
]);
}
}

View File

@ -32,41 +32,61 @@ use Sikofitt\DoughnutWeddingBundle\Entity\Image;
class ImageRepository extends EntityRepository
{
/**
* @param string $tag
*
* @return array
*/
public function findImageByTag(string $tag): array
{
$images = $this->getEntityManager()
->createQueryBuilder()
->select('i')
->from(Image::class, 'i')
->where('i.tags LIKE :tag')
->setParameter('tag', '%'.$tag.'%')
->getQuery()->getResult();
/**
* @var int $key
* @var Image $image
*/
foreach ($images as $key => $image) {
if (false === in_array($tag, $image->getTags(), true)) {
unset($images[$key]);
}
}
* @return array|null
*/
public function findAllSortedByUpdatedAtDesc(): ?array
{
return $this
->getEntityManager()
->createQueryBuilder()
->select('i')
->from(Image::class, 'i')
->orderBy('i.updatedAt', 'DESC')
->getQuery()
->getResult();
}
return $images;
/**
* @param string $tag
*
* @return array
*/
public function findImageByTag(string $tag): array
{
$images = $this->getEntityManager()
->createQueryBuilder()
->select('i')
->from(Image::class, 'i')
->orderBy('i.updatedAt', 'DESC')
->where('i.tags LIKE :tag')
->setParameter('tag', '%'.$tag.'%')
->getQuery()
->getResult();
/**
* @var int $key
* @var Image $image
*/
foreach ($images as $key => $image) {
if (false === in_array($tag, $image->getTags(), true)) {
unset($images[$key]);
}
}
return $images;
}
public function findImageByCategory(string $category): array
{
return $this
->getEntityManager()
->createQueryBuilder()
->select('i')
->from(Image::class, 'i')
->where('i.category =:category')
->setParameter('category', $category)
->getQuery()->getResult();
->getEntityManager()
->createQueryBuilder()
->select('i')
->from(Image::class, 'i')
->orderBy('i.updatedAt', 'DESC')
->where('i.category =:category')
->setParameter('category', $category)
->getQuery()
->getResult();
}
}

View File

@ -24,7 +24,11 @@
<div class="uk-modal-dialog">
<button class="uk-padding uk-modal-close-full uk-close-large" type="button" uk-close></button>
<div class="uk-grid-collapse uk-child-width-1-2@s uk-flex" uk-grid>
<div class="uk-background-cover" style="background-image: url({{ imageUrl }});" uk-height-viewport></div>
<div class="uk-background-cover" style="background-image: url({{ imageUrl }});" uk-height-viewport>
<div class="uk-hidden@m uk-overlay uk-light uk-position-center-right">
<a href="#" data-id="{{ image.id }}" class="comment-scroll uk-inline uk-margin-remove-bottom uk-margin-large-top"> {% if image.comments|length > 0 %}{{ image.comments|length }}{% endif %} Comments</a>
</div>
</div>
<div id="comment-panel-{{ image.id }}" class="uk-margin-large-bottom@s uk-padding-large uk-overflow-auto" style="max-height:100vh">
<div class="uk-overflow-auto" >
<div class="uk-width-1-1">
@ -45,7 +49,9 @@
<ul class="uk-comment-meta uk-subnav uk-subnav-divider uk-margin-remove-top">
<li class="uk-subnav-divider">View more like this</li>
{% for tag in image.tags %}
{% if tag is not null and tag is not empty %}
<a style="text-decoration:underline;" href="{{ path('gallery_tag_action', {'tag':tag}) }}">{{ tag|capitalize }}</a>
{% endif %}
{% endfor %}
</ul>
{% endif %}
@ -146,6 +152,9 @@
}
});
jQuery('.comment-scroll').on('click', function(event) {
jQuery('#modal-full-'+jQuery(this).attr('data-id')).animate({scrollTop: jQuery('#comment-panel-'+jQuery(this).attr('data-id')).offset().top}, 1000);
});
});
</script>
{% endblock javascripts %}

View File

@ -2,14 +2,20 @@
{% block title %}Gallery Upload{% endblock title %}
{% block body %}
<h2 class="uk-text-center">Upload an Image to the Gallery</h2>
<h2 class="uk-margin-large-bottom uk-text-center uk-margin-remove-top">Upload an Image to the Gallery</h2>
{{ form_start(form, {'attr': { 'class': 'uk-form uk-form-horizontal'}}) }}
{{ form_label(form.imageFile) }}
<div class="uk-form-controls uk-form-controls-text">
{{ form_errors(form.imageFile) }}
{{ form_widget(form.imageFile) }}
</div>
<div class="uk-width-1-1">
{{ form_label(form.imageFile) }}
<div class="uk-width-1-2@m uk-width-1-1@s" uk-form-custom>
{{ form_errors(form.imageFile) }}
{{ form_widget(form.imageFile) }}
<button id="file-select" class="uk-align-left uk-button-large uk-button uk-button-primary uk-margin-small-bottom uk-width-1-1@s uk-width-1-2@m" type="button" tabindex="-1">Select File</button>
<div class="uk-width-1-4 uk-align-left uk-text-left uk-margin-small-top" id="file-name"></div>
</div>
</div>
{{ form_label(form.description) }}
<div class="uk-form-controls">
{{ form_errors(form.description) }}
@ -34,11 +40,10 @@
</ul>
<a href="#" class="uk-inline uk-align-right uk-button uk-button-default" id="add-tag">Add Tag</a>
</div>
<input type="hidden" name="MAX_FILE_SIZE" value="8388608" />
<div class="uk-form-controls uk-margin-large-top">
<button class="uk-button uk-button-large uk-button-primary" name="submit" id="gallery_image_upload">Upload</button>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock body %}
@ -48,6 +53,10 @@
var tagCount = '{{ form.tags|length }}';
jQuery(document).ready(function() {
jQuery('form').on('change', 'input[type=file]', function(event) {
jQuery('#file-select').text(this.files.item(0).name);
});
jQuery('#add-tag').click(function(e) {
e.preventDefault();
@ -64,6 +73,9 @@
// create a new list element and add it to the list
var newLi = jQuery('<li></li>').html(newWidget);
newLi.appendTo(tagList);
var input = jQuery('#gallery_upload_tags_'+(tagCount -1));
input.focus();
});
})
</script>

View File

@ -38,7 +38,9 @@
<ul class="uk-comment-meta uk-subnav uk-subnav-divider uk-margin-remove-top">
<li class="uk-subnav-divider">View more like this</li>
{% for tag in image.tags %}
{% if tag is not null and tag is not empty %}
<a style="text-decoration:underline;" href="{{ path('gallery_tag_action', {'tag':tag}) }}">{{ tag|capitalize }}</a>
{% endif %}
{% endfor %}
</ul>
{% endif %}