Fossil

Check-in [78721d4a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Per request in forumpost/9fd5135acc, added intra-document links to each response which link back to the being-replied-to post within the same page (using an #anchor-tag), without reloading from the server.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | forum-reply-links
Files: files | file ages | folders
SHA3-256: 78721d4aa0fa51ee98107da408c89bfa9c5e140ef7086e309aa28e15b59950c0
User & Date: stephan 2019-07-02 04:45:20
Context
2019-07-02
06:37
Replaced the forum post DIV ids forum{RID} with post-{short-UUID}, which allowed removal of the new A NAME tag and enables permalinks (RIDs are volatile). Added forumPost class to all post DIVs, to hopefully simplify some upcoming JS code. check-in: 69364ba5 user: stephan tags: forum-reply-links
04:45
Per request in forumpost/9fd5135acc, added intra-document links to each response which link back to the being-replied-to post within the same page (using an #anchor-tag), without reloading from the server. check-in: 78721d4a user: stephan tags: forum-reply-links
2019-07-01
13:38
Improvements to the help-text for /brlist. check-in: 611fe9b0 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/forum.c.

281
282
283
284
285
286
287
288
289




































290



291
292

293
294
295
296
297
298
299
...
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
...
372
373
374
375
376
377
378



379
380

381
382
383
384
385
386
387
...
404
405
406
407
408
409
410

411
412
413
414
415
416
417
...
423
424
425
426
427
428
429

430
431
432
433
434
435
436
...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
  @ <br>
  @ <label><input type="checkbox" name="trust">
  @ Trust user "%h(pPost->zUser)"
  @ so that future posts by "%h(pPost->zUser)" do not require moderation.
  @ </label>
  @ <input type="hidden" name="trustuser" value="%h(pPost->zUser)">
}

/*




































** Display all posts in a forum thread in chronological order



*/
static void forum_display_chronological(int froot, int target){

  ForumThread *pThread = forumthread_create(froot, 0);
  ForumEntry *p;
  int notAnon = login_is_individual();
  for(p=pThread->pFirst; p; p=p->pNext){
    char *zDate;
    Manifest *pPost;
    int isPrivate;        /* True for posts awaiting moderation */
................................................................................
    if( p->fpid==target ){
      @ <div id="forum%d(p->fpid)" class="forumTime forumSel">
    }else if( p->pLeaf!=0 ){
      @ <div id="forum%d(p->fpid)" class="forumTime forumObs">
    }else{
      @ <div id="forum%d(p->fpid)" class="forumTime">
    }

    if( pPost->zThreadTitle ){
      @ <h1>%h(pPost->zThreadTitle)</h1>
    }
    zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
    @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid))
    fossil_free(zDate);
    if( p->pEdit ){
      @ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a>
    }
    if( p->firt ){
      ForumEntry *pIrt = p->pPrev;
      while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev;
      if( pIrt ){
        @ reply to %z(href("%R/forumpost/%S?t=c",pIrt->zUuid))%d(p->firt)</a>
      }
    }
    if( p->pLeaf ){
      @ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\
      @ %d(p->pLeaf->fpid)</a>
    }
    if( g.perm.Debug ){
      @ <span class="debug">\
      @ <a href="%R/artifact/%h(p->zUuid)">artifact</a></span>
................................................................................
    @ </div>
  }
  forumthread_delete(pThread);
}

/*
** Display all messages in a forumthread with indentation.



*/
static int forum_display_hierarchical(int froot, int target){

  ForumThread *pThread;
  ForumEntry *p;
  Manifest *pPost, *pOPost;
  int fpid;
  const char *zUuid;
  char *zDate;
  const char *zSel;
................................................................................
      zUuid = p->pLeaf->zUuid;
      pPost = manifest_get(fpid, CFTYPE_FORUM, 0);
    }else{
      fpid = p->fpid;
      zUuid = p->zUuid;
      pPost = pOPost;
    }

    zSel = p->fpid==target ? " forumSel" : "";
    if( p->nIndent==1 ){
      @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'>
    }else{
      @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \
      @ style='margin-left: %d((p->nIndent-1)*3)ex;'>
    }
................................................................................
    zDate = db_text(0, "SELECT datetime(%.17g)", pOPost->rDate);
    @ <p>By %h(pOPost->zUser) on %h(zDate)
    fossil_free(zDate);
    if( g.perm.Debug ){
      @ <span class="debug">\
      @ <a href="%R/artifact/%h(p->zUuid)">(%d(p->fpid))</a></span>
    }

    if( p->pLeaf ){
      zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
      if( fossil_strcmp(pOPost->zUser,pPost->zUser)==0 ){
        @ and edited on %h(zDate)
      }else{
        @ as edited by %h(pPost->zUser) on %h(zDate)
      }
................................................................................
      zMode = "c";  /* Default to chronological on mobile */
    }else{
      zMode = "h";
    }
  }
  if( zMode[0]=='c' ){
    style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
    forum_display_chronological(froot, fpid);
  }else{
    style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
    forum_display_hierarchical(froot, fpid);
  }
  style_load_js("forum.js");
  style_footer();
}

