Browse Source

Evolution #125: Actualisation des éléments ajax

bastien 12 years ago
parent
commit
9bed3ec5aa

+ 6 - 0
app/Resources/translations/userui.fr.yml View File

@@ -41,6 +41,12 @@ tags:
41 41
     inputs:
42 42
       cancel:       Annuler
43 43
       submit:       Faire la demande
44
+  new:
45
+    has_news:       %count% éléments viennent d'être ajoutés, %link%
46
+    has_news_one:   %count% élément vient d'être ajouté, %link%
47
+    has_news_link:  cliquez ici pour les afficher
48
+    has_news_link_one:  cliquez ici pour l'afficher
49
+    has_news_link_more_x:  cliquez ici pour en afficher %x%
44 50
            
45 51
 filter:
46 52
   network: "Résultats de "

+ 164 - 0
src/Muzich/CoreBundle/Controller/ElementController.php View File

@@ -211,4 +211,168 @@ class ElementController extends Controller
211 211
     }
212 212
   }
213 213
   
214
+  protected function getcountNewMessage($count)
215
+  {
216
+    if ($count == 1)
217
+    {
218
+      $transid = 'tags.new.has_news_one';
219
+      $transidlink = 'tags.new.has_news_link_one';
220
+    }
221
+    else if ($count == 0)
222
+    {
223
+      return '';
224
+    }
225
+    else 
226
+    {
227
+      $transid = 'tags.new.has_news';
228
+      $transidlink = 'tags.new.has_news_link';
229
+    }
230
+    
231
+    
232
+    if ($count > ($limit = $this->container->getParameter('search_default_count')))
233
+    {
234
+      $link = $this->trans(
235
+        'tags.new.has_news_link_more_x', 
236
+        array(
237
+          '%x%' => $limit
238
+        ), 
239
+        'userui'
240
+      );
241
+    }
242
+    else
243
+    {
244
+      $link = $this->trans(
245
+        $transidlink, 
246
+        array(), 
247
+        'userui'
248
+      );
249
+    }
250
+    
251
+    $link = '<a href="#" class="show_new_elements" >'.$link.'</a>';
252
+    
253
+    return $this->trans(
254
+      $transid, 
255
+      array(
256
+        '%count%' => $count,
257
+        '%link%'  => $link
258
+      ), 
259
+      'userui'
260
+    );
261
+  }
262
+  
263
+  /**
264
+   * Retourne le nombre de nouveaux éléments possible
265
+   *
266
+   * @param int $refid 
267
+   */
268
+  public function countNewsAction($refid)
269
+  {
270
+    if (!$this->getRequest()->isXmlHttpRequest())
271
+    { 
272
+      return $this->redirect($this->generateUrl('index'));
273
+    }
274
+    
275
+    if ($this->getUser() == 'anon.')
276
+    {
277
+      if ($this->getRequest()->isXmlHttpRequest())
278
+      {
279
+        return $this->jsonResponse(array(
280
+          'status' => 'mustbeconnected'
281
+        ));
282
+      }
283
+      else
284
+      {
285
+        return $this->redirect($this->generateUrl('index'));
286
+      }
287
+    }
288
+    
289
+    $es = $this->getElementSearcher();
290
+    $es->update(array(
291
+      // On veux de nouveaux éléments
292
+      'searchnew' => true,
293
+      // Notre id de référence
294
+      'id_limit'  => $refid
295
+    ));
296
+    
297
+    $count = $es->getElements($this->getDoctrine(), $this->getUserId(), 'count');
298
+    
299
+    return $this->jsonResponse(array(
300
+      'status'   => 'success',
301
+      'count'    => $count,
302
+      'message'  => $this->getcountNewMessage($count)
303
+    ));
304
+  }
305
+  
306
+  /**
307
+   * Cette action, utilisé en ajax seulement, retourne les x nouveaux éléments
308
+   * depuis le refid transmis. Tout en respectant le filtre en cours.
309
+   * 
310
+   * @param int $refid identifiant de l'élément de référence
311
+   * 
312
+   * @return jsonResponse
313
+   */
314
+  public function getNewsAction($refid)
315
+  {
316
+    if (!$this->getRequest()->isXmlHttpRequest())
317
+    { 
318
+      return $this->redirect($this->generateUrl('index'));
319
+    }
320
+    
321
+    if ($this->getUser() == 'anon.')
322
+    {
323
+      if ($this->getRequest()->isXmlHttpRequest())
324
+      {
325
+        return $this->jsonResponse(array(
326
+          'status' => 'mustbeconnected'
327
+        ));
328
+      }
329
+      else
330
+      {
331
+        return $this->redirect($this->generateUrl('index'));
332
+      }
333
+    }
334
+    
335
+    $es = $this->getElementSearcher();
336
+    $es->update(array(
337
+      // On veux de nouveaux éléments
338
+      'searchnew' => true,
339
+      // Notre id de référence
340
+      'id_limit'  => $refid,
341
+      // On en veut qu'un certain nombres
342
+      'count'     => $this->container->getParameter('search_default_count')
343
+    ));
344
+    
345
+    // Récupération de ces nouveaux élméents
346
+    $elements = $es->getElements($this->getDoctrine(), $this->getUserId());
347
+    
348
+    // On en fait un rendu graphique
349
+    $html_elements = $this->render('MuzichCoreBundle:SearchElement:default.html.twig', array(
350
+      'user'        => $this->getUser(),
351
+      'elements'    => $elements,
352
+      'invertcolor' => false
353
+    ))->getContent();
354
+    
355
+    // On calcule le nouveau compte de nouveaux
356
+    $count = 0;
357
+    if (count($elements))
358
+    {      
359
+      $es->update(array(
360
+        // On veux de nouveaux éléments
361
+        'searchnew' => true,
362
+        // Notre id de référence
363
+        'id_limit'  => $elements[0]->getId(),
364
+        // On n'en récupère que x
365
+        'count'     => $this->container->getParameter('search_default_count')
366
+      ));
367
+      $count = $es->getElements($this->getDoctrine(), $this->getUserId(), 'count');
368
+    }
369
+    
370
+    return $this->jsonResponse(array(
371
+      'status'  => 'success',
372
+      'html'    => $html_elements,
373
+      'count'   => $count,
374
+      'message' => $this->getcountNewMessage($count)
375
+    ));
376
+  }
377
+  
214 378
 }

