Browse Source

New comment form behaviour
logic to ensure consistent listeners for comment buttons
heartbeat loader
fixes for HeartbeatForm

logicp 7 years ago
parent
commit
e205df12bd

+ 19 - 3
css/heartbeat.css

@@ -23,6 +23,14 @@
   max-width: 100%;
 }
 
+.heartbeat-comments {
+  display: none;
+}
+
+.heartbeat-comments-visible {
+  display: block!important;
+}
+
 /*Imgs displayed in colorbox*/
 
 .cboxPhoto {
@@ -154,9 +162,6 @@ Temporarily hiding all irrelevant content */
 #block-heartbeatblock #block-kekistan-breadcrumbs,
 #block-heartbeatblock #block-kekistan-page-title { display: none}
 
-/*.heartbeat-stream #content {*/
-  /*margin-left: 0;*/
-/*}*/
 
 #block-heartbeatblock #content {
   margin-left: 0!important;
@@ -164,6 +169,17 @@ Temporarily hiding all irrelevant content */
 }
 
 
+#heartbeat-loader {
+  display: none;
+  position: fixed;
+  bottom: 48px;
+  right: 24px;
+  min-width: 64px;
+  min-height: 64px;
+  background: url('/sites/default/files/inline-images/lRq6T7n.gif');
+  background-size: contain;
+}
+
 
 /*heartbeat-stream section.section {*/
   /*padding: 0;*/

+ 157 - 30
js/heartbeat.js

@@ -1,16 +1,71 @@
 /**
  * Created by logicp on 5/28/17.
  */
