瀏覽代碼

Chutier link from audio player cartel is working git add .

Bachir Soussi Chiadmi 6 年之前
父節點
當前提交
c0d185bb6d
共有 23 個文件被更改,包括 645 次插入196 次删除
  1. 59 1
      sites/all/modules/figli/edlp_studio/assets/js/edlp_studio.js
  2. 4 1
      sites/all/modules/figli/edlp_studio/edlp_studio.libraries.yml
  3. 45 12
      sites/all/modules/figli/edlp_studio/edlp_studio.module
  4. 5 4
      sites/all/modules/figli/edlp_studio/edlp_studio.routing.yml
  5. 9 0
      sites/all/modules/figli/edlp_studio/src/ChutierListBuilder.php
  6. 148 13
      sites/all/modules/figli/edlp_studio/src/Controller/ChutierController.php
  7. 52 0
      sites/all/modules/figli/edlp_studio/src/Entity/Chutier.php
  8. 29 0
      sites/all/modules/figli/edlp_studio/src/Entity/ChutierInterface.php
  9. 0 0
      sites/all/themes/custom/edlptheme/assets/dist/img/favori-off.svg
  10. 0 0
      sites/all/themes/custom/edlptheme/assets/dist/img/favori-on.svg
  11. 1 0
      sites/all/themes/custom/edlptheme/assets/dist/scripts/main.min.js
  12. 55 29
      sites/all/themes/custom/edlptheme/assets/dist/styles/app.min.css
  13. 32 0
      sites/all/themes/custom/edlptheme/assets/img/favori-off.svg
  14. 57 0
      sites/all/themes/custom/edlptheme/assets/img/favori-on.svg
  15. 1 0
      sites/all/themes/custom/edlptheme/assets/scripts/main.js
  16. 74 34
      sites/all/themes/custom/edlptheme/assets/styles/app.scss
  17. 0 78
      sites/all/themes/custom/edlptheme/templates/content/__node--enregistrement--index.html.twig
  18. 31 24
      sites/all/themes/custom/edlptheme/templates/content/node--enregistrement--player-cartel.html.twig
  19. 5 0
      sites/default/config/sync/core.entity_view_display.node.enregistrement.player_cartel.yml
  20. 14 0
      sites/default/config/sync/system.action.user_add_role_action.user.yml
  21. 14 0
      sites/default/config/sync/system.action.user_remove_role_action.user.yml
  22. 1 0
      sites/default/config/sync/user.role.authenticated.yml
  23. 9 0
      sites/default/config/sync/user.role.user.yml

+ 59 - 1
sites/all/modules/figli/edlp_studio/assets/js/edlp_studio.js

@@ -1,5 +1,63 @@
 (function ($, Drupal) {
-  
 
+  function init(){
+    console.log('Studio Init');
+    initEvents();
+    initAjax();
+  };
 
+  function initEvents(){
+    $('body').on('new-audio-cartel-loaded', initAjax);
+  };
+
+  function initAjax(){
+    console.log('studio initAjax chutier');
+    $('.chutier-ajax-link:not(.ajax-enabled)')
+      .addClass('ajax-enabled')
+      .on('click', onClickAjaxLink);
+  };
+
+  function onClickAjaxLink(e){
+    console.log('studio onClickAjaxLink chutier');
+    e.preventDefault();
+    // var $this = $(this);
+    addRemoveToChutier($(this));
+    // switch($this.attr('action')){
+    //   case 'add':
+    //     // TODO: get target chutier
+    //     addToChutier($this);
+    //     break;
+    //   case 'remove':
+    //     // TODO: if we use more than one chutoer per user get target chutier
+    //     removeFromChutier($this);
+    //     break;
+    // }
+    return false;
+  };
+
+  function addRemoveToChutier($link){
+    // var ajax_path = 'edlp_studio/ajax/chutier/add/'+id; // + '/' +cid;
+    var ajax_path = $link.attr('data-drupal-link-system-path');
+    var path = window.location.origin + drupalSettings.path.baseUrl + ajax_path;
+    $link.addClass('ajax-loading');
+    $.getJSON(path, {})
+      .done(function(data){
+        onActionToChutierDone($link, data);
+      })
+      .fail(function(jqxhr, textStatus, error){
+        onErrorActionToChutier(jqxhr, textStatus, error, $link);
+      });
+  };
+
+  function onActionToChutierDone($link, data){
+    console.log('onActionToChutierDone',data);
+    $link.replaceWith(data.new_link);
+    initAjax();
+  };
+
+  function onErrorActionToChutier(jqxhr, textStatus, error, $link){
+    console.warn('add to chuttier load failed : '+error, jqxhr.responseText);
+  };
+
+  init();
 })(jQuery, Drupal);