+ 32 - 8
src/Muzich/CoreBundle/Repository/ElementRepository.php View File

@@ -30,12 +30,13 @@ class ElementRepository extends EntityRepository
30 30
    * @param ElementSearcher $searcher
31 31
    * @return Doctrine\ORM\Query
32 32
    */
33
-  public function findBySearch(ElementSearcher $searcher, $user_id)
34
-  {    
33
+  public function findBySearch(ElementSearcher $searcher, $user_id, $exec_type = 'execute')
34
+  {
35 35
     // Tableaux des paramétres
36 36
     $params_ids = array();
37 37
     $params_select = array();
38 38
     $params_select['uid'] = $user_id;
39
+    $order_by = "ORDER BY e_.created DESC, e_.id DESC";
39 40
     
40 41
     // Booléen nous permettant de savoir si un where a déjà été écrit
41 42
     $is_where = false;
@@ -138,18 +139,28 @@ class ElementRepository extends EntityRepository
138 139
       }
139 140
     }
140 141
     
141
-    // Si id_limit est précisé c'est que l'on demande "la suite"
142
+    // Si id_limit est précisé c'est que l'on demande "la suite" ou "les nouveaux"
142 143
     $where_id_limit = '';
143
-    if (($id_limit = $searcher->getIdLimit()))
144
+    if (($id_limit = $searcher->getIdLimit()) && !$searcher->isSearchingNew())
144 145
     {
145 146
       $where_id_limit = ($is_where) ? ' AND' : ' WHERE';
146 147
       $is_where = true;
147 148
       $where_id_limit .= " e_.id < :id_limit";
148 149
       $params_ids['id_limit'] = $id_limit;
149 150
     }
151
+    elseif ($id_limit && $searcher->isSearchingNew())
152
+    {
153
+      $where_id_limit = ($is_where) ? ' AND' : ' WHERE';
154
+      $is_where = true;
155
+      $where_id_limit .= " e_.id > :id_limit";
156
+      $params_ids['id_limit'] = $id_limit;
157
+      // Pour pouvoir charger les x nouveaux on doit organiser la liste 
158
+      // de manière croissante
159
+      $order_by = "ORDER BY e_.created ASC, e_.id ASC";
160
+    }
150 161
     