+
+const commentListen = function(e) {
+
+  let commentBlock = e.srcElement.parentNode.parentNode.querySelector('.heartbeat-comments');
+
+  if (!commentBlock.classList.contains('heartbeat-comments-visible')) {
+    commentBlock.className += ' heartbeat-comments-visible';
+  } else {
+    commentBlock.classList.remove('heartbeat-comments-visible');
+  }
+
+
+  if (drupalSettings.user.uid > 0) {
+
+    let childs = e.srcElement.parentNode.querySelectorAll('.form-submit, .js-form-type-textarea');
+    console.dir(childs);
+    for (let c = 0; c < childs.length; c++) {
+      toggleCommentElements(childs[c]);
+    }
+  } else {
+    // loginModal()
+    $.ajax({
+      type: 'GET',
+      url: '/user/modal/login',
+      success: function (response) {
+        mainContainer = document.getElementById('main');
+        loginBlock = document.createElement('div');
+        loginBlock.innerHTML = response;
+        loginBlock.className = 'kekistan-login-block';
+        loginBlock.id = 'kekistan-login-block';
+        closeBtn = document.createElement('div');
+        closeBtn.className =  'kekistan-login-block-close';
+        closeBtn.innerHTML = '✖';
+        loginBlock.appendChild(closeBtn);
+        mainContainer.appendChild(loginBlock);
+
+        closeBtn.addEventListener('click', function() {
+          loginBlock.innerHTML = '';
+          mainContainer.removeChild(loginBlock);
+        });
+
+      }
+    });
+  }
+};
+
+
 (function($, Drupal, drupalSettings) {
+
+  $(document).ready(function() {
+
+    const loader = document.createElement('div');
+    loader.id = 'heartbeat-loader';
+    const body = document.getElementsByTagName('body')[0];
+    body.appendChild(loader);
+
     Drupal.behaviors.heartbeat = {
         attach: function (context, settings) {
 
           if (drupalSettings.friendData != null) {
-            var divs = document.querySelectorAll('.flag-friendship a.use-ajax');
+            let divs = document.querySelectorAll('.flag-friendship a.use-ajax');
 
             for (let i = 0; i < divs.length; i++) {
               let anchor = divs[i];
-              var userId = anchor.href.substring(anchor.href.indexOf('friendship') + 11, anchor.href.indexOf('?destination'));
+              let userId = anchor.href.substring(anchor.href.indexOf('friendship') + 11, anchor.href.indexOf('?destination'));
               JSON.parse(drupalSettings.friendData).forEach(function (friendship) {
                 if (friendship.uid_target === userId && friendship.uid == drupalSettings.user.uid && friendship.status == 0) {
                   anchor.innerHTML = 'Friendship Pending';
@@ -76,21 +131,26 @@
               });
             }
           };
+        }
+    };
 
-          let stream = document.querySelector('.heartbeat-stream');
+    commentFormListeners();
+    let stream = document.getElementById('block-heartbeatblock');
 
-          let observer = new MutationObserver(function(mutations) {
-            listenImages();
-          });
+    let observer = new MutationObserver(function(mutations) {
+    console.log('observer observes a change');
+    listenImages();
+    hideCommentForms();
+    commentFormListeners();
+    });
 
-          let config = { attributes: true, childList: true, characterData: true };
+    let config = { attributes: true, childList: true, characterData: true };
 
-          observer.observe(stream, config);
-        }
-    };
+    observer.observe(stream, config);
+    console.dir(observer);
 
 
-  function updateFeed() {
+    function updateFeed() {
 
     $.ajax({
       type: 'POST',
@@ -98,9 +158,9 @@
       success: function (response) {
       }
     })
-  }
+    }
 
-  function listenImages() {
+    function listenImages() {
     let cboxOptions = {
       maxWidth: '960px',
       maxHeight: '960px',
@@ -111,22 +171,20 @@
       let phid = parentClass.substring(parentClass.indexOf('hid') + 4);
       $(this).colorbox({rel: phid, href: $(this).attr('src'), cboxOptions});
     });
-  }
+    }
 
-  function listenCommentPost() {
-    //TODO is drupal data selector enough? I doubt it.
+    function listenCommentPost() {
     let comments = document.querySelectorAll('[data-drupal-selector]');
 
     for (let i = 0; i < comments.length; i++) {
       let comment = comments[i];
-      // console.dir(comment);
       comment.addEventListener('click', function() {
           getParent(comment);
       })
     }
-  }
+    }
 
-  function getParent(node) {
+    function getParent(node) {
     if (node != null && node != undefined && node.classList != undefined && node.classList.contains('heartbeat-comment')) {
       let id = node.id.substr(node.id.indexOf('-') + 1);
       $.ajax({
@@ -140,9 +198,9 @@
         getParent(node.parentNode);
       }
     }
-  }
+    }
 
-  function getScrollXY() {
+    function getScrollXY() {
     var scrOfX = 0, scrOfY = 0;
     if( typeof( window.pageYOffset ) == 'number' ) {
       //Netscape compliant
@@ -158,19 +216,19 @@
       scrOfX = document.documentElement.scrollLeft;
     }
     return [ scrOfX, scrOfY ];
-  }
+    }
 
-//taken from http://james.padolsey.com/javascript/get-document-height-cross-browser/
-  function getDocHeight() {
+    //taken from http://james.padolsey.com/javascript/get-document-height-cross-browser/
+    function getDocHeight() {
     var D = document;
     return Math.max(
       D.body.scrollHeight, D.documentElement.scrollHeight,
       D.body.offsetHeight, D.documentElement.offsetHeight,
       D.body.clientHeight, D.documentElement.clientHeight
     );
-  }
+    }
 
-  document.addEventListener("scroll", function (event) {
+    document.addEventListener("scroll", function (event) {
 
     if (drupalSettings.filterMode == false && (getScrollXY()[1] + window.innerHeight) / getDocHeight() > 0.99) {
 
@@ -188,24 +246,31 @@
 
             drupalSettings.lastHid = hid;
 
+            $('#heartbeat-loader').show(225);
+
             $.ajax({
               type: 'POST',
               url: '/heartbeat/update_feed/' + hid,
+
               success: function (response) {
 
                 feedBlock = document.getElementById('block-heartbeatblock');
                 insertNode = document.createElement('div');
                 insertNode.innerHTML = response;
-                feedBlock.appendChild(insertNode);
+                feedBlock.appendChild(insertNode)
+              },
+
+              complete: function() {
+                $('#heartbeat-loader').hide(225);
               }
             });
           }
         }
       }
     }
-  });
+    });
 
-  $(document).on('cbox_open', function() {
+    $(document).on('cbox_open', function() {
     $("#colorbox").swipe( {
       //Generic swipe handler for all directions
       swipeLeft:function(event, direction, distance, duration, fingerCount) {
@@ -243,7 +308,69 @@
     return true;
 
     }
-  );
+    );
 
+    })
 })(jQuery, Drupal, drupalSettings);
 