+ 4 - 1
sites/all/modules/figli/edlp_studio/edlp_studio.libraries.yml

@@ -1,3 +1,6 @@
 edlp_studio-library:
   js:
-    js/edlp_studio.js: {}
+    assets/js/edlp_studio.js: { scope: footer }
+  dependencies:
+    - core/drupalSettings
+    - core/jquery

+ 45 - 12
sites/all/modules/figli/edlp_studio/edlp_studio.module

@@ -6,7 +6,8 @@
  */
 
 use Drupal\Core\Routing\RouteMatchInterface;
-
+use Drupal\Core\Url;
+use Drupal\edlp_studio\Entity\Chutier;
 /**
  * Implements hook_help().
  */
@@ -23,6 +24,15 @@ function edlp_studio_help($route_name, RouteMatchInterface $route_match) {
   }
 }
 
+/**
+ * Implements hook_page_attachments().
+ * @param array $attachments
+ */
+function edlp_studio_page_attachments(array &$attachments) {
+  $attachments['#attached']['library'][] = 'edlp_studio/edlp_studio-library';
+}
+
+
 /**
 * hook_entity_extra_field_info()
 *
@@ -30,8 +40,8 @@ function edlp_studio_help($route_name, RouteMatchInterface $route_match) {
 function edlp_studio_entity_extra_field_info(){
   $extra = [];
   // TODO: get node content type by settings @see readme
-  $extra['node']['enregistrement']['display']['add_to_chutier'] = [
-    'label' => t('Add to chutier link'),
+  $extra['node']['enregistrement']['display']['chutier_actions'] = [
+    'label' => t('Chutier actions'),
     'description' => 'Display a link to add the content to chutier',
     'weight' => 99,
     'visible' => FALSE,
@@ -45,18 +55,41 @@ function edlp_studio_entity_extra_field_info(){
  * @see https://www.amazeelabs.com/en/render-menu-tree-custom-code-drupal-8
  */
 function edlp_studio_node_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