151 162
     // Requête qui selectionnera les ids en fonction des critéres
152
-    $r_ids = $this->getEntityManager()
163
+    $id_query = $this->getEntityManager()
153 164
       ->createQuery(
154 165
         "SELECT e_.id
155 166
         FROM MuzichCoreBundle:Element e_
@@ -163,12 +174,25 @@ class ElementRepository extends EntityRepository
163 174
         $where_favorite
164 175
         $where_id_limit
165 176
         GROUP BY e_.id
166
-        ORDER BY e_.created DESC, e_.id DESC")
177
+        $order_by")
167 178
      ->setParameters($params_ids)
168
-     ->setMaxResults($searcher->getCount())
169
-     ->getArrayResult()
170 179
     ;
171 180
     
181
+    // Si on a précisé que l'on voulait un count, pas de limite
182
+    if ($exec_type != 'count')
183
+    {
184
+      $id_query->setMaxResults($searcher->getCount());
185
+    }
186
+    
187
+    // si l'on a demandé un count
188
+    if ($exec_type == 'count')
189
+    {
190
+      // On retourne cette query
191
+      return $id_query;
192
+    }
193
+    
194
+    $r_ids = $id_query->getArrayResult();
195
+    
172 196
     $ids = array();
173 197
     
174 198
     if (count($r_ids))

+ 7 - 0
src/Muzich/CoreBundle/Resources/config/routing.yml View File

@@ -81,4 +81,11 @@ element_remove:
81 81
   pattern: /element/{element_id}/remove
82 82
   defaults: { _controller: MuzichCoreBundle:Element:remove }
83 83
   
84
+element_new_count:
85
+  pattern: /ajax/element/new/count/{refid}
86
+  defaults: { _controller: MuzichCoreBundle:Element:countNews, refid: null }
87
+  
88
+element_new_get:
89
+  pattern: /ajax/element/new/get/{refid}
90
+  defaults: { _controller: MuzichCoreBundle:Element:getNews, refid: null }
84 91
   

+ 2 - 0
src/Muzich/CoreBundle/Resources/views/layout.html.twig View File

@@ -38,6 +38,8 @@
38 38
     url_search_tag = "{{ path('search_tag') }}";
39 39
     url_get_favorites_tags = "{{ path('ajax_get_favorites_tags') }}";
40 40
     url_add_tag = "{{ path('ajax_add_tag') }}";
41
+    url_element_new_count = "{{ path('element_new_count') }}";
42
+    url_element_new_get = "{{ path('element_new_get') }}";
41 43
   </script>
42 44
   {% block js %}{% endblock %}
43 45
   

+ 33 - 10
src/Muzich/CoreBundle/Searcher/ElementSearcher.php View File

@@ -59,12 +59,21 @@ class ElementSearcher extends Searcher implements SearcherInterface
59 59
   /**
60 60
    * Si id_limit est renseigné c'est que l'on veut trouver les elements
61 61
    * plus vieux (ont utilise l'id comme référence) que l'id_limi passé.
62
+   * EDIT: Ou les éléments plus récents si $searchnew est a vrai
62 63
    * 
63 64
    * @var type int
64 65
    */
65 66
   protected $id_limit = null;
66 67
   
67 68
   /**
69
+   * Si searchnew est a vrai, c'est que l'on recherche les nouveau éléments 
70
+   * depuis id_limit.
71
+   * 
72
+   * @var type boolean
73
+   */
74
+  protected $searchnew = false;
75
+  
76
+  /**
68 77
    * @see SearcherInterface
69 78
    * @param array $params 
70 79
    */
@@ -77,7 +86,7 @@ class ElementSearcher extends Searcher implements SearcherInterface
77 86
     
78 87
     // Mise a jour des attributs
79 88
     $this->setAttributes(array(
80
-      'network', 'tags', 'count', 'user_id', 'group_id', 'favorite', 'id_limit'
89
+      'network', 'tags', 'count', 'user_id', 'group_id', 'favorite', 'id_limit', 'searchnew'
81 90
     ), $params);
82 91
     
83 92
   }
@@ -90,7 +99,7 @@ class ElementSearcher extends Searcher implements SearcherInterface
90 99
   {
91 100
     // Mise a jour des attributs
92 101
     $this->setAttributes(array(
93
-      'network', 'tags', 'count', 'user_id', 'group_id', 'favorite', 'id_limit'
102
+      'network', 'tags', 'count', 'user_id', 'group_id', 'favorite', 'id_limit', 'searchnew'
94 103
     ), $params);
95 104
   }
96 105
   
@@ -178,13 +187,16 @@ class ElementSearcher extends Searcher implements SearcherInterface
178 187
    * Construction de l'objet Query
179 188
    *
180 189
    * @param Registry $doctrine
190
+   * @param int $user_id
191
+   * @param string $exec_type
192
+   * 
181 193
    * @return collection
182 194
    */
183
-  protected function constructQueryObject(Registry $doctrine, $user_id)
195
+  protected function constructQueryObject(Registry $doctrine, $user_id, $exec_type = 'execute')
184 196
   {
185 197
     $this->setQuery($doctrine
186 198
       ->getRepository('MuzichCoreBundle:Element')
187
-      ->findBySearch($this, $user_id))
199
+      ->findBySearch($this, $user_id, $exec_type))
188 200
     ;
189 201
   }
190 202
   
@@ -192,14 +204,14 @@ class ElementSearcher extends Searcher implements SearcherInterface
192 204
    * Retourne l'objet Query
193 205
    * 
194 206
    * @param Registry $doctrine
207
+   * @param int $user_id
208
+   * @param string $exec_type
209
+   * 
195 210
    * @return collection
196 211
    */
197
-  public function getQuery(Registry $doctrine, $user_id)
212
+  public function getQuery(Registry $doctrine, $user_id, $exec_type = 'execute')
198 213
   {
199
-    if (!$this->query)
200
-    {
201
-      $this->constructQueryObject($doctrine, $user_id);
202
-    }
214
+    $this->constructQueryObject($doctrine, $user_id, $exec_type);
203 215
     return $this->query;
204 216
   }
205 217
 
@@ -209,11 +221,13 @@ class ElementSearcher extends Searcher implements SearcherInterface
209 221
    * 
210 222
    * @param Registry $doctrine
211 223
    * @param int $user_id
224
+   * @param string $exec_type Type d'execution
225
+   * 
212 226
    * @return collection
213 227
    */
214 228
   public function getElements(Registry $doctrine, $user_id, $exec_type = 'execute')
215 229
   {
216
-    $query = $this->getQuery($doctrine, $user_id);
230
+    $query = $this->getQuery($doctrine, $user_id, $exec_type);
217 231
     
218 232
     switch ($exec_type)
219 233
     {
@@ -221,10 +235,19 @@ class ElementSearcher extends Searcher implements SearcherInterface
221 235
         return $query->execute();
222 236
       break;
223 237
     
238
+      case 'count':
239
+        return count($query->getArrayResult());
240
+      break;
241
+    
224 242
       default :
225 243
         throw new \Exception('Mode de récupération des Elements non supporté.');
226 244
       break;
227 245
     }
228 246
   }
229 247
   
248
+  public function isSearchingNew()
249
+  {
250
+    return $this->searchnew;
251
+  }
252
+  
230 253
 }

+ 1 - 1
src/Muzich/CoreBundle/Searcher/Searcher.php View File

@@ -49,7 +49,7 @@ abstract class Searcher
49 49
     $this->query = $query;
50 50
   }
51 51
 
52
-  public function getQuery(Registry $doctrine, $user_id)
52
+  public function getQuery(Registry $doctrine, $user_id, $exec_type)
53 53
   {
54 54
     return $this->query;
55 55
   }

+ 6 - 1
src/Muzich/CoreBundle/lib/Controller.php View File

@@ -40,7 +40,12 @@ class Controller extends BaseController
40 40
   }
41 41
   
42 42
   /**
43
-   * Retourn l'objet ElementSearcher en cours.
43
+   * @desc Retourn l'objet ElementSearcher en cours.
44
+   * 
45
+   * @param int $count Si renseigné impact le nombre d'éléments qui seront 
46
+   * récupérés
47
+   * @param boolean $force_new Si a vrai la méthode procéède comme si on 
48
+   * demandé un nouveau objet de recherche (basé sur les tags favoris donc).
44 49
    * 
45 50
    * @return  ElementSearcher
46 51
    */

+ 8 - 0
src/Muzich/HomeBundle/Resources/views/Home/index.html.twig View File