+function commentFormListeners() {
+  console.log('Comment Form Listeners');
+  let cFormButtons = document.querySelectorAll('.heartbeat-comment-button');
+
+
+  for (let b = 0; b < cFormButtons.length; b++) {
+    cFormButtons[b].removeEventListener('click', commentListen);
+    cFormButtons[b].addEventListener('click', commentListen);
+  }
+}
+
+
+
+/******** Load Login Block **********
+ ******** append to document ********
+ ******** Hover in middle of screen */
+
+function loginModal() {
+
+  $.ajax({
+    type: 'GET',
+    url: '/user/modal/login',
+    success: function (response) {
+      mainContainer = document.getElementById('main');
+      loginBlock = document.createElement('div');
+      loginBlock.innerHTML = response;
+      loginBlock.className = 'kekistan-login-block';
+      loginBlock.id = 'kekistan-login-block';
+      closeBtn = document.createElement('div');
+      closeBtn.className =  'kekistan-login-block-close';
+      closeBtn.innerHTML = '✖';
+      loginBlock.appendChild(closeBtn);
+      mainContainer.appendChild(loginBlock);
+
+      closeBtn.addEventListener('click', function() {
+        loginBlock.innerHTML = '';
+        mainContainer.removeChild(loginBlock);
+      });
+
+    }
+  });
+}
+
+function hideCommentForms() {
+  let forms = document.querySelectorAll('.heartbeat-comment-form .js-form-type-textarea, .heartbeat-comment-form .form-submit');
+
+  for (let f = 0; f < forms.length; f++) {
+    forms[f].className += ' comment-form-hidden';
+  }
+}
+
+function toggleCommentElements(node) {
+
+  console.dir(node);
+  if (node.classList.contains('comment-form-hidden')) {
+    console.log('removing comment-form-hidden class from element');
+    node.classList.remove('comment-form-hidden');
+  } else {
+    node.className += ' comment-form-hidden';
+  }
+}

+ 7 - 14
src/Form/HeartbeatCommentForm.php

@@ -2,11 +2,11 @@
 
 namespace Drupal\heartbeat\Form;
 
+use Drupal\Core\Ajax\PrependCommand;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Comment\Entity\Comment;
 use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Ajax\AppendCommand;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\statusmessage\MarkupGenerator;
 
@@ -24,14 +24,6 @@ class HeartbeatCommentForm extends FormBase {
     /**
      * {@inheritdoc}
      */
-  public static function create(ContainerInterface $container)
-  {
-    return new static(
-//      $container->get('status_type_service'),
-//      $container->get('statusservice'),
-      $container->get('markupgenerator'));
-  }
-
 
   /**
    * {@inheritdoc}
@@ -51,7 +43,6 @@ class HeartbeatCommentForm extends FormBase {
   public function buildForm(array $form, FormStateInterface $form_state) {
     $form['comment_body'] = array(
       '#type' => 'textarea',
-      '#prefix' => '<div class="heartbeat-comment-button">Comment</div>',
       '#title' => $this->t('Comment Body'),
     );
 
@@ -82,9 +73,11 @@ class HeartbeatCommentForm extends FormBase {
 
       if (strlen(trim($commentBody)) > 1) {
         $extraMarkup = null;
-        if (!empty($urls = $this->markupGenerator->validateUrl($commentBody))) {
-          $url = array_values($urls)[0];
-          $url = !is_array($url) ? $url : array_values($url)[0];
+        $sharedUrls = array_values($this->markupGenerator->validateUrl($commentBody))[0];
+
+        if (!empty($sharedUrls)) {
+
+          $url = !is_array($sharedUrls) ? $sharedUrls : array_values($sharedUrls)[0];
           $this->markupGenerator->parseMarkup($url);
           $extraMarkup = '<a href="' . $url . '" class="status-comment-share"> ' . $this->markupGenerator->generatePreview() . '</a>';
         }
@@ -104,7 +97,7 @@ class HeartbeatCommentForm extends FormBase {
           $cid = $comment->id();
           $body = $commentBody;
           $response = new AjaxResponse();
-          $response->addCommand(new AppendCommand(
+          $response->addCommand(new PrependCommand(
               '#heartbeat-' . $config->get('entity_id') . ' .heartbeat-comments',
               '<div id="heartbeat-comment-' . $comment->id() . '"><span class="comment-owner"><span class="comment-username">' . \Drupal::currentUser()->getAccountName() . '</span>' . render($userview) . '<span class"comment-ago">1 sec ago</span></span><span class="comment-body">' . $commentBody . '</span><span class="sub-comment"><a href="/heartbeat/subcommentrequest/' . $cid . '" class="button button-action use-ajax">Reply</a></span></div>')
           );

+ 20 - 1
src/Form/HeartbeatForm.php

@@ -2,9 +2,15 @@
 
 namespace Drupal\heartbeat\Form;
 
+use Drupal\Component\Datetime\TimeInterface;
+use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Entity\ContentEntityForm;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManager;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\heartbeat\Entity;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Form controller for Heartbeat edit forms.
@@ -17,9 +23,22 @@ class HeartbeatForm extends ContentEntityForm {
   /**
    * {@inheritdoc}
    */
+
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity_type.manager')
+    );
+  }
+
+
+  public function __construct(EntityTypeManager $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
+//    parent::__construct($entity_type_bundle_info, $time);
+    $this->nodeManager = $entity_type_manager->getStorage('node');
+  }
+
   public function buildForm(array $form, FormStateInterface $form_state) {
 
-    $this->nodeManager = \Drupal::service('entity_type.manager')->getStorage('node');
+//    $this->nodeManager = \Drupal::service('entity_type.manager')->getStorage('node');
     /* @var $entity \Drupal\heartbeat\Entity\Heartbeat */
     $form = parent::buildForm($form, $form_state);
     $entity = &$this->entity;

+ 27 - 27
src/Plugin/Block/HeartbeatBlock.php

@@ -141,38 +141,37 @@ class HeartbeatBlock extends BlockBase implements ContainerFactoryPluginInterfac
         $uids[] = $uid->uid;
       }
     }