-  $display_settings = $display->getComponent('add_to_chutier');
+  $display_settings = $display->getComponent('chutier_actions');
   if (!empty($display_settings)) {
     // dpm($entity);
     // dpm($entity->id());
-    $url = Url::fromRoute('edlp_studio.chutier_controller_add_content', ['id'=>$entity->id()], array(
-      'attributes' => array(
-        'class' => ['add-to-chutier-link', 'ajax-link'],
-        'target_id' => $entity->id(),
-      )
-    ));
-    $build['add_to_chutier'] = array(
-      '#title' => t("Add this content to chutier."),
+    $user = \Drupal::currentUser();
+    // dpm($user);
+    if($user->id() == 0){
+    //   // TODO: check if user loged in ? yes -> links : no : popup message
+    //   $action = 'add';
+    }
+    // else{
+    //   // TODO: check if node already in chutier ? no -> add link : yes -> remove link
+    //   // use getUserChutiersContents() from \Drupal\edlp_studio\ChutierInterface
+    //   $contents = Chutier::getUserChutiersContents($user->id());
+    //   dpm($contents);
+    //   if(array_search($entity->id(), $contents) === false){
+    //     $action = 'add';
+    //   }else{
+    //     $action = 'remove';
+    //   }
+    // }
+    // $args = array(
+    //   'action'=>$action,
+    //   'id'=>$entity->id()
+    // );
+    // $url = Url::fromRoute('edlp_studio.chutier_controller_ajax_add_content', $args, array(
+    //   'attributes' => array(
+    //     'class' => ['chutier-link','chutier-ajax-link'],
+    //     'action' => $action,
+    //     'target_id' => $entity->id(),
+    //   )
+    // ));
+    $url = Chutier::getActionsUrl($entity->id(), $user->id());
+    $build['chutier_actions'] = array(
+      '#title' => t("Chutier."),
       '#type' => 'link',
       '#url' => $url,
       '#options'=>array(

+ 5 - 4
sites/all/modules/figli/edlp_studio/edlp_studio.routing.yml

@@ -6,10 +6,11 @@ edlp_studio.studio:
   requirements:
     _permission: 'administer studio'
 
-edlp_studio.chutier_controller_add_content:
-  path: '/studio/chutier/add/{id}'
+edlp_studio.chutier_controller_ajax_add_content:
+  path: '/edlp_studio/ajax/chutier/{action}/{id}/{cid}'
   defaults:
-    _controller: '\Drupal\edlp_studio\Controller\ChutierController::addContent'
-    _title: 'Add content to chutier'
+    _controller: '\Drupal\edlp_studio\Controller\ChutierController::AddRemoveContent'
+    _title: 'Add/remove content to/from chutier'
+    cid: null
   requirements:
     _permission: 'use chutier'

+ 9 - 0
sites/all/modules/figli/edlp_studio/src/ChutierListBuilder.php

@@ -20,6 +20,8 @@ class ChutierListBuilder extends EntityListBuilder {
   public function buildHeader() {
     $header['id'] = $this->t('Chutier ID');
     $header['name'] = $this->t('Name');
+    $header['user'] = $this->t('User');
+    // $header['default'] = $this->t('User id');
     return $header + parent::buildHeader();
   }
 
@@ -34,6 +36,13 @@ class ChutierListBuilder extends EntityListBuilder {
       'entity.chutier.edit_form',
       ['chutier' => $entity->id()]
     );
+    $row['user'] = Link::createFromRoute(
+      $entity->getOwner()->getUserName(),
+      'entity.user.canonical',
+      ['user' => $entity->getOwnerId()]
+    );
+
+    // $row['uid'] = $entity->getOwnerId();
     return $row + parent::buildRow($entity);
   }
 

+ 148 - 13
sites/all/modules/figli/edlp_studio/src/Controller/ChutierController.php

@@ -3,38 +3,173 @@
 namespace Drupal\edlp_studio\Controller;
 
 use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\User\UserDataInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\JsonResponse;
 
+use Drupal\edlp_studio\Entity\Chutier;
 
 /**
  * Class ChutierController.
  */
 class ChutierController extends ControllerBase {
 
+  protected $user;
+  protected $userdata;
+
+  /**
+   * Class constructor.
+   */
+  public function __construct(AccountInterface $account, UserDataInterface $userdata) {
+    $this->user = $account;
+    $this->userdata = $userdata;
+  }
+
   /**
-   * Hello.
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    // Instantiates this form class.
+    return new static(
+      // Load the service required to construct this class.
+      $container->get('current_user'),
+      $container->get('user.data')
+    );
+  }
+
+
+  /**
+   * AdddContent.
    *
    * @return json
-   *   Return Hello string.
+   *   Return status.
    */
-  public function AddContent($id) {
-    // TODO: get current user
-    // TODO: check if default chutier exists ? yes use it : no create and use it.
-    // TODO: add $id to documents field
-    // TODO: return status
+  public function AddRemoveContent($action, $id, $cid) {
+    $this->error_message = null;
+    $status = 'ok';
+    // get current user :
+    // done by DependencyInjection of AccountInterface
 
-    $response = new JsonResponse();
+    // TODO: use the send chutier instead of default
+    // check if default chutier exists ? yes use it : no create and use it.
+    $this->checkChutier();
+    // dpm($this->chutier);
 
-    $data = array(
-      'test' => 'Hello chutier',
+    // check if $id exists, is a document, and does not already exist in chutier
+    switch($action){
+      case 'add':
+        $this->validateNewDoc($id);
+        if(!$this->error_message){
+          // add $id to documents field
+          $this->addNewDoc($id);
+          $message = t('Node @id added to chutier.', array('@id'=>$id));
+        }else{
+          $status = "error";
+        }
+        break;
+      case 'remove':
+        $this->removeDoc($id);
+        $message = t('Node @id removed to chutier.', array('@id'=>$id));
+        break;
+    }
+
+    $url = Chutier::getActionsUrl($id, $this->user->id());
+    $new_link_build = array(
+      '#title' => t("Chutier."),
+      '#type' => 'link',
+      '#url' => $url,
+      '#options'=>array(
+        'attributes' => array(
+          'data-drupal-link-system-path' => $url->getInternalPath()
+        )
+      )
     );
+    $new_link = render($new_link_build);
 
-    $response->setData($data);
+    if($status == 'error'){
+      $message = $this->error_message;
+    }
 
+    // JSON
+    $response = new JsonResponse();
+    $data = array(
+      'status' => $status,
+      'message' => $message,
+      'new_link' => $new_link,
+    );
+    $response->setData($data);
     return $response;
+
+    // classic html
     // return array(
-    //   '#markup'=>'Hello Chutier'
-    // );  }
+    //   '#markup'=>'Status : ' . $status . ' | Message : ' . $message,
+    // );
+  }
+
+  private function addNewDoc($id){
+    $this->chutier->documents->appendItem($id);
+    $this->chutier->save();
+  }
+
+  private function removeDoc($id){
+    $values = array_column($this->chutier->documents->getValue(), 'target_id');
+    $index = array_search($id,$values);
+    $this->chutier->documents->removeItem($index);
+    $this->chutier->save();
+  }
+
+  private function validateNewDoc($id){
+    $node = entity_load('node', $id);
+    if($node){
+      // TODO: get node bundle by settings (@see readme)
+      if($node->getType() == 'enregistrement'){
+        $docs = array_column($this->chutier->documents->getValue(), 'target_id');
+        if( in_array($id, $docs) ){
+          $this->error_message = t("Node '@title'(@id) already exists in chutier '@name'(@cid)", array(
+            '@title'=>$node->getTitle(),
+            '@id'=>$id,
+            '@name' => $this->chutier->getName(),
+            '@cid' => $this->chutier->id())
+          );
+        }
+      }else{
+        $this->error_message = t("Node @title (@id) is not an Enregistrement (@type)", array(
+          '@title'=>$node->getTitle(),
+          '@id'=>$id,
+          '@type' => $node->getType())
+        );
+      }
+    }else{
+      $this->error_message = t("Node @id does not exists", array('@id'=>$id));
+    }
+  }
+
+  private function checkChutier(){
+    $default_chutier_id = $this->userdata->get('edlp_studio', $this->user->id(), 'default_chutier');
+    // dpm($this->default_chutier_id);
+    $this->chutier = entity_load('chutier', $default_chutier_id);
+    // if default chutier does not exists, create, save and record it
+    if(!$this->chutier){
+      $this->createDefaultChutier();
+    }
+  }
+
+  private function createDefaultChutier(){
+    // dpm('createDefaultChutier');
+    $this->createChutier();
+    $this->userdata->set('edlp_studio', $this->user->id(), 'default_chutier', $this->chutier->id());
+  }
+
+  public function createChutier(){
+    $chutier = array(
+      'id' => NULL,
+      'uid' => $this->user->id(),
+      'status' => TRUE,
+      'name' => t('Default'),
+    );
+    $this->chutier = entity_create('chutier', $chutier);
+    $this->chutier->save();
   }
 
 }

+ 52 - 0
sites/all/modules/figli/edlp_studio/src/Entity/Chutier.php

@@ -8,6 +8,7 @@ use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityChangedTrait;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\user\UserInterface;
+use Drupal\Core\Url;
 
 /**
  * Defines the Chutier entity.
@@ -240,4 +241,55 @@ class Chutier extends ContentEntityBase implements ChutierInterface {
     return $fields;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function getUserChutiersContents($uid){
+    // TODO: use query if we use more than one chutier
+    // $query = \Drupal::entityQuery('chutier')
+    //   ->condition('user_id', $uid);
+    //
+    // $chutiers_nids = $query->execute();
+    // $chutiers = entity_load_multiple('chutier', $chutiers_nids);
+    //
+    // $contents = array();
+    // foreach ($chutiers as $id => $chutier) {
+    //   $contents[$id] = array_column($chutier->documents->getValue(), 'target_id');
+    // }
+
+    /** @var UserDataInterface $userData */
+    $userData = \Drupal::service('user.data');
+    $default_chutier_id = $userData->get('edlp_studio', $uid, 'default_chutier');
+    if($chutier = entity_load('chutier', $default_chutier_id)){
+      return array_column($chutier->documents->getValue(), 'target_id');
+    }else{
+      return array();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getActionsUrl($id, $uid){
+    $contents = self::getUserChutiersContents($uid);
+    // dpm($contents);
+    if(array_search($id, $contents) === false){
+      $action = 'add';
+    }else{
+      $action = 'remove';
+    }
+    $args = array(
+      'action'=>$action,
+      'id'=>$id
+    );
+    $url = Url::fromRoute('edlp_studio.chutier_controller_ajax_add_content', $args, array(
+      'attributes' => array(
+        'class' => ['chutier-link','chutier-ajax-link'],
+        'action' => $action,
+        'target_id' => $id,
+      )
+    ));
+    return $url;
+  }
+
 }

+ 29 - 0
sites/all/modules/figli/edlp_studio/src/Entity/ChutierInterface.php

@@ -74,4 +74,33 @@ interface ChutierInterface extends ContentEntityInterface, EntityChangedInterfac
    */
   public function setPublished($published);
 
+  /**
+   * get the contents in user's chutiers
+   *
+   * @param int $uid
+   *   user id
+   *
+   * @return array
+   *   associative array of contents by chutiers
+   *
+   */
+  public static function getUserChutiersContents($uid);
+
+
+  /**
+   * get the contents in user's chutiers
+   *
+   * @param int $id
+   *   content id
+   *
+   * @param int $uid
+   *   user id
+   *
+   * @return Drupal\Core\Url
+   *   depending on action is add or remove
+   *
+   */
+  public static function getActionsURL($id, $uid);
+
+
 }

File diff suppressed because it is too large
+ 0 - 0
sites/all/themes/custom/edlptheme/assets/dist/img/favori-off.svg


File diff suppressed because it is too large
+ 0 - 0
sites/all/themes/custom/edlptheme/assets/dist/img/favori-on.svg


+ 1 - 0
sites/all/themes/custom/edlptheme/assets/dist/scripts/main.min.js

@@ -131,6 +131,7 @@ edlp_vars = {
         console.log('AudioPlayer node loaded', data);
         this.$cartel.html(data.rendered);
         this.$cartel.removeClass('loading');
+        _$body.trigger({'type':'new-audio-cartel-loaded'});
         initAjaxLinks();
       },
       onNodeLoadFail(jqxhr, textStatus, error){

+ 55 - 29
sites/all/themes/custom/edlptheme/assets/dist/styles/app.min.css

@@ -1365,67 +1365,75 @@ body.ajax-loading main[role="main"]:before {
     height: 100%; }
   #audio-player .cartel {
     position: relative;
-    max-width: 400px;
+    max-width: 350px;
     margin-left: 1em;
     background-color: white;
     opacity: 1;
     -webkit-transition: opacity 0.5s ease-in-out;
-    transition: opacity 0.5s ease-in-out; }
+    transition: opacity 0.5s ease-in-out;
+    white-space: nowrap; }
     #audio-player .cartel.loading {
       opacity: 0; }
-    #audio-player .cartel .first-cartel .entrees {
+    #audio-player .cartel .actions, #audio-player .cartel .cartels {
+      display: inline-block;
+      vertical-align: top;
+      white-space: normal;
+      position: relative; }
+    #audio-player .cartel .actions {
+      width: 1.5em; }
+    #audio-player .cartel .cartels .first-cartel .entrees {
       line-height: 0; }
