Commit 21ac3bca authored by Hermann Mayer's avatar Hermann Mayer

Added JMSSerializerBundle. Implemented a simple Section Controller. (Mostly for…

Added JMSSerializerBundle. Implemented a simple Section Controller. (Mostly for AJAX requests) Sidebar Controller Frontend now supports to add empty and existing section prototypes.
parent b1b0d213
......@@ -24,6 +24,7 @@ class AppKernel extends Kernel
new Jity\HomepageBundle\JityHomepageBundle(),
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
new Xi\Bundle\BreadcrumbsBundle\XiBreadcrumbsBundle(),
new JMS\SerializerBundle\JMSSerializerBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
......
......@@ -28,6 +28,7 @@
"sensio/generator-bundle": "2.1.*",
"jms/security-extra-bundle": "1.2.*",
"jms/di-extra-bundle": "1.1.*",
"jms/serializer-bundle": "dev-master",
"doctrine/doctrine-fixtures-bundle": "dev-master",
"doctrine/data-fixtures": "dev-master",
"knplabs/knp-markdown-bundle": "dev-master",
......
{
"hash": "9dfcd511dbc0d40724c84829dc10dea6",
"hash": "c498fc1553cab3e685212307305d8f25",
"packages": [
{
"name": "doctrine/common",
......@@ -677,6 +677,74 @@
"expression"
]
},
{
"name": "jms/serializer-bundle",
"version": "dev-master",
"target-dir": "JMS/SerializerBundle",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/JMSSerializerBundle.git",
"reference": "bd1288b32c0838f03f9a7c90ece80e64c4b78145"
},
"dist": {
"type": "zip",
"url": "https://github.com/schmittjoh/JMSSerializerBundle/zipball/bd1288b32c0838f03f9a7c90ece80e64c4b78145",
"reference": "bd1288b32c0838f03f9a7c90ece80e64c4b78145",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"jms/metadata": ">=1.1.0,<1.3-dev"
},
"conflict": {
"symfony/framework-bundle": "<2.1-dev"
},
"require-dev": {
"twig/twig": ">=1.8,<2.0-dev",
"doctrine/orm": ">=2.1,<2.4-dev",
"symfony/framework-bundle": ">=2.1,<2.2-dev",
"symfony/yaml": ">=2.1,<2.3-dev",
"symfony/form": ">=2.1,<2.3-dev",
"symfony/validator": ">=2.1,<2.3-dev",
"symfony/doctrine-bridge": ">=2.1,<2.2-dev"
},
"suggest": {
"symfony/framework-bundle": "2.*"
},
"time": "1349518993",
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"JMS\\SerializerBundle": ""
}
},
"license": [
"Apache2"
],
"authors": [
{
"name": "Johannes M. Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
}
],
"description": "Allows you to easily serialize, and deserialize object graphs of any complexity",
"homepage": "http://jmsyst.com/bundles/JMSSerializerBundle",
"keywords": [
"json",
"xml",
"serialization",
"deserialization",
"jaxb"
]
},
{
"name": "knplabs/knp-markdown-bundle",
"version": "dev-master",
......@@ -1521,6 +1589,7 @@
],
"minimum-stability": "alpha",
"stability-flags": {
"jms/serializer-bundle": 20,
"doctrine/doctrine-fixtures-bundle": 20,
"doctrine/data-fixtures": 20,
"knplabs/knp-markdown-bundle": 20,
......
<?php
namespace Jity\HomepageBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Jity\HomepageBundle\Entity\Section;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
/**
* SectionController
*
* @uses Controller
* @version $id$
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
class SectionController extends Controller
{
/**
* indexAction
*
* @access public
* @return void
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
// Use DQL because its more powerfull and only one query is needed
$q = $em->createQueryBuilder('s')
->select('s.id, s.title')
->from('JityHomepageBundle:Section', 's')
->getQuery()
;
return new Response(
json_encode($q->getArrayResult())
);
}
/**
* showAction
*
* @param mixed $id
* @access public
* @return void
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('JityHomepageBundle:Section')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Section entity.');
}
$serializer = $this->container->get('serializer');
return new Response(
$serializer->serialize($entity, 'json')
);
}
}
......@@ -4,10 +4,13 @@ namespace Jity\HomepageBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Role\RoleInterface;
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Exclude;
/**
* @ORM\Entity
* @ORM\Table(name="`group`")
* @ExclusionPolicy("None")
*/
class Group implements RoleInterface, \Serializable
{
......@@ -25,6 +28,7 @@ class Group implements RoleInterface, \Serializable
* joinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="parent_group_id", referencedColumnName="id")}
* )
* @Exclude
*/
protected $parents;
......@@ -40,11 +44,13 @@ class Group implements RoleInterface, \Serializable
/**
* @ORM\ManyToMany(targetEntity="User", mappedBy="groups")
* @Exclude
*/
protected $users;
/**
* @ORM\OneToMany(targetEntity="Section", mappedBy="group")
* @Exclude
**/
protected $sections;
......
......@@ -3,10 +3,13 @@
namespace Jity\HomepageBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Exclude;
/**
* @ORM\Entity
* @ORM\Table(name="section")
* @ExclusionPolicy("None")
*/
class Section
{
......@@ -39,6 +42,7 @@ class Section
* mappedBy="section",
* cascade={"persist", "remove"}
* )
* @Exclude
*/
protected $sidebarSection;
......
......@@ -30,10 +30,13 @@ class SidebarType extends AbstractType
$builder
->add('name')
->add('sections', 'collection', array(
'type' => new SectionType(),
'label' => 'Verbundene Sektionen',
'label_attr' => array(
'class' => 'form_embedded_label'
'type' => new SectionType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Verbundene Sektionen',
'label_attr' => array(
'class' => 'form_embedded_label'
)
))
;
......
......@@ -22,6 +22,10 @@ JityHomepageBundle_author_sidebar:
resource: "@JityHomepageBundle/Resources/config/routing/sidebar.yml"
prefix: /author/sidebar
JityHomepageBundle_author_section:
resource: "@JityHomepageBundle/Resources/config/routing/section.yml"
prefix: /author/section
JityHomepageBundle_user:
resource: "@JityHomepageBundle/Resources/config/routing/user.yml"
prefix: /user
......
author_section:
pattern: /
defaults: { _controller: "JityHomepageBundle:Section:index", label: "Sidebars", parent: "author_dashboard", _format: "json" }
author_section_show:
pattern: /{id}/show
defaults: { _controller: "JityHomepageBundle:Section:show", label: "Details", parent: "author_section", _format: "json" }
......@@ -381,6 +381,12 @@ hr {
padding-right: 59px;
}
.sortable-new {
background-image: url("/bundles/jityhomepage/img/new-sortable-bg.png");
background-repeat:no-repeat;
background-position:right bottom;
}
.sortable .dragbar {
cursor: pointer;
position: absolute;
......
......@@ -21,7 +21,7 @@
{% spaceless %}
<div class="control-group">
<label class="control-label" {% for attrname,attrvalue in label_attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{{ form_label(form) }}</label>
<label class="control-label" {{ block('widget_attributes') }}>{{ form_label(form) }}</label>
<div class="controls">
{{ form_widget(form) }}
<span class="help-inline">{{ form_errors(form) }}</span>
......@@ -50,7 +50,7 @@
{% for rows in form %}
<div class="sortable">
<div class="sortable {{ form.vars.full_name }}">
<div class="dragbar"></div>
<div class="controllpanel">
......@@ -67,10 +67,103 @@
{% endfor %}
{{ form_rest(form) }}
</div>
<script>
$(document).ready(function() {
collections = {
amount: {{ form|length }},
widgets: {{ form.0|length }},
form: "{{ form.vars.full_name }}".replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
itemPattern: "("
+ "{{ form.vars.full_name }}".replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
+ "\\[).+(\\]\\[.+\\]$)",
replaceItemIndex: function(name, index) {
return name.replace(
new RegExp(this.itemPattern),
"$1" + index +"$2"
);
},
reorderWidgetsNames: function() {
$('.' + this.form).each(function (c, el){
$(el).find(':input').each(function (i, input){
var cur = $(input);
cur.attr('name', collections.replaceItemIndex(cur.attr('name'), c));
});
});
},
add: function(data) {
var coll = $('#{{ form.vars.id }}');
var prototype = coll.attr('data-prototype');
// Replace '__name__' in the prototype's HTML to
// instead be a number based on the current collection's length.
var el = $(
prototype.replace(/__name__/g, coll.children().length)
);
// If we got data to fill our prototype with
if (data) {
el.find(':input').each(function (i, input) {
$(input).val(data[i]);
});
}
// Add new element to the top of the collection
el.prependTo(coll).hide().slideDown();
},
initSortable: function() {
$('.collection > div').sortable({
placeholder: "ui-state-highlight",
helper: 'clone',
stop: function(event, ui) { collections.reorderWidgetsNames(); }
});
}
};
});
</script>
</div>
{% endspaceless %}
{% endblock collection_widget %}
{#
Embedded Collection (sortable) Prototype Styling
#}
{% block collection_item_widget %}
{% spaceless %}
<div class="sortable sortable-new {{ form.vars.full_name }}">
<div class="dragbar"></div>
<div class="controllpanel">
<a class="btn btn-danger btn-remove" title="Entfernen" href="#">
<i class="icon-white icon-remove"></i>
</a>
</div>
{% for row in prototype %}
{{ form_row(row) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock collection_item_widget %}
......@@ -16,6 +16,8 @@
} %}
<script>
$(document).ready(function() {
$('textarea[data-target="#editor_modal"]').bind('focus', function(){
editor.setSyncElement('#' + $(this).attr('id'));
});
......@@ -27,47 +29,76 @@
+ '</div>'
);
$('.collection > div').sortable({
placeholder: "ui-state-highlight",
helper:'clone'
});
// Start sortable ui for the collection
collections.initSortable();
$('.btn-remove').click(function (e){
sections = {
init: function() {
$('.btn-remove').click(function (e){
// Dont do anything on link clicking
e.preventDefault();
// Dont do anything on link clicking
e.preventDefault();
// Configure and run the modal
confirmModal
.setLabel('Bestätigung der Löschaktion')
.setBody('Möchten Sie dieses Element wirklich löschen?')
.setButtons([
{
id: 1,
class: 'btn-danger',
icon: 'icon-share-alt',
value: 'Abbrechen'
},
{
id: 2,
class: 'btn-primary',
icon: 'icon-ok',
value: 'Löschen',
data: this,
click: function (data){
var el = $(data).closest('.sortable');
el.slideUp(function() {
// At end of sliding remove element from dom
el.remove();
});
}
// Configure and run the modal
confirmModal
.setLabel('Bestätigung der Löschaktion')
.setBody('Möchten Sie dieses Element wirklich löschen?')
.setButtons([
{
id: 1,
class: 'btn-danger',
icon: 'icon-share-alt',
value: 'Abbrechen'
},
{
id: 2,
class: 'btn-primary',
icon: 'icon-ok',
value: 'Löschen',
data: this,
click: function (data){
var el = $(data).closest('.sortable');
el.slideUp(function() {
// At end of sliding remove element from dom
el.remove();
});
}
}
])
.show()
;
});
},
fetchAndAdd: function(id) {
// Build the path for the request
var path = '{{ path('author_section_show', {id: "__id__"}) }}'.replace(/__id__/g, id);
// Get the requested data and write it to a new section
$.get(
path,
function(data) {
console.log(data);
collections.add([
data.title,
data.content,
(data.group) ? data.group.id : 0
]);
sections.init();
}
])
.show()
;
});
);
}
}
sections.init();
$('#section_btn_add').click(function (e){
......@@ -78,15 +109,12 @@
confirmModal
.setLabel('Was möchten Sie tun?')
.setBody(
' <div>'
' <div>'
+ ' <legend class="h2">Bestehende Sektion</legend>'
+ ' Sie können an dieser Stelle problemlos bereits bestehende Sektionen hinzufügen und diese sortieren.<br><br>'
+ ' <select id="section_new_select" style="margin-bottom: 0px;">'
+ ' <option value="1">Test #1</option>'
+ ' <option value="1">Test #2</option>'
+ ' <option value="1">Test #2</option>'
+ ' </select>'
+ ' <a class="btn btn-primary" href="#">'
+ ' <a class="btn btn-primary" href="#" onclick="sections.fetchAndAdd($(\'#section_new_select\').find(\':selected\').val()); confirmModal.hide();">'
+ ' <i class="icon-white icon-ok"></i>'
+ ' Hinzufügen'
+ ' </a>'
......@@ -94,7 +122,7 @@
+ ' <div>'
+ ' <legend class="h2">Neue Sektion</legend>'
+ ' Es ist aber auch möglich neue Sektionen gleich in diesem Schritt anzulegen.<br><br>'
+ ' <a class="btn btn-primary" href="#">'
+ ' <a class="btn btn-primary" href="#" onclick="collections.add(); sections.init(); confirmModal.hide();">'
+ ' <i class="icon-white icon-ok"></i>'
+ ' Anlegen'
+ ' </a>'
......@@ -114,5 +142,19 @@
])
.show()
;
// Get all section names
var existingSections = {% render 'JityHomepageBundle:Section:index' %};
var sectionsSelect = $('#section_new_select');
// Fill the select with this list
existingSections.forEach(function (cur) {
sectionsSelect.append(
$('<option></option>').val(cur.id).html(cur.title)
);
});
});
});
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment