document positioning

This commit is contained in:
Etienne Roudeix
2013-12-16 10:55:18 +01:00
parent 0e30ce2760
commit 583cbe95b6
14 changed files with 161 additions and 27 deletions

View File

@@ -28,6 +28,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Core\Event\Document\DocumentCreateOrUpdateEvent; use Thelia\Core\Event\Document\DocumentCreateOrUpdateEvent;
use Thelia\Core\Event\Document\DocumentDeleteEvent; use Thelia\Core\Event\Document\DocumentDeleteEvent;
use Thelia\Core\Event\Document\DocumentEvent; use Thelia\Core\Event\Document\DocumentEvent;
use Thelia\Core\Event\UpdateFilePositionEvent;
use Thelia\Exception\ImageException; use Thelia\Exception\ImageException;
use Thelia\Model\ConfigQuery; use Thelia\Model\ConfigQuery;
use Thelia\Tools\FileManager; use Thelia\Tools\FileManager;
@@ -195,6 +196,11 @@ class Document extends BaseCachedFile implements EventSubscriberInterface
$event->setModelDocument($event->getModelDocument()); $event->setModelDocument($event->getModelDocument());
} }
public function updatePosition(UpdateFilePositionEvent $event)
{
return $this->genericUpdatePosition($event->getQuery(), $event);
}
/** /**
* Take care of deleting document in the database and file storage * Take care of deleting document in the database and file storage
* *
@@ -218,6 +224,7 @@ class Document extends BaseCachedFile implements EventSubscriberInterface
TheliaEvents::DOCUMENT_DELETE => array("deleteDocument", 128), TheliaEvents::DOCUMENT_DELETE => array("deleteDocument", 128),
TheliaEvents::DOCUMENT_SAVE => array("saveDocument", 128), TheliaEvents::DOCUMENT_SAVE => array("saveDocument", 128),
TheliaEvents::DOCUMENT_UPDATE => array("updateDocument", 128), TheliaEvents::DOCUMENT_UPDATE => array("updateDocument", 128),
TheliaEvents::DOCUMENT_UPDATE_POSITION => array("updatePosition", 128),
); );
} }
} }

View File

@@ -28,7 +28,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Core\Event\Image\ImageCreateOrUpdateEvent; use Thelia\Core\Event\Image\ImageCreateOrUpdateEvent;
use Thelia\Core\Event\Image\ImageDeleteEvent; use Thelia\Core\Event\Image\ImageDeleteEvent;
use Thelia\Core\Event\Image\ImageEvent; use Thelia\Core\Event\Image\ImageEvent;
use Thelia\Core\Event\UpdateImagePositionEvent; use Thelia\Core\Event\UpdateFilePositionEvent;
use Thelia\Model\ConfigQuery; use Thelia\Model\ConfigQuery;
use Thelia\Tools\FileManager; use Thelia\Tools\FileManager;
use Thelia\Tools\URL; use Thelia\Tools\URL;
@@ -302,7 +302,7 @@ class Image extends BaseCachedFile implements EventSubscriberInterface
$event->setModelImage($event->getModelImage()); $event->setModelImage($event->getModelImage());
} }
public function updatePosition(UpdateImagePositionEvent $event) public function updatePosition(UpdateFilePositionEvent $event)
{ {
return $this->genericUpdatePosition($event->getQuery(), $event); return $this->genericUpdatePosition($event->getQuery(), $event);
} }

View File

@@ -95,6 +95,11 @@
<requirement key="parentType">.*</requirement> <requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement> <requirement key="parentId">\d+</requirement>
</route> </route>
<route id="admin.document.update-position" path="/admin/document/type/{parentType}/{parentId}/update-position">
<default key="_controller">Thelia\Controller\Admin\FileController::updateDocumentPositionAction</default>
<requirement key="parentType">.*</requirement>
<requirement key="parentId">\d+</requirement>
</route>
<route id="admin.document.update.view" path="/admin/document/type/{parentType}/{documentId}/update" methods="get"> <route id="admin.document.update.view" path="/admin/document/type/{parentType}/{documentId}/update" methods="get">
<default key="_controller">Thelia\Controller\Admin\FileController::viewDocumentAction</default> <default key="_controller">Thelia\Controller\Admin\FileController::viewDocumentAction</default>
<requirement key="parentType">.*</requirement> <requirement key="parentType">.*</requirement>

View File

@@ -25,7 +25,7 @@ namespace Thelia\Controller\Admin;
use Propel\Runtime\Exception\PropelException; use Propel\Runtime\Exception\PropelException;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
use Thelia\Core\Event\UpdateImagePositionEvent; use Thelia\Core\Event\UpdateFilePositionEvent;
use Thelia\Core\HttpFoundation\Response; use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Security\Resource\AdminResources; use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Event\Document\DocumentCreateOrUpdateEvent; use Thelia\Core\Event\Document\DocumentCreateOrUpdateEvent;
@@ -615,10 +615,10 @@ class FileController extends BaseAdminController
} }
// Feed event // Feed event
$imageUpdateImagePositionEvent = new UpdateImagePositionEvent( $imageUpdateImagePositionEvent = new UpdateFilePositionEvent(
$fileManager->getImageModelQuery($parentType), $fileManager->getImageModelQuery($parentType),
$imageId, $imageId,
UpdateImagePositionEvent::POSITION_ABSOLUTE, UpdateFilePositionEvent::POSITION_ABSOLUTE,
$position $position
); );
@@ -650,6 +650,60 @@ class FileController extends BaseAdminController
return new Response($message); return new Response($message);
} }
public function updateDocumentPositionAction($parentType, $parentId)
{
$message = null;
$documentId = $this->getRequest()->request->get('document_id');
$position = $this->getRequest()->request->get('position');
$this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
$this->checkXmlHttpRequest();
$fileManager = new FileManager($this->container);
$documentModelQuery = $fileManager->getDocumentModelQuery($parentType);
$model = $documentModelQuery->findPk($documentId);
if ($model === null || $position === null) {
return $this->pageNotFound();
}
// Feed event
$documentUpdateDocumentPositionEvent = new UpdateFilePositionEvent(
$fileManager->getDocumentModelQuery($parentType),
$documentId,
UpdateFilePositionEvent::POSITION_ABSOLUTE,
$position
);
// Dispatch Event to the Action
try {
$this->dispatch(
TheliaEvents::DOCUMENT_UPDATE_POSITION,
$documentUpdateDocumentPositionEvent
);
} catch (\Exception $e) {
$message = $this->getTranslator()
->trans(
'Fail to update document position',
array(),
'document'
) . $e->getMessage();
}
if(null === $message) {
$message = $this->getTranslator()
->trans(
'Document position updated',
array(),
'document'
);
}
return new Response($message);
}
/** /**
* Manage how a document has to be deleted (AJAX) * Manage how a document has to be deleted (AJAX)
* *

View File

@@ -404,6 +404,7 @@ final class TheliaEvents
* Save given documents * Save given documents
*/ */
const DOCUMENT_UPDATE = "action.updateDocument"; const DOCUMENT_UPDATE = "action.updateDocument";
const DOCUMENT_UPDATE_POSITION = "action.updateDocumentPosition";
/** /**
* Delete given document * Delete given document

View File

@@ -25,7 +25,7 @@ namespace Thelia\Core\Event;
use Propel\Runtime\ActiveQuery\ModelCriteria; use Propel\Runtime\ActiveQuery\ModelCriteria;
class UpdateImagePositionEvent extends UpdatePositionEvent class UpdateFilePositionEvent extends UpdatePositionEvent
{ {
protected $query; protected $query;

View File

@@ -7,6 +7,7 @@ use Propel\Runtime\Connection\ConnectionInterface;
class CategoryDocument extends BaseCategoryDocument class CategoryDocument extends BaseCategoryDocument
{ {
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
use \Thelia\Model\Tools\PositionManagementTrait; use \Thelia\Model\Tools\PositionManagementTrait;
/** /**

View File

@@ -7,6 +7,7 @@ use Propel\Runtime\Connection\ConnectionInterface;
class ContentDocument extends BaseContentDocument class ContentDocument extends BaseContentDocument
{ {
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
use \Thelia\Model\Tools\PositionManagementTrait; use \Thelia\Model\Tools\PositionManagementTrait;
/** /**

View File

@@ -7,6 +7,7 @@ use Propel\Runtime\Connection\ConnectionInterface;
class FolderDocument extends BaseFolderDocument class FolderDocument extends BaseFolderDocument
{ {
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
use \Thelia\Model\Tools\PositionManagementTrait; use \Thelia\Model\Tools\PositionManagementTrait;
/** /**

View File

@@ -7,6 +7,7 @@ use Propel\Runtime\Connection\ConnectionInterface;
class ProductDocument extends BaseProductDocument class ProductDocument extends BaseProductDocument
{ {
use \Thelia\Model\Tools\ModelEventDispatcherTrait;
use \Thelia\Model\Tools\PositionManagementTrait; use \Thelia\Model\Tools\PositionManagementTrait;
/** /**

View File

@@ -6,9 +6,10 @@ $(function($){
// Remove image on click // Remove document on click
$.documentUploadManager.initDocumentDropZone = function() { $.documentUploadManager.initDocumentDropZone = function() {
$.documentUploadManager.onClickDeleteDocument(); $.documentUploadManager.onClickDeleteDocument();
$.documentUploadManager.sortDocument();
var documentDropzone = new Dropzone("#documents-dropzone", { var documentDropzone = new Dropzone("#documents-dropzone", {
dictDefaultMessage : $('.btn-browse').html(), dictDefaultMessage : $('.btn-browse').html(),
@@ -39,6 +40,7 @@ $(function($){
documentDropzone.removeFile(file); documentDropzone.removeFile(file);
$.documentUploadManager.updateDocumentListAjax(); $.documentUploadManager.updateDocumentListAjax();
$.documentUploadManager.onClickDeleteDocument(); $.documentUploadManager.onClickDeleteDocument();
$.documentUploadManager.sortDocument();
}); });
@@ -67,7 +69,7 @@ $(function($){
}); });
}; };
// Remove image on click // Remove document on click
$.documentUploadManager.onClickDeleteDocument = function() { $.documentUploadManager.onClickDeleteDocument = function() {
$('.document-manager .document-delete-btn').on('click', function (e) { $('.document-manager .document-delete-btn').on('click', function (e) {
e.preventDefault(); e.preventDefault();
@@ -97,4 +99,52 @@ $(function($){
return false; return false;
}); });
}; };
$.documentUploadManager.sortDocument = function() {
$( "#js-sort-document" ).sortable({
placeholder: "ui-sortable-placeholder col-sm-6 col-md-3",
change: function( event, ui ) {
/* refresh position */
var pickedElement = ui.item;
var position = 0;
$( "#js-sort-document").children('li').each(function(k, element) {
if($(element).data('sort-id') == pickedElement.data('sort-id')) {
return true;
}
position++;
if($(element).is('.ui-sortable-placeholder')) {
pickedElement.find('.js-sorted-position').html(position);
} else {
$(element).find('.js-sorted-position').html(position);
}
});
},
stop: function( event, ui ) {
/* update */
var newPosition = ui.item.find('.js-sorted-position').html();
var documentId = ui.item.data('sort-id');
$.ajax({
type: "POST",
url: documentReorder,
data: {
document_id: documentId,
position: newPosition
},
statusCode: {
404: function() {
$(".document-manager .message").html(
documentReorderErrorMessage
);
}
}
}).done(function(data) {
$(".document-manager .message").html(
data
);
});
}
});
$( "#js-sort-document" ).disableSelection();
};
}); });