-      #audio-player .cartel .first-cartel .entrees span {
+      #audio-player .cartel .cartels .first-cartel .entrees span {
         display: inline-block;
         width: 8px;
         height: 8px;
         background-color: black;
         margin-right: 3px; }
-        #audio-player .cartel .first-cartel .entrees span[tid='134'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='134'] {
           background-color: #2b8f2f; }
-        #audio-player .cartel .first-cartel .entrees span[tid='121'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='121'] {
           background-color: #3a33b6; }
-        #audio-player .cartel .first-cartel .entrees span[tid='125'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='125'] {
           background-color: #2c9f57; }
-        #audio-player .cartel .first-cartel .entrees span[tid='119'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='119'] {
           background-color: #c48978; }
-        #audio-player .cartel .first-cartel .entrees span[tid='132'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='132'] {
           background-color: #5270bb; }
-        #audio-player .cartel .first-cartel .entrees span[tid='122'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='122'] {
           background-color: #fb54d3; }
-        #audio-player .cartel .first-cartel .entrees span[tid='129'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='129'] {
           background-color: #e07483; }
-        #audio-player .cartel .first-cartel .entrees span[tid='120'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='120'] {
           background-color: #655845; }
-        #audio-player .cartel .first-cartel .entrees span[tid='130'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='130'] {
           background-color: #7e0868; }