/*
** Return true if a forum post should be moderated.









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>

|
>







 







>









|
<
<
<
<
<
<







 







>
>
>

|
>







 







>







 







>







 







|


|







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361






362
363
364
365
366
367
368
...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  @ <br>
  @ <label><input type="checkbox" name="trust">
  @ Trust user "%h(pPost->zUser)"
  @ so that future posts by "%h(pPost->zUser)" do not require moderation.
  @ </label>
  @ <input type="hidden" name="trustuser" value="%h(pPost->zUser)">
}

/*
** If pPost->firt then this routine outputs an "in reply to" link to
** the post being replied to, else this is a no-op.
**
** The generated link is a document-local reference to #post-ID, where
** ID is the short-form UUID of the being-reponded-to post (the length
** being determined by the %!S cgi_printf() flag).
**
** zPostName must be the name of the current post being displayed, as
** it appears in the the URL. e.g. for /forumpost/abcddcba, zPostName
** must be "abcddcba". This is required for building an absolute link
** to work around the document having a BASE tag which breaks
** intra-document links (which HTML treats like relative links, thus
** applying the BASE HREF to them).
**
** zTMode must be the current thread display mode: "c"=chronological,
** "h"=hierarchical. (Without that parameter on the URL, the browser
** switches from chronological to hierarchical view when clicking an
** intra-document link in the former mode.)
*/
static void forum_output_reply_link( const char *zPostName,
                                     const char * zTMode,
                                     const ForumEntry * pPost ){
  if( pPost->firt ){
    const ForumEntry *pIrt = pPost->pPrev;
    while( pIrt && pIrt->fpid!=pPost->firt ) pIrt = pIrt->pPrev;
    if( pIrt ){
      cgi_printf("in reply to [<a "
                 "href=\"%R/%s/%s?t=%s#post-%!S\">"
                 "%S</a>]\n",
                 g.zPath, zPostName, zTMode, pIrt->zUuid,
                 pIrt->zUuid);
    }
  }
}

/*
** Display all posts in a forum thread in chronological order
**
** See forum_output_reply_link() for details of the zPostName
** parameter.
*/
static void forum_display_chronological(int froot, int target,
                                        const char *zPostName){
  ForumThread *pThread = forumthread_create(froot, 0);
  ForumEntry *p;
  int notAnon = login_is_individual();
  for(p=pThread->pFirst; p; p=p->pNext){
    char *zDate;
    Manifest *pPost;
    int isPrivate;        /* True for posts awaiting moderation */
................................................................................
    if( p->fpid==target ){
      @ <div id="forum%d(p->fpid)" class="forumTime forumSel">
    }else if( p->pLeaf!=0 ){
      @ <div id="forum%d(p->fpid)" class="forumTime forumObs">
    }else{
      @ <div id="forum%d(p->fpid)" class="forumTime">
    }
    @ <a name="post-%!S(p->zUuid)"></a>
    if( pPost->zThreadTitle ){
      @ <h1>%h(pPost->zThreadTitle)</h1>
    }
    zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
    @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid))
    fossil_free(zDate);
    if( p->pEdit ){
      @ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a>
    }
    forum_output_reply_link( zPostName, "c", p );






    if( p->pLeaf ){
      @ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\
      @ %d(p->pLeaf->fpid)</a>
    }
    if( g.perm.Debug ){
      @ <span class="debug">\
      @ <a href="%R/artifact/%h(p->zUuid)">artifact</a></span>
................................................................................
    @ </div>
  }
  forumthread_delete(pThread);
}

/*
** Display all messages in a forumthread with indentation.
**
** See forum_output_reply_link() for details of the zPostName
** parameter.
*/
static int forum_display_hierarchical(int froot, int target,
                                      const char * zPostName){
  ForumThread *pThread;
  ForumEntry *p;
  Manifest *pPost, *pOPost;
  int fpid;
  const char *zUuid;
  char *zDate;
  const char *zSel;
................................................................................
      zUuid = p->pLeaf->zUuid;
      pPost = manifest_get(fpid, CFTYPE_FORUM, 0);
    }else{
      fpid = p->fpid;
      zUuid = p->zUuid;
      pPost = pOPost;
    }
    @ <a name="post-%!S(zUuid)"></a>
    zSel = p->fpid==target ? " forumSel" : "";
    if( p->nIndent==1 ){
      @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'>
    }else{
      @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \
      @ style='margin-left: %d((p->nIndent-1)*3)ex;'>
    }
................................................................................
    zDate = db_text(0, "SELECT datetime(%.17g)", pOPost->rDate);
    @ <p>By %h(pOPost->zUser) on %h(zDate)
    fossil_free(zDate);
    if( g.perm.Debug ){
      @ <span class="debug">\
      @ <a href="%R/artifact/%h(p->zUuid)">(%d(p->fpid))</a></span>
    }
    forum_output_reply_link( zPostName, "h", p );
    if( p->pLeaf ){
      zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
      if( fossil_strcmp(pOPost->zUser,pPost->zUser)==0 ){
        @ and edited on %h(zDate)
      }else{
        @ as edited by %h(pPost->zUser) on %h(zDate)
      }
................................................................................
      zMode = "c";  /* Default to chronological on mobile */
    }else{
      zMode = "h";
    }
  }
  if( zMode[0]=='c' ){
    style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
    forum_display_chronological(froot, fpid, zName);
  }else{
    style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
    forum_display_hierarchical(froot, fpid, zName);
  }
  style_load_js("forum.js");
  style_footer();
}

/*
** Return true if a forum post should be moderated.