View File

@@ -429,3 +429,16 @@ table {
} }
} }
} }
// document list style
ul.document-list {
> li {
padding: @table-condensed-cell-padding;
line-height: @line-height-base;
border-top: 1px solid @table-border-color;
&:nth-child(odd) {
background-color: @table-bg-accent;
}
}
}

View File

@@ -32,5 +32,7 @@ Parameters:
<script> <script>
var documentDropZoneUrl = "{url path="/admin/document/type/$documentType/$parentId/save-ajax"}"; var documentDropZoneUrl = "{url path="/admin/document/type/$documentType/$parentId/save-ajax"}";
var documentListUrl = "{url path="/admin/document/type/$documentType/$parentId/list-ajax"}"; var documentListUrl = "{url path="/admin/document/type/$documentType/$parentId/list-ajax"}";
var documentReorder = "{url path="/admin/document/type/$documentType/$parentId/update-position"}";
var documentListErrorMessage = "{intl l='Can\'t load documents, please refresh this page.'}"; var documentListErrorMessage = "{intl l='Can\'t load documents, please refresh this page.'}";
var documentReorderErrorMessage = "{intl l='Can\'t reorder documents, please refresh this page.'}";
</script> </script>

View File

@@ -7,29 +7,27 @@ Parameters:
parentId = Document parent id, ex: category id parentId = Document parent id, ex: category id
*} *}
{ifloop rel="document"} {ifloop rel="document"}
<table class="table table-striped table-condensed table-left-aligned"> <ul id="js-sort-document" class="list-unstyled document-list">
{loop type="document" name="document" source="{$documentType}" order="manual" source_id="{$parentId}"} {loop type="document" name="document" source="{$documentType}" order="manual" source_id="{$parentId}"}
<tr> <li class="clearfix ui-state-default" data-sort-id="{$ID}">
<td> <a href="{$DOCUMENT_PATH}" title="{$TITLE}" class="pull-left" target="_blank">{$TITLE}</a>
<a href="{$DOCUMENT_PATH}" title="{$TITLE}" class="" target="_blank">{$TITLE}</a>
</td>
<td> <div class="btn-group pull-right">
<div class="btn-group"> <a class="image-update-btn btn btn-default btn-xs disabled js-sorted-position" href="#">{$POSITION}</a>
<a class="image-update-btn btn btn-default btn-xs disabled js-sorted-position" href="#">{$POSITION}</a> <a class="document-update-btn btn btn-default btn-xs" href="{url path="/admin/document/type/$documentType/$ID/update"}" data-error-message="{intl l='Please retry'}">
<a class="document-update-btn btn btn-default btn-xs" href="{url path="/admin/document/type/$documentType/$ID/update"}" data-error-message="{intl l='Please retry'}"> <span class="glyphicon glyphicon-edit"></span>
<span class="glyphicon glyphicon-edit"></span> </a>
</a> <a class="document-delete-btn btn btn-default btn-xs" href="{url path="/admin/document/type/$documentType/delete/$ID"}" data-error-message="{intl l='Please retry'}">
<a class="document-delete-btn btn btn-default btn-xs" href="{url path="/admin/document/type/$documentType/delete/$ID"}" data-error-message="{intl l='Please retry'}"> <span class="glyphicon glyphicon-trash"></span>
<span class="glyphicon glyphicon-trash"></span> </a>
</a> </div>
</div> </li>
<td>
</tr>
{/loop} {/loop}
</table> </ul>
{/ifloop} {/ifloop}
{elseloop rel="document"} {elseloop rel="document"}
<div class="alert alert-info">{intl l='There is no documents attached to this %type.' type=$documentType}</div> <div class="alert alert-info">{intl l='There is no documents attached to this %type.' type=$documentType}</div>
{/elseloop} {/elseloop}