-        #audio-player .cartel .first-cartel .entrees span[tid='118'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='118'] {
           background-color: #0e7121; }
-        #audio-player .cartel .first-cartel .entrees span[tid='127'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='127'] {
           background-color: #dabd42; }
-        #audio-player .cartel .first-cartel .entrees span[tid='133'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='133'] {
           background-color: #0399bb; }
-        #audio-player .cartel .first-cartel .entrees span[tid='128'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='128'] {
           background-color: #399a1c; }
-        #audio-player .cartel .first-cartel .entrees span[tid='124'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='124'] {
           background-color: #708540; }
-        #audio-player .cartel .first-cartel .entrees span[tid='116'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='116'] {
           background-color: #191bff; }
-        #audio-player .cartel .first-cartel .entrees span[tid='117'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='117'] {
           background-color: #279d84; }
-        #audio-player .cartel .first-cartel .entrees span[tid='131'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='131'] {
           background-color: #5219ab; }
-        #audio-player .cartel .first-cartel .entrees span[tid='126'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='126'] {
           background-color: #d49cb6; }
-        #audio-player .cartel .first-cartel .entrees span[tid='123'] {
+        #audio-player .cartel .cartels .first-cartel .entrees span[tid='123'] {
           background-color: #497715; }
-    #audio-player .cartel .first-cartel h2.node-title {
+    #audio-player .cartel .cartels .first-cartel h2.node-title {
       margin: 0.2em 0 0;
       font-size: 1em; }
-    #audio-player .cartel .first-cartel p {
+    #audio-player .cartel .cartels .first-cartel p {
       margin: 0;
       font-size: 0.75em; }
-    #audio-player .cartel .second-cartel {
+    #audio-player .cartel .cartels .second-cartel {
       position: absolute;
       top: 0;
       left: 0;
@@ -1435,20 +1443,37 @@ body.ajax-loading main[role="main"]:before {
       opacity: 0;
       -webkit-transition: opacity 0.2s ease-in-out;
       transition: opacity 0.2s ease-in-out; }