-      if ($feed !== null && $this->heartbeatStreamServices) {
-      $uids = count($uids) > 1 ? array_unique($uids) : $uids;
-        if (!empty($uids)) {
-          foreach ($this->heartbeatStreamServices->createStreamForUidsByType($uids, $feed) as $heartbeat) {
-            $this->renderMessage($messages, $heartbeat);
-          }
-        } else {
-          foreach ($this->heartbeatStreamServices->createStreamByType($feed) as $heartbeat) {
-            $this->renderMessage($messages, $heartbeat);
-          }
+    if ($feed !== null && $this->heartbeatStreamServices) {
+    $uids = count($uids) > 1 ? array_unique($uids) : $uids;
+      if (!empty($uids)) {
+        foreach ($this->heartbeatStreamServices->createStreamForUidsByType($uids, $feed) as $heartbeat) {
+          $this->renderMessage($messages, $heartbeat);
         }
       } else {
-//        foreach ($this->heartbeatStreamServices->createStreamForUids($uids) as $heartbeat) {
-        foreach ($this->heartbeatStreamServices->loadAllStreams() as $heartbeat) {
+        foreach ($this->heartbeatStreamServices->createStreamByType($feed) as $heartbeat) {
           $this->renderMessage($messages, $heartbeat);
         }
       }
+    } else {
+      foreach ($this->heartbeatStreamServices->loadAllStreams() as $heartbeat) {
+        $this->renderMessage($messages, $heartbeat);
+      }
+    }
 
-      return [
-        '#theme' => 'heartbeat_stream',
-        '#messages' => $messages,
-        '#attached' => array(
-          'library' => 'heartbeat/heartbeat',
-          'drupalSettings' => [
-            'activeFeed' => 'jigga',
-            'friendData' => $friendData,
-          ]
-        ),
-        '#cache' => array('max-age' => 0)
-      ];
+    return [
+      '#theme' => 'heartbeat_stream',
+      '#messages' => $messages,
+      '#attached' => array(
+        'library' => 'heartbeat/heartbeat',
+        'drupalSettings' => [
+          'activeFeed' => 'jigga',
+          'friendData' => $friendData,
+        ]
+      ),
+      '#cache' => array('max-age' => 0)
+    ];
 
-    }
+  }
 
     private function renderMessage(array &$messages, $heartbeat) {
       $timeago = null;
@@ -295,7 +294,7 @@ class HeartbeatBlock extends BlockBase implements ContainerFactoryPluginInterfac
       }
 
       $form = \Drupal::service('form_builder')->getForm('\Drupal\heartbeat\Form\HeartbeatCommentForm', $heartbeat);
-
+      $commentCount = count($comments);
       $messages[] = array('heartbeat' => $heartbeat->getMessage()->getValue()[0]['value'],
         'userPicture' => $rendered,
         'userId' => $user->id(),
@@ -304,7 +303,8 @@ class HeartbeatBlock extends BlockBase implements ContainerFactoryPluginInterfac
         'userName' => $user->getAccountName(),
         'user' => $userView,
         'commentForm' => $form,
-        'comments' => $comments,
+        'comments' => array_reverse($comments),
+        'commentCount' => $commentCount > 0 ? $commentCount : '',
         'likeFlag' => Heartbeat::flagAjaxMarkup('heartbeat_like', $heartbeat, $this->flagService),
         'unlikeFlag' => Heartbeat::flagAjaxMarkup('jihad_flag', $heartbeat, $this->flagService)
         );

+ 10 - 1
templates/heartbeat-stream.html.twig

@@ -42,7 +42,17 @@
         <div class="heartbeat-unlike">
           {{ message.unlikeFlag }}
         </div>
+        <div class="heartbeat-comment-button">
+          {% if message.commentCount > 1 %}
+            {{ message.commentCount }} comments
+          {% elseif message.commentCount == 1 %}
+            {{ message.commentCount }} comment
+          {% else %}
+            Comment
+          {% endif %}
+        </div>
         <div class="heartbeat-comment" id="comment-{{ message.id }}">
+          {{ message.commentForm }}
           <div class="heartbeat-comments">
             {% for comment in message.comments %}
               <div id="heartbeat-comment-{{ comment.id }}">
@@ -66,7 +76,6 @@
               </div>
             {% endfor %}
           </div>
-          {{ message.commentForm }}
         </div>
       </div>
     </div>