@@ -37,6 +37,14 @@
37 37
     <input class="main button" type="submit" value="{{ 'filter.submit'|trans({}, 'userui') }}"/>
38 38
   </form>
39 39
 
40
+  <div class="display_more_elements" style="display: none;">
41
+    <span></span>
42
+  </div>
43
+
44
+  <div class="elements_loader_div">
45
+    <img class="elements_new_loader" style="display: none;" src="{{ asset('/bundles/muzichcore/img/ajax-loader.gif') }}" alt="loading" />
46
+  </div>
47
+
40 48
   {% include "MuzichCoreBundle:SearchElement:default.html.twig" with {'noelements_filter' : true }%}
41 49
     
42 50
   <div class="elements_loader_div">

+ 6 - 0
web/bundles/muzichcore/css/main.css View File

@@ -914,4 +914,10 @@ position: absolute;
914 914
 #container a.element_edit_link
915 915
 {
916 916
   text-decoration: none;
917
+}
918
+
919
+div.display_more_elements
920
+{
921
+  background-color: #D9F7FF;
922
+  text-align: center;
917 923
 }

+ 83 - 0
web/bundles/muzichcore/js/muzich.js View File

@@ -1029,6 +1029,7 @@ $(document).ready(function(){
1029 1029
         $('form[name="search"]').slideDown();
1030 1030
       }
1031 1031
       remove_tags('add');
1032
+      recolorize_element_list();
1032 1033
     }
1033 1034
     else if (response.status == 'error')
1034 1035
     {
@@ -1154,5 +1155,87 @@ $(document).ready(function(){
1154 1155
     
1155 1156
     return null;
1156 1157
   }
1158
+  
1159
+  ////////////////////////////////////////
1160
+  /// Gestion de nouveaux éléments
1161
+  
1162
+  function check_new_elements()
1163
+  {
1164
+    var url = url_element_new_count
1165
+      +'/'
1166
+      +str_replace('element_', '', $('ul.elements li:first').attr('id'))
1167
+    ;
1168
+    $.getJSON(url, function(response){
1169
+      
1170
+      if (response.status == 'mustbeconnected')
1171
+      {
1172
+        $(location).attr('href', url_index);
1173
+      }
1174
+      
1175
+      if (response.status == 'success' && response.count)
1176
+      {
1177
+        $('div.display_more_elements').show();
1178
+        $('div.display_more_elements span').html(response.message);
1179
+      }
1180
+      
1181
+      setTimeout(check_new_elements, 300000);
1182
+    });
1183
+  }
1184
+  
1185
+  if ($('div.display_more_elements').length)
1186
+  {
1187
+    setTimeout(check_new_elements, 300000);
1188
+  }
1189
+  
1190
+  $('a.show_new_elements').live('click', function(){
1191
+    var url = url_element_new_get
1192
+      +'/'
1193
+      +str_replace('element_', '', $('ul.elements li:first').attr('id'))
1194
+    ;
1195
+    $('img.elements_new_loader').show();
1196
+    $.getJSON(url, function(response){
1197
+      
1198
+      if (response.status == 'mustbeconnected')
1199
+      {
1200
+        $(location).attr('href', url_index);
1201
+      }
1202
+      
1203
+      if (response.status == 'success')
1204
+      {
1205
+        if (response.count)
1206
+        {
1207
+          $('div.display_more_elements').show();
1208
+          $('div.display_more_elements span').html(response.message);
1209
+        }
1210
+        else
1211
+        {
1212
+          $('div.display_more_elements').hide();
1213
+        }
1214
+        
1215
+        $('ul.elements').prepend(response.html);
1216
+        recolorize_element_list();
1217
+      }
1218
+      
1219
+      $('img.elements_new_loader').hide();
1220
+    });
1221
+  });
1222
+
1223
+  function recolorize_element_list()
1224
+  {
1225
+    $('ul.elements li.element').each(function(index){
1226
+      if ((index & 1) == 1)
1227
+      {
1228
+        $(this).removeClass('even');
1229
+        $(this).removeClass('odd');
1230
+        $(this).addClass('odd');
1231
+      }
1232
+      else
1233
+      {
1234
+        $(this).removeClass('odd');
1235
+        $(this).removeClass('even');
1236
+        $(this).addClass('even');
1237
+      }
1238
+    });
1239
+  }
1157 1240
    
1158 1241
  });