-      #audio-player .cartel .second-cartel > * {
+      #audio-player .cartel .cartels .second-cartel > * {
         display: inline-block;
         vertical-align: top; }
-      #audio-player .cartel .second-cartel .col-left a {
+      #audio-player .cartel .cartels .second-cartel .col-left a {
         display: block;
         font-size: 0.90em;
         font-weight: 600; }
-      #audio-player .cartel .second-cartel .col-right {
+      #audio-player .cartel .cartels .second-cartel .col-right {
         font-size: 0.75em; }
     #audio-player .cartel:hover .second-cartel {
       opacity: 1; }
   #audio-player.is-playing .btns .play-pause {
     background-image: url(../img/audio-player-pause.svg); }
 
+a.chutier-link {
+  display: block;
+  width: 1em;
+  height: 1em;
+  overflow: hidden;
+  text-indent: 50em;
+  background-position: center;
+  background-repeat: no-repeat;
+  background-size: contain;
+  background-image: url(../img/favori-off.svg);
+  -webkit-transition: opacity 0.2s ease-in-out;
+  transition: opacity 0.2s ease-in-out; }
+  a.chutier-link[action="remove"] {
+    background-image: url(../img/favori-on.svg); }
+  a.chutier-link.ajax-loading {
+    opacity: 0.2; }
+
 body.path-agenda main .col > .wrapper {
   height: 100%; }
 
@@ -1767,6 +1792,7 @@ footer {
           width: 350px;
           opacity: 1; }
   footer #block-userlogin {
+    pointer-events: all;
     position: relative;
     width: 20px;
     height: 20px; }

File diff suppressed because it is too large
+ 32 - 0
sites/all/themes/custom/edlptheme/assets/img/favori-off.svg


File diff suppressed because it is too large
+ 57 - 0
sites/all/themes/custom/edlptheme/assets/img/favori-on.svg


+ 1 - 0
sites/all/themes/custom/edlptheme/assets/scripts/main.js

@@ -108,6 +108,7 @@
         console.log('AudioPlayer node loaded', data);
         this.$cartel.html(data.rendered);
         this.$cartel.removeClass('loading');
