Commit d0fd1d63 authored by Hermann Mayer's avatar Hermann Mayer

Added Jity/Tag-Generator-Bundle. Build Frontend for the Tag-Generator in Article Forms.

parent bc8f7397
......@@ -29,6 +29,7 @@ class AppKernel extends Kernel
new SunCat\MobileDetectBundle\MobileDetectBundle(),
new EWZ\Bundle\RecaptchaBundle\EWZRecaptchaBundle(),
new Presta\SitemapBundle\PrestaSitemapBundle(),
new Jity\TagGeneratorBundle\JityTagGeneratorBundle(),
);
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
......
No preview for this file type
......@@ -43,7 +43,8 @@
"hwi/oauth-bundle": "dev-master",
"suncat/mobile-detect-bundle": "dev-master",
"excelwebzone/recaptcha-bundle": "dev-master",
"presta/sitemap-bundle": "dev-sitemap-dumper"
"presta/sitemap-bundle": "dev-sitemap-dumper",
"jity/tag-generator": "dev-master"
},
"scripts": {
"post-install-cmd": [
......
This diff is collapsed.
......@@ -83,7 +83,7 @@ class ArticleController extends Controller
$em = $this->getDoctrine()->getManager();
$entity = $this->mergeEntity($request, $em, $form, $entity);
$entity = $this->mergeEntity($request, $em, $form, $entity);
$em->persist($entity);
$em->flush();
......@@ -131,15 +131,15 @@ class ArticleController extends Controller
$entity = $em->getRepository('JityHomepageBundle:Article')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Article entity.');
}
// First clear all tags, they will be new added
foreach ($entity->getTags() as $tag) {
$entity->removeTag($tag);
}
if (!$entity) {
throw $this->createNotFoundException('Unable to find Article entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createForm(new ArticleType(), $entity);
$editForm->bind($request);
......@@ -166,16 +166,16 @@ class ArticleController extends Controller
}
/**
* mergeEntity
*
* mergeEntity
*
* Add collection merge support. So unique elements
* will be connected instead of new inserted and
* changes to the connected entites will be merged.
*
* @param Request $request
* @param mixed $em
* @param mixed $form
* @param mixed $entity
* @param Request $request
* @param mixed $em
* @param mixed $form
* @param mixed $entity
* @access private
* @return void
*/
......@@ -230,9 +230,9 @@ class ArticleController extends Controller
}
/**
* createDeleteForm
*
* @param mixed $id
* createDeleteForm
*
* @param mixed $id
* @access private
* @return void
*/
......
......@@ -20,6 +20,9 @@ class EditorController extends Controller
/**
* formatAction
*
* @param Request $request
* @param mixed $text
*
* @access public
* @return void
*/
......@@ -28,7 +31,7 @@ class EditorController extends Controller
// Get markdown parser service
$parser = $this->container->get('markdown.parser');
if (empty($text)) {
if (true === empty($text)) {
// Get 'text' variable from POST
$text = $request->request->get('text');
......@@ -61,6 +64,36 @@ class EditorController extends Controller
));
}
/**
* tagsAction
*
* @param Request $request
* @param mixed $text
*
* @access public
* @return void
*/
public function tagsAction(Request $request, $text)
{
// Get Jity Tag Generator
$generator = $this->container->get('jity.tag.generator');
if (true === empty($text)) {
// Get 'text' variable from POST
$text = $request->request->get('text');
}
$serializer = $this->container->get('serializer');
return new Response(
$serializer->serialize(
$generator->getTags($text)->toArray(),
'json'
)
);
}
/**
* modalAction
*
......
......@@ -7,19 +7,19 @@ use Symfony\Component\Form\AbstractType,
Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* ArticleType
*
* ArticleType
*
* @uses AbstractType
* @version $id$
* @author Hermann Mayer <hermann.mayer92@gmail.com>
* @author Hermann Mayer <hermann.mayer92@gmail.com>
*/
class ArticleType extends AbstractType
{
/**
* buildForm
*
* @param FormBuilderInterface $builder
* @param array $options
* buildForm
*
* @param FormBuilderInterface $builder
* @param array $options
* @access public
* @return void
*/
......@@ -101,22 +101,24 @@ class ArticleType extends AbstractType
}
/**
* setDefaultOptions
*
* @param OptionsResolverInterface $resolver
* setDefaultOptions
*
* @param OptionsResolverInterface $resolver
* @access public
* @return void
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Jity\HomepageBundle\Entity\Article'
'data_class' => 'Jity\HomepageBundle\Entity\Article',
// We want to validate our embedded tag form
'cascade_validation' => true
));
}
/**
* getName
*
* getName
*
* @access public
* @return void
*/
......
......@@ -3,3 +3,8 @@ editor_format:
defaults: { _controller: JityHomepageBundle:Editor:format, text: '' }
requirements: { _method: post }
editor_tags:
pattern: /tags
defaults: { _controller: JityHomepageBundle:Editor:tags, text: '' }
requirements: { _method: post }
......@@ -40,4 +40,9 @@ Jity\HomepageBundle\Entity\Comment:
- NotBlank: { message: "Diese Angabe muss noch ausgefüllt werden." }
- Length: { min: 2, minMessage: "Diese Angabe muss mindestens {{ limit }} Zeichen lang sein." }
Jity\HomepageBundle\Entity\Tag:
properties:
name:
- NotBlank: { message: "Diese Angabe muss noch ausgefüllt werden." }
- Length: { min: 2, minMessage: "Diese Angabe muss mindestens {{ limit }} Zeichen lang sein." }
......@@ -222,7 +222,7 @@ a {
color: #D2551C;
}
a:hover, a:focus {
a:hover {
color: #D21B0E;
}
......
......@@ -49,7 +49,7 @@ a {
color: #D2551C;
}
a:hover, a:focus {
a:hover {
color: #D21B0E;
}
......
//fgnass.github.com/spin.js#v1.2.7
!function(e,t,n){function o(e,n){var r=t.createElement(e||"div"),i;for(i in n)r[i]=n[i];return r}function u(e){for(var t=1,n=arguments.length;t<n;t++)e.appendChild(arguments[t]);return e}function f(e,t,n,r){var o=["opacity",t,~~(e*100),n,r].join("-"),u=.01+n/r*100,f=Math.max(1-(1-e)/t*(100-u),e),l=s.substring(0,s.indexOf("Animation")).toLowerCase(),c=l&&"-"+l+"-"||"";return i[o]||(a.insertRule("@"+c+"keyframes "+o+"{"+"0%{opacity:"+f+"}"+u+"%{opacity:"+e+"}"+(u+.01)+"%{opacity:1}"+(u+t)%100+"%{opacity:"+e+"}"+"100%{opacity:"+f+"}"+"}",a.cssRules.length),i[o]=1),o}function l(e,t){var i=e.style,s,o;if(i[t]!==n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(o=0;o<r.length;o++){s=r[o]+t;if(i[s]!==n)return s}}function c(e,t){for(var n in t)e.style[l(e,n)||n]=t[n];return e}function h(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var i in r)e[i]===n&&(e[i]=r[i])}return e}function p(e){var t={x:e.offsetLeft,y:e.offsetTop};while(e=e.offsetParent)t.x+=e.offsetLeft,t.y+=e.offsetTop;return t}var r=["webkit","Moz","ms","O"],i={},s,a=function(){var e=o("style",{type:"text/css"});return u(t.getElementsByTagName("head")[0],e),e.sheet||e.styleSheet}(),d={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",speed:1,trail:100,opacity:.25,fps:20,zIndex:2e9,className:"spinner",top:"auto",left:"auto",position:"relative"},v=function m(e){if(!this.spin)return new m(e);this.opts=h(e||{},m.defaults,d)};v.defaults={},h(v.prototype,{spin:function(e){this.stop();var t=this,n=t.opts,r=t.el=c(o(0,{className:n.className}),{position:n.position,width:0,zIndex:n.zIndex}),i=n.radius+n.length+n.width,u,a;e&&(e.insertBefore(r,e.firstChild||null),a=p(e),u=p(r),c(r,{left:(n.left=="auto"?a.x-u.x+(e.offsetWidth>>1):parseInt(n.left,10)+i)+"px",top:(n.top=="auto"?a.y-u.y+(e.offsetHeight>>1):parseInt(n.top,10)+i)+"px"})),r.setAttribute("aria-role","progressbar"),t.lines(r,t.opts);if(!s){var f=0,l=n.fps,h=l/n.speed,d=(1-n.opacity)/(h*n.trail/100),v=h/n.lines;(function m(){f++;for(var e=n.lines;e;e--){var i=Math.max(1-(f+e*v)%h*d,n.opacity);t.opacity(r,n.lines-e,i,n)}t.timeout=t.el&&setTimeout(m,~~(1e3/l))})()}return t},stop:function(){var e=this.el;return e&&(clearTimeout(this.timeout),e.parentNode&&e.parentNode.removeChild(e),this.el=n),this},lines:function(e,t){function i(e,r){return c(o(),{position:"absolute",width:t.length+t.width+"px",height:t.width+"px",background:e,boxShadow:r,transformOrigin:"left",transform:"rotate("+~~(360/t.lines*n+t.rotate)+"deg) translate("+t.radius+"px"+",0)",borderRadius:(t.corners*t.width>>1)+"px"})}var n=0,r;for(;n<t.lines;n++)r=c(o(),{position:"absolute",top:1+~(t.width/2)+"px",transform:t.hwaccel?"translate3d(0,0,0)":"",opacity:t.opacity,animation:s&&f(t.opacity,t.trail,n,t.lines)+" "+1/t.speed+"s linear infinite"}),t.shadow&&u(r,c(i("#000","0 0 4px #000"),{top:"2px"})),u(e,u(r,i(t.color,"0 0 1px rgba(0,0,0,.1)")));return e},opacity:function(e,t,n){t<e.childNodes.length&&(e.childNodes[t].style.opacity=n)}}),function(){function e(e,t){return o("<"+e+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',t)}var t=c(o("group"),{behavior:"url(#default#VML)"});!l(t,"transform")&&t.adj?(a.addRule(".spin-vml","behavior:url(#default#VML)"),v.prototype.lines=function(t,n){function s(){return c(e("group",{coordsize:i+" "+i,coordorigin:-r+" "+ -r}),{width:i,height:i})}function l(t,i,o){u(a,u(c(s(),{rotation:360/n.lines*t+"deg",left:~~i}),u(c(e("roundrect",{arcsize:n.corners}),{width:r,height:n.width,left:n.radius,top:-n.width>>1,filter:o}),e("fill",{color:n.color,opacity:n.opacity}),e("stroke",{opacity:0}))))}var r=n.length+n.width,i=2*r,o=-(n.width+n.length)*2+"px",a=c(s(),{position:"absolute",top:o,left:o}),f;if(n.shadow)for(f=1;f<=n.lines;f++)l(f,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(f=1;f<=n.lines;f++)l(f);return u(t,a)},v.prototype.opacity=function(e,t,n,r){var i=e.firstChild;r=r.shadow&&r.lines||0,i&&t+r<i.childNodes.length&&(i=i.childNodes[t+r],i=i&&i.firstChild,i=i&&i.firstChild,i&&(i.opacity=n))}):s=l(t,"animation")}(),typeof define=="function"&&define.amd?define(function(){return v}):e.Spinner=v}(window,document);
$.fn.spin = function(opts) {
this.each(function() {
var $this = $(this),
data = $this.data();
if (data.spinner) {
data.spinner.stop();
delete data.spinner;
}
if (opts !== false) {
var opts = {
lines: 17, // The number of lines to draw
length: 2, // The length of each line
width: 2, // The line thickness
radius: 11, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 0, // The rotation offset
color: '#fff', // #rgb or #rrggbb
speed: 1.2, // Rounds per second
trail: 30, // Afterglow percentage
shadow: true, // Whether to render a shadow
hwaccel: true, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: 'auto', // Top position relative to parent in px
left: 'auto' // Left position relative to parent in px
};
data.spinner = new Spinner($.extend({color: $this.css('color')}, opts)).spin(this);
}
});
return this;
};
......@@ -168,5 +168,10 @@ $(document).ready(function() {
}();
$.fn.modal.defaults.maxHeight = function(){
// subtract the height of the modal header and footer
return $(window).height() - 200;
}
});
......@@ -43,11 +43,12 @@ $(document).ready(function() {
+ '</div>'
);
// Start sortable ui for the collection
collections.initSortable();
tags = {
analysedTags: undefined,
init: function() {
......@@ -113,9 +114,9 @@ $(document).ready(function() {
$(
'<p id="no_sections_msg">'
+ '<img class="pull-right" src="{{ asset('bundles/jityhomepage/img/help/no-section-arrow.png') }}" />'
+ '<br>Noch sind keine Sektionen mit dieser Sidebar verbunden.<br>'
+ '<br>Noch sind keine Tags mit diesem Artikel verbunden.<br>'
+ 'Das soll natürlich nicht so bleiben, deshalb können Sie ganz bequem über<br>'
+ 'diesen Knopf neue Sektionen anlegen, oder bestehende verbinden.'
+ 'diesen Knopf neue Tags anlegen, oder bestehende verbinden.'
+ '</p>'
).insertBefore(list.first()).hide().fadeIn();
......@@ -149,6 +150,34 @@ $(document).ready(function() {
tags.init();
}
);
},
analyseText: function() {
$('#tags_spinner').spin();
$.post(
'{{ path('editor_tags') }}',
{text: $('textarea[id="jity_homepagebundle_articletype_content"]').val()},
function(data) {
data = jQuery.parseJSON(data);
tags.analysedTags = data;
$('#parsed_tags_new_select option').replaceWith('');
for (var property in data) {
$('#parsed_tags_new_select').append(
$('<option></option>').html(data[property].name)
);
};
$('#tags_spinner').spin().hide();
$('#parsed_tags_new_select').show();
$('#add-parsed-btn').show();
}
);
}
}
......@@ -164,7 +193,7 @@ $(document).ready(function() {
.setLabel('Was möchten Sie tun?')
.setBody(
' <div>'
+ ' <legend class="h2">Bestehende Sektion</legend>'
+ ' <legend class="h2">Bestehender Tag</legend>'
+ ' Sie können an dieser Stelle problemlos bereits bestehende Tags hinzufügen und diese sortieren.<br><br>'
+ ' <select id="tags_new_select" style="margin-bottom: 0px;">'
+ ' </select>'
......@@ -173,8 +202,24 @@ $(document).ready(function() {
+ ' Hinzufügen'
+ ' </a>'
+ ' </div><br>'
+ ' <div>'
+ ' <legend class="h2">Tag aus Text ermitteln</legend>'
+ ' Mit Hilfe dieser Funktionalität wird Ihr Text analysiert und passende Tags zur Auswahl zur Verfügung gestellt.<br><br>'
+ ' <select id="parsed_tags_new_select" style="display: none; margin-bottom: 0px;">'
+ ' </select><div id="tags_spinner"></div>'
+ ' <a class="btn btn-primary" href="#" onclick="tags.analyseText(); return false;">'
+ ' <i class="icon-white icon-refresh"></i>'
+ ' Text Analysieren'
+ ' </a>'
+ ' <a id="add-parsed-btn" class="btn btn-primary" href="#" style="display: none" onclick="collections.add({class: \'sortable-new\'}, [undefined, $(\'#parsed_tags_new_select\').find(\':selected\').val()], $(\'#tags-list-100\')); tags.init(); confirmModal.hide(); return false;">'
+ ' <i class="icon-white icon-ok"></i>'
+ ' Hinzufügen'
+ ' </a>'
+ ' </div><br>'
+ ' <div>'
+ ' <legend class="h2">Neue Sektion</legend>'
+ ' <legend class="h2">Neuer Tag</legend>'
+ ' Es ist aber auch möglich neue Tags gleich in diesem Schritt anzulegen.<br><br>'
+ ' <a class="btn btn-primary" href="#" onclick="collections.add({class: \'sortable-new\'}, [undefined, new String()], $(\'#tags-list-100\')); tags.init(); confirmModal.hide(); return false;">'
+ ' <i class="icon-white icon-ok"></i>'
......@@ -208,6 +253,20 @@ $(document).ready(function() {
$('<option></option>').val(cur.id).html(cur.name)
);
});
if (tags.analysedTags) {
for (var property in tags.analysedTags) {
$('#parsed_tags_new_select').append(
$('<option></option>').html(tags.analysedTags[property].name)
);
$('#parsed_tags_new_select').show();
$('#add-parsed-btn').show();
};
}
});
});
</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