+        _$body.trigger({'type':'new-audio-cartel-loaded'});
         initAjaxLinks();
       },
       onNodeLoadFail(jqxhr, textStatus, error){

+ 74 - 34
sites/all/themes/custom/edlptheme/assets/styles/app.scss

@@ -248,6 +248,7 @@ main[role="main"]{
   &>*{
     display: inline-block;
     vertical-align: middle;
+    // word-break:keep-all;
     padding:0;
     max-height: 100%;
     // outline: 1px solid green;
@@ -312,49 +313,61 @@ main[role="main"]{
   .cartel{
     // TODO: set max-width regarding responsive
     position: relative;
-    max-width: 400px;
+    max-width: 350px;
     margin-left: 1em;
     background-color: white;
     opacity: 1;
     transition: opacity 0.5s ease-in-out;
     &.loading{opacity: 0;}
-    .first-cartel{
+    white-space: nowrap;
+    .actions, .cartels{
+      display: inline-block;
+      vertical-align: top;
+      white-space: normal;
+      position: relative;
+    }
+    .actions{
+      width:1.5em;
+    }
+    .cartels{
+      .first-cartel{
 
-      .entrees{
-        line-height: 0;
-        span{
-          @include entrie-micro-square;
+        .entrees{
+          line-height: 0;
+          span{
+            @include entrie-micro-square;
+          }
         }
-      }
-      h2.node-title{
-        margin:0.2em 0 0;
-        font-size: 1em;
-      }
-      p{
-        margin:0;
-        font-size: 0.75em;
-      }
-    }
-    .second-cartel{
-      position: absolute;
-      top: 0; left:0;
-      background-color: white;
-      height:100%; min-width: 100%;
-      opacity: 0;
-      transition: opacity 0.2s ease-in-out;
-      &>*{
-        display: inline-block;
-        vertical-align: top;
-      }
-      .col-left{
-        a{
-          display: block;
-          font-size: 0.90em;
-          font-weight: 600;
+        h2.node-title{
+          margin:0.2em 0 0;
+          font-size: 1em;
+        }
+        p{
+          margin:0;
+          font-size: 0.75em;
         }
       }
-      .col-right{
-        font-size: 0.75em;
+      .second-cartel{
+        position: absolute;
+        top: 0; left:0;
+        background-color: white;
+        height:100%; min-width: 100%;
+        opacity: 0;
+        transition: opacity 0.2s ease-in-out;
+        &>*{
+          display: inline-block;
+          vertical-align: top;
+        }
+        .col-left{
+          a{
+            display: block;
+            font-size: 0.90em;
+            font-weight: 600;
+          }
+        }
+        .col-right{
+          font-size: 0.75em;
+        }
       }
     }
     &:hover{
@@ -368,6 +381,32 @@ main[role="main"]{
   }
 }
 
+
+ //  ___ _           _ _
+ // / __| |_ _  _ __| (_)___
+ // \__ \  _| || / _` | / _ \
+ // |___/\__|\_,_\__,_|_\___/
+
+a.chutier-link{
+  display: block;
+  width:1em;height:1em;
+  overflow: hidden;
+  text-indent: 50em;
+  // background-color: red;
+  background-position: center;
+  background-repeat: no-repeat;
+  background-size: contain;
+  background-image: url(../img/favori-off.svg);
+  &[action="remove"]{
+    background-image: url(../img/favori-on.svg);
+  }
+  transition: opacity 0.2s ease-in-out;
+  &.ajax-loading{
+    opacity: 0.2;
+  }
+}
+
+
  //    _    _            _  _         _
  //   /_\  (_)__ ___ __ | \| |___  __| |___
  //  / _ \ | / _` \ \ / | .` / _ \/ _` / -_)
@@ -772,6 +811,7 @@ footer{
   }
 
   #block-userlogin{
+    pointer-events: all;
     // outline: 1px solid blue;
     $wh:20px;
     position: relative;

+ 0 - 78
sites/all/themes/custom/edlptheme/templates/content/__node--enregistrement--index.html.twig

@@ -1,78 +0,0 @@
-{#
-/**
- * @file
- * Theme override to display a node.
- *
- * Available variables:
- * - node: The node entity with limited access to object properties and methods.
- *   Only method names starting with "get", "has", or "is" and a few common
- *   methods such as "id", "label", and "bundle" are available. For example:
- *   - node.getCreatedTime() will return the node creation timestamp.
- *   - node.hasField('field_example') returns TRUE if the node bundle includes
- *     field_example. (This does not indicate the presence of a value in this
- *     field.)
- *   - node.isPublished() will return whether the node is published or not.
- *   Calling other methods, such as node.delete(), will result in an exception.
- *   See \Drupal\node\Entity\Node for a full list of public properties and
- *   methods for the node object.
- * - label: The title of the node.
- * - content: All node items. Use {{ content }} to print them all,
- *   or print a subset such as {{ content.field_example }}. Use
- *   {{ content|without('field_example') }} to temporarily suppress the printing
- *   of a given child element.
- * - author_picture: The node author user entity, rendered using the "compact"
- *   view mode.
- * - metadata: Metadata for this node.
- * - date: Themed creation date field.
- * - author_name: Themed author name field.
- * - url: Direct URL of the current node.
- * - display_submitted: Whether submission information should be displayed.
- * - attributes: HTML attributes for the containing element.
- *   The attributes.class element may contain one or more of the following
- *   classes:
- *   - node: The current template type (also known as a "theming hook").
- *   - node--type-[type]: The current node type. For example, if the node is an
- *     "Article" it would result in "node--type-article". Note that the machine
- *     name will often be in a short form of the human readable label.
- *   - node--view-mode-[view_mode]: The View Mode of the node; for example, a
- *     teaser would result in: "node--view-mode-teaser", and
- *     full: "node--view-mode-full".
- *   The following are controlled through the node publishing options.
- *   - node--promoted: Appears on nodes promoted to the front page.
- *   - node--sticky: Appears on nodes ordered above other non-sticky nodes in
- *     teaser listings.
- *   - node--unpublished: Appears on unpublished nodes visible only to site
- *     admins.
- * - title_attributes: Same as attributes, except applied to the main title
- *   tag that appears in the template.
- * - content_attributes: Same as attributes, except applied to the main
- *   content tag that appears in the template.
- * - author_attributes: Same as attributes, except applied to the author of
- *   the node tag that appears in the template.
- * - title_prefix: Additional output populated by modules, intended to be
- *   displayed in front of the main title tag that appears in the template.
- * - title_suffix: Additional output populated by modules, intended to be
- *   displayed after the main title tag that appears in the template.
- * - view_mode: View mode; for example, "teaser" or "full".
- * - teaser: Flag for the teaser state. Will be true if view_mode is 'teaser'.
- * - page: Flag for the full page state. Will be true if view_mode is 'full'.
- * - readmore: Flag for more state. Will be true if the teaser content of the
- *   node cannot hold the main body content.
- * - logged_in: Flag for authenticated user status. Will be true when the
- *   current user is a logged-in member.
- * - is_admin: Flag for admin user status. Will be true when the current user
- *   is an administrator.
- *
- * @see template_preprocess_node()
- *
- * @todo Remove the id attribute (or make it a class), because if that gets
- *   rendered twice on a page this is invalid CSS for example: two lists
- *   in different view modes.
- */
-#}
-<h2{{ title_attributes.addClass('node-title') }}>
-  <a href="{{ url }}" rel="bookmark" {{ link_attributes }}>{{ label }}</a>
-</h2>
-<div{{ content_attributes.addClass('node__content') }}>
-  {{ content }}
-</div>

+ 31 - 24
sites/all/themes/custom/edlptheme/templates/content/node--enregistrement--player-cartel.html.twig

@@ -82,32 +82,39 @@
 %}
 {{ attach_library('classy/node') }}
 <article{{ attributes.addClass(classes) }}>
-  <section class="first-cartel">
-    <div class="entrees">
-      {# THIS IS REALLY DIRTY !! #}
-      {% for key, child in content.field_entrees if key|first != '#' %}
-        {% set tid = child['#cache']['tags'][0]|replace({'taxonomy_term:':''}) %}
-        <span class="entree" tid="{{ tid }}" title="{{ child }}"></span>
-      {% endfor %}
-    </div>
-    <h2{{ title_attributes.addClass('node-title') }}>
-      {{ label }}
-    </h2>
-    <div class="description">
-      {{ content.field_description }}
-    </div>
+  <section class="actions">
+    {{ content.chutier_actions }}
   </section>
-  <section class="second-cartel">
-    {% if col_left %}
-      <div class="col-left">
-        {{ link_transcript }}
-        {{ link_article }}
+  <section class="cartels">
+
+    <section class="first-cartel">
+      <div class="entrees">
+        {# THIS IS REALLY DIRTY !! #}
+        {% for key, child in content.field_entrees if key|first != '#' %}
+          {% set tid = child['#cache']['tags'][0]|replace({'taxonomy_term:':''}) %}
+          <span class="entree" tid="{{ tid }}" title="{{ child }}"></span>
+        {% endfor %}
       </div>
-    {% endif %}
-    {% if col_right %}
-      <div class="col-right">
-        right colume
+      <h2{{ title_attributes.addClass('node-title') }}>
+        {{ label }}
+      </h2>
+      <div class="description">
+        {{ content.field_description }}
       </div>
-    {% endif %}
+    </section>
+    <section class="second-cartel">
+      {% if col_left %}
+        <div class="col-left">
+          {{ link_transcript }}
+          {{ link_article }}
+        </div>
+      {% endif %}
+      {% if col_right %}
+        <div class="col-right">
+          right colume
+        </div>
+      {% endif %}
+    </section>
+
   </section>
 </article>

+ 5 - 0
sites/default/config/sync/core.entity_view_display.node.enregistrement.player_cartel.yml

@@ -29,6 +29,11 @@ content:
     region: content
     settings: {  }
     third_party_settings: {  }
+  chutier_actions:
+    weight: 1
+    region: content
+    settings: {  }
+    third_party_settings: {  }
   content_moderation_control:
     weight: -20
     region: content

+ 14 - 0
sites/default/config/sync/system.action.user_add_role_action.user.yml

@@ -0,0 +1,14 @@
+uuid: edce0062-97e8-4dba-848f-0d1ada71a23e
+langcode: fr
+status: true
+dependencies:
+  config:
+    - user.role.user
+  module:
+    - user
+id: user_add_role_action.user
+label: 'Add the User role to the selected user(s)'
+type: user
+plugin: user_add_role_action
+configuration:
+  rid: user

+ 14 - 0
sites/default/config/sync/system.action.user_remove_role_action.user.yml

@@ -0,0 +1,14 @@
+uuid: c4a61f84-8f75-4d58-a319-0deb762aba56
+langcode: fr
+status: true
+dependencies:
+  config:
+    - user.role.user
+  module:
+    - user
+id: user_remove_role_action.user
+label: 'Remove the User role from the selected user(s)'
+type: user
+plugin: user_remove_role_action
+configuration:
+  rid: user

+ 1 - 0
sites/default/config/sync/user.role.authenticated.yml

@@ -20,6 +20,7 @@ permissions:
   - 'delete own fil entities'
   - 'edit own chutier entities'
   - 'edit own fil entities'
+  - 'use chutier'
   - 'use text format wysiwyg'
   - 'view own unpublished chutier entities'
   - 'view own unpublished fil entities'

+ 9 - 0
sites/default/config/sync/user.role.user.yml

@@ -0,0 +1,9 @@
+uuid: 05cb1550-ab78-4bf9-a7d0-39a33e3fa03b
+langcode: fr
+status: true
+dependencies: {  }
+id: user
+label: User
+weight: -4
+is_admin: null
+permissions: {  }

Some files were not shown because too many files changed in this diff