Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
9 posts Page 1 of 1
Hey folks,

It's been a widely requested feature and I am proud to deliver it right now as in screenshots.
download (2).png
download (2).png (12.18 KiB) Viewed 1400 times

download (3).png
download (3).png (27.34 KiB) Viewed 1400 times

download (4).png
download (4).png (6.63 KiB) Viewed 1400 times


Pagination between cloned pages in admin panel is a time-saver and makes it easier to navigate, edit, view etc. No more hitting back and forth, I guess. This version is a fully tested and working first draft, with basic <- # ->, so if you want to add something in it - welcome. Maybe a better css-styling? I hope someone can share an update to this.

Code: Select all
<cms:editable type='message' name='admin_navlinks' dynamic='default_data' order='-100'>cms_navlinks.html</cms:editable>

Place this simple line of code somewhere among the rest of the editables, better inside cms:template block.

Next, create a snippet with name cms_navlinks.html in your snippet directory.

Third, paste the following code to the snippet and visit the template as super-admin (as usual to register editable).

Code: Select all


<cms:if k_template_is_clonable >
  <cms:set total_pages = "<cms:pages count_only='1' />" scope='global' />
    <cms:if total_pages >

      <!-- A FAIR BIT OF STYLING -->
      <style>.panel { padding: 15px; border: 1px solid #ddd; border-radius: 2px;}.pull-right { float: right !important;}.pagination { padding: 0; margin-top:-11px ; border-radius: 3px;}.pagination > li { display: inline;} .pagination > li:first-child > a, .pagination > li:first-child > span { border-bottom-left-radius: 3px; border-top-left-radius: 3px;}.pagination > li > a, .pagination > li > span { position: relative; float: left; padding: 7px 12px; line-height: 2; text-decoration: none; color: #333333; background-color: #fff; border: 1px solid #ddd; margin-left: -1px;} .pagination > li:last-child > a, .pagination > li:last-child > span { border-bottom-right-radius: 3px; border-top-right-radius: 3px;} </style>

          <cms:hide>FIND CURRENT POSITION OF OPENED PAGE IN CMS</cms:hide>
          <cms:set edited_page_id = k_page_id scope='global' />
          <cms:pages paginate='0' limit='0' orderby='publish_date' order='desc' >
            <cms:if k_page_id = edited_page_id >
              <cms:set current_position = k_current_record scope='global' />
            </cms:if>
          </cms:pages>

          <cms:set prev_page_num = "<cms:sub current_position '1' />" /><cms:hide>PREVIOUS PAGE POSITION</cms:hide>
          <cms:set next_page_num = "<cms:add current_position '1' />" /><cms:hide>FOLLOWING PAGE POSITION</cms:hide>

    <div class="panel">
      <span>Pagination:&emsp;<cms:show total_pages /> Published Page<cms:if total_pages gt '1' >s</cms:if>. </span>
        Template: <span><a href="<cms:show k_template_link />" target="_blank" >open</a></span> /
           Page:
          <cms:hide>'DELETE' IS AVAILABLE FOR SUPERADMIN ONLY</cms:hide>
            <cms:if k_user_access_level = '10' >
                <span><a href="<cms:admin_delete_link />"  >del</a></span> /
            </cms:if>
          <span><a href="<cms:show k_page_link />" target="_blank" >open</a></span>

      <ul class="pagination pull-right">

        <cms:hide>CHECK ALL PAGES</cms:hide> 
          <cms:pages paginate='0' limit='0' orderby='publish_date' order='desc'>

            <cms:if k_current_record = prev_page_num ><cms:hide>SHOW LINK TO PREVIOUS PAGE</cms:hide>
              <li><a href='<cms:pages masterpage=k_template_name offset="<cms:sub prev_page_num '1' />"  limit='1' ><cms:admin_link /><cms:set title=k_page_title scope="global" /></cms:pages>' >←&nbsp;<cms:excerpt count='20' truncate_chars='1'><cms:show title /></cms:excerpt></a></li>
            </cms:if> 

            <cms:if k_current_record = current_position ><cms:hide>SHOW LINK TO CURRENT PAGE</cms:hide>
              <li><a href='<cms:pages masterpage=k_template_name offset=prev_page_num limit='1' ><cms:admin_link /></cms:pages>' ><cms:show current_position /></a></li>
            </cms:if>


            <cms:if k_current_record = next_page_num  ><cms:hide>SHOW LINK TO NEXT PAGE</cms:hide>
              <li><a href='<cms:pages masterpage=k_template_name offset=current_position  limit='1' ><cms:admin_link /><cms:set title=k_page_title scope="global" /></cms:pages>' ><cms:excerpt count='20' truncate_chars='1'><cms:show title /></cms:excerpt>&nbsp;→</a></li>
            </cms:if> 

          </cms:pages>


      </ul>
      </div>

    </cms:if><cms:hide>/total_pages</cms:hide>
</cms:if><cms:hide>/clonable</cms:hide>



I have also added titles for pages, truncated to 20 chars, to make everything more UI-friendly. Hope to hear your feedbacks, guys :D
I did use this function today, and i must say WOW. Makes the experience better and you can work more efficiant. If you have many pages like blog posts you can easyli just go back and forward without going out and then inn again like before.

Thank Trendoman for this on the current project :)
Thank you, @kimheggen :D

Today I worked on a very long page and it was pain to scroll down to view the page. So I added new links to my pagination: Open template, Open Page.
download.png
download.png (3.54 KiB) Viewed 1369 times


Also, I thought, sometimes it is very comfy to Delete Page, especially while in development. It would be nice for super-admin mostly, and I added this link with a simple check to make sure clients (logged-in as admins only) won't delete anything by chance.

Updated the whole code in the first post and fixed behavior for system-reserved template 'Users', which doesn't report much info about itself and therefore the code was not working correctly there. Now, pagination shouldn't appear in such places.
Complete overhaul was needed to increase the speed of code. It was too slow for a 1000 clonable pages, almost several seconds (5-6 sec) to calculate positions etc. Very ineffective!

Actually, the original code was over 20 sec, then optimized with parameter of cms:pages skip_custom_fields='1' it was close to reality with around 10 sec and best result 5-6 sec.
download (2).png
download (2).png (2.29 KiB) Viewed 1320 times


Now the thing is over 200 times faster!

download.png
download.png (4.98 KiB) Viewed 1320 times


Code: Select all

<cms:if k_template_is_clonable && k_page_name && k_page_date ne '0000-00-00 00:00:00' >
 
      <!-- A FAIR BIT OF STYLING -->
      <style>.panel { padding: 15px; border: 1px solid #ddd; border-radius: 2px;}.pull-right { float: right !important;}.pagination { padding: 0; margin-top:-11px ; border-radius: 3px;}.pagination > li { display: inline;} .pagination > li:first-child > a, .pagination > li:first-child > span { border-bottom-left-radius: 3px; border-top-left-radius: 3px;}.pagination > li > a, .pagination > li > span { position: relative; float: left; padding: 7px 12px; line-height: 2; text-decoration: none; color: #333333; background-color: #fff; border: 1px solid #ddd; margin-left: -1px;} .pagination > li:last-child > a, .pagination > li:last-child > span { border-bottom-right-radius: 3px; border-top-right-radius: 3px;} .warning {color:firebrick; font-weight: bold; } </style>

<cms:set total_pages = "<cms:pages count_only='1' />" scope='global' /> 
<cms:set position = "<cms:add '0' '1' />" scope='global' />
    <div class="panel">
     
      <span>Pagination:&emsp;<cms:show total_pages /> Page<cms:if total_pages gt '1' >s</cms:if>. </span>
            Template: <span><a href="<cms:show k_template_link />" target="_blank" >open</a></span> /
            Page: <span><a href="<cms:show k_page_link />" target="_blank" >open</a></span>
                  <cms:if k_user_access_level='10' ><cms:hide>'DELETE' AVAIL FOR SUPERADMIN</cms:hide>
                  <span ><a href="<cms:admin_delete_link />" class="warning" > / d</a></span></cms:if>
     
           
      <cms:ignore>SHOW PREV PAGES</cms:ignore>
      <cms:set my_sql="
      SELECT p.id, p.template_id
      FROM <cms:php>echo K_TBL_PAGES;</cms:php> p
      WHERE p.template_id='<cms:show k_template_id />'
      AND p.id > '<cms:show k_page_id />'
      AND NOT p.publish_date = '0000-00-00 00:00:00'
      ORDER BY p.id asc
      " />
     
      <cms:query sql=my_sql limit='1' paginate='1'
                 fetch_pages='1' skip_custom_fields='1' >
       
                <cms:set position = "<cms:add k_total_pages '1' />" scope='global' />

                <cms:if k_total_records_on_page gt '0' && k_current_record eq '1' >
                  <cms:set prev_page_link  = "<cms:admin_link />" scope='global' />
                  <cms:set prev_page_title = k_page_title scope='global' />
                </cms:if>

            <cms:no_results>
              <cms:set prev_page_link  = '' scope='global' />
            </cms:no_results>

      </cms:query>
     
     
      <cms:ignore>GET NEXT PAGE</cms:ignore>
      <cms:set my_sql="
      SELECT p.id, p.template_id
      FROM <cms:php>echo K_TBL_PAGES;</cms:php> p
      WHERE p.template_id='<cms:show k_template_id />'
      AND p.id < '<cms:show k_page_id />'
      AND NOT p.publish_date = '0000-00-00 00:00:00'
      ORDER BY p.id desc
      " />
     
      <cms:query sql=my_sql limit='2' paginate='1'
                 fetch_pages='1' skip_custom_fields='1' >
       
                <cms:if k_total_records_on_page gt '0' && k_current_record eq '1' >
                  <cms:set next_page_link = "<cms:admin_link />" scope='global' />
                  <cms:set next_page_title = k_page_title scope='global' />
                </cms:if>

            <cms:no_results>
              <cms:set next_page_link  = '' scope='global' />
            </cms:no_results>
      </cms:query>
     
     
      <ul class="pagination pull-right">
       
              <cms:if prev_page_link >
              <li>
                <a href="<cms:show prev_page_link />" >←&nbsp;
                         <cms:excerpt count='15' truncate_chars='1'>
                             <cms:show prev_page_title />
                         </cms:excerpt>
                 </a>
               </li>
              </cms:if>
       
              <li><a><cms:show position /></a></li>
                 
              <cms:if next_page_link >
              <li>
                <a href="<cms:show next_page_link />" >
                         <cms:excerpt count='15' truncate_chars='1'>
                             <cms:show next_page_title />
                         </cms:excerpt>&nbsp;→
                </a>
              </li>
              </cms:if>
       
      </ul>
      </div>
</cms:if>



It was possible thanks to earlier examples provided by @KK and a tag custom SQL queries from 2013 :D I really should think about using it more often as complexity grows. It is not only hundreds time faster, it's also very nice looking and beautifully coded. Art of the Speed :twisted: Rrrmm, Rmmm, Weeeaouww :lol:

Seriously, crazy stuff :)

A hint: to write the beautiful sql code it is not needed to write it actually :) return_sql='1' for cms:pages will show full sql query.
Code: Select all
<cms:pages start_on=k_page_date return_sql='1'  />


CouchCMS with no knowledge of PHP or SQL required :D

3a1f512d18d63c097653e820fc6e44342d9f70e8.jpg
3a1f512d18d63c097653e820fc6e44342d9f70e8.jpg (26.87 KiB) Viewed 1324 times
Thanks Anton - this code works beautifully!
I must say that there is little problem in version 2, however!
<cms:admin_delete_link /> not works, my question is - this tag will support in version 2?

Thanks
trendoman wrote: Hey folks...I have also added titles for pages, truncated to 20 chars, to make everything more UI-friendly. Hope to hear your feedbacks, guys :D


First, thanks for putting this together. I have found it very helpful.

Even though I'm not using your revised version, with the SQL query, I modified your original snippet to look and feel more like the admin theme, with a bit of CSS, uses icons, without the delete button as it didn't work, and with the use of localization strings where possible ("view" and "page"; but not for "first", "of" or "last").

Code: Select all
<cms:set page_translated="<cms:php>
  $words = array_map('strtolower', array_map('trim', array(\"<cms:localize 'pages'/>\",\"<cms:localize 'original_page'/>\",\"<cms:localize 'parent_page'/>\",\"<cms:localize 'points_to_another_page'/>\")));
  $sort_by_strlen = create_function('$a, $b', 'if (strlen($a) == strlen($b)) { return strcmp($a, $b); } return (strlen($a) < strlen($b)) ? -1 : 1;');
  usort($words, $sort_by_strlen);
  $longest_common_substring = array();
  $shortest_string = str_split(array_shift($words));
  while (sizeof($shortest_string)) { array_unshift($longest_common_substring, ''); foreach ($shortest_string as $ci => $char) { foreach ($words as $wi => $word) { if (!strstr($word, $longest_common_substring[0] . $char)) { break 2; } } $longest_common_substring[0].= $char; } array_shift($shortest_string); }
  usort($longest_common_substring, $sort_by_strlen);
  echo ucfirst(array_pop($longest_common_substring));
</cms:php>" />
<cms:if k_template_is_clonable>
  <cms:set total_pages = "<cms:pages count_only='1' skip_custom_fields='1'/>" scope='global'/>
  <cms:if total_pages>
    <style>.panel{padding:15px;border:1px solid #ddd;border-radius:2px;}.pull-right{float:right !important;}.pagination>li>a{margin-right:0px;}.pagination>li{display:inline;}.btn-icon-right{margin:0 -15px 0 10px;}</style>
    <cms:set edited_page_id = k_page_id scope='global'/>
    <cms:pages paginate='0' limit='1000000' orderby='publish_date' order='desc' skip_custom_fields='1'><cms:if k_page_id = edited_page_id><cms:set current_position = k_current_record scope='global'/></cms:if></cms:pages>
    <cms:set prev_page_num = "<cms:sub current_position '1'/>"/>
    <cms:set next_page_num = "<cms:add current_position '1'/>"/>
    <div class="panel">
      <a class="btn btn-success" href="<cms:show k_template_link/>" target="_blank"><span class="btn-icon"><cms:show_icon 'magnifying-glass'/></span><cms:localize 'view'/> <cms:show k_template_title/></a>
      <ul class="pagination pull-right">
        <cms:pages paginate='0' limit='1000000' orderby='publish_date' order='desc' skip_custom_fields='1'><cms:if k_current_record = prev_page_num>
        <li>
          <a class="btn" href='<cms:pages masterpage=k_template_name offset="<cms:sub current_page_num prev_page_num/>"  limit='1' skip_custom_fields='1'><cms:admin_link/><cms:set title=k_page_title scope="global"/></cms:pages>'><span class="btn-icon"><cms:show_icon 'media-step-backward'/></span>First</a>
          <a class="btn" href='<cms:pages masterpage=k_template_name offset="<cms:sub prev_page_num '1'/>"  limit='1' skip_custom_fields='1'><cms:admin_link/><cms:set title=k_page_title scope="global"/></cms:pages>'><span class="btn-icon"><cms:show_icon 'arrow-circle-left'/></span>"<cms:excerpt count='20' truncate_chars='1'><cms:show title/></cms:excerpt>"</a>
        </li>
        </cms:if><cms:if k_current_record = current_position>
        <li>
          <a class="btn btn-success" href='<cms:show k_page_link/>'><span class="btn-icon"><cms:show_icon 'magnifying-glass'/></span><cms:show page_translated /> <cms:show current_position/> of <cms:show total_pages/></a>
        </li>
        </cms:if><cms:if k_current_record = next_page_num>
        <li>
          <a class="btn" href='<cms:pages masterpage=k_template_name offset=current_position  limit='1' skip_custom_fields='1'><cms:admin_link/><cms:set title=k_page_title scope="global"/></cms:pages>'>"<cms:excerpt count='20' truncate_chars='1'><cms:show title/></cms:excerpt>"<span class="btn-icon btn-icon-right"><cms:show_icon 'arrow-circle-right'/></span></a>
          <a class="btn" href='<cms:pages masterpage=k_template_name offset="<cms:sub total_pages '1'/>" limit='1' skip_custom_fields='1'><cms:admin_link/><cms:set title=k_page_title scope="global"/></cms:pages>'>Last<span class="btn-icon btn-icon-right"><cms:show_icon 'media-step-forward'/></span></a>
        </li>
        </cms:if></cms:pages>
      </ul>
    </div>
  </cms:if>
</cms:if>


Hope this can be of use to someone!

Attachments

den0x, thank you very much for adapting original concept to CouchCMS 2. I tested it and found it looks and works just awesome (at first glance). Nice and thoughtful!

SQL version was needed for a job with thousands of cloned pages and older version of CMS. If something similar appears at hands with modern version of Couch, I'll try to revisit this topic and post changes.

Also, limit='0' equals to limit='1000' in Couch. In SQL version I didn't use limit at all, because number of pages was well above 1000. In short, changing in your code (and my original non-sql code) limit='0' to limit='10000000000000' :) should help try pagination correctly for such cases.
You're welcome and good point with regards to limit. I updated my post with both limits increased to 1000000.

I'm only just starting to explore CouchCMS in more detail and don't have something with that many pages yet.
I'd be curious if anyone's experience points to it still causing a poor performance at some point, and thus requiring SQL.
We'll find out here at some point I suppose!
@den0x, I found (again) your post very valuable. I have merged another code from post viewtopic.php?f=8&t=11665 to Approve-Un-approve pages. I.e. publish-unpublish.

2018-08-05-004.png
2018-08-05-004.png (26.63 KiB) Viewed 156 times

2018-08-05-005.png
2018-08-05-005.png (20.12 KiB) Viewed 156 times


Code: Select all
<!-- Template config -->
<cms:config_form_view>
   
   
   <cms:html>
     
      <cms:if "<cms:get_flash 'publish_status_success' />" >
         <cms:admin_add_js>
            $(function() {
               toastr.success("Your changes have been saved", "Success", { // TODO: localize
                  "positionClass": "toast-bottom-right",
                  "showDuration": "250",
                  "hideDuration": "250",
                  "timeOut": "2500",
                  "extendedTimeOut": "500",
                  "icon": '<cms:show_icon 'check' />'
               });
            });
         </cms:admin_add_js>
      </cms:if>

      <cms:if "<cms:is_ajax />">
         
         <cms:set status = "<cms:gpc 'status' />" />
         <cms:set pageid = "<cms:gpc 'id' />" />
         
         <cms:if status eq '1' >
            <cms:set new_publish_date = "<cms:date format='Y-m-d H:i:s' />" />
         <cms:else />   
            <cms:set new_publish_date = "0000-00-00 00:00:00" />
         </cms:if>
         
         <cms:db_persist
            _masterpage=k_template_name
            _page_id = pageid
            _mode='edit'         
            k_publish_date=new_publish_date
         >
            <cms:if k_success>
               <cms:set result_msg = 'Success!' scope='global'/>
               <cms:set_flash name='publish_status_success' value='1' />
            </cms:if>
           
            <cms:if k_error>
               <cms:set result_msg = 'Error!' scope='global'/>
            </cms:if>
         </cms:db_persist>
         
         <cms:abort msg=result_msg />
         
      </cms:if>   

      
      <cms:if k_page_date eq '0000-00-00 00:00:00' ><cms:ignore>

            // Adds label "unpublished"

         </cms:ignore>
         <span id="page-unpublished" class="label label-error" style="position: absolute;right: 210px;margin-top: 25px;">Unpublished</span>
      </cms:if>
      
      
    </cms:html>

   
    <cms:script>
     
      function change_publish_status( id, status, name ){
         var msg = '';
         if( status === '1'){
            msg = 'Are you sure you want to publish page: '+name+'?';
         }
         else{
            msg = 'Are you sure you want to un-publish page: '+name+'?';
         }   
         if( confirm(msg) ){

            $('body').css('cursor', 'wait');
            $.ajax({
               method: "POST",
               url: "<cms:show k_qs_link />",
               data: { id: id, status: status },
                  success: function(data) {

                     console.log(data);
                     //window.alert(data);
                     location.reload();

                  }
            })   
         }
      }
                     
    </cms:script>
      
   
   <cms:field 'admin_navlinks' label='Navigation' desc='Use this to go to other pages' order='10000'>
      <cms:embed 'extras/pages_nav_buttons_admin_form_view.html' />
   </cms:field>   
      
</cms:config_form_view>
<!-- Template config End -->





And in your amazing snippet, the new button goes like this:

Code: Select all
....
<div class="panel">
  <a class="btn btn-success" href="<cms:show k_template_link/>" target="_blank"><span class="btn-icon"><cms:show_icon 'magnifying-glass'/></span><cms:localize 'view'/> <cms:show k_template_title/></a>
 
    <!-- Approve-Un-approve button -->
    <cms:if k_page_date = '0000-00-00 00:00:00' >
        <a class="btn btn-primary" href="<cms:show k_template_link/>" target="_blank" onclick="change_publish_status( '<cms:show k_page_id />', '1', '<cms:show k_page_title />' ); return false;"><span class="btn-icon"><cms:show_icon 'power-standby'/></span><cms:localize 'approve'/>?</a>    
    <cms:else />
        <a class="btn btn-error" href="<cms:show k_template_link/>" target="_blank" onclick="change_publish_status( '<cms:show k_page_id />', '0', '<cms:show k_page_title />' ); return false;"><span class="btn-icon"><cms:show_icon 'power-standby'/></span><cms:localize 'unapprove'/>!</a>          
    </cms:if>
    <!-- Approve-Un-approve button End -->   

  <ul class="pagination pull-right">
....


My use-case is that I quickly review a page and do the 'unpublish' thing. Page has a link to video and a zip and my backend code checks if file is indeed present (viewtopic.php?f=8&t=11691). Pages were auto-generated from external source and some files are missing. This combined setup helps immensely.
9 posts Page 1 of 1

Who is online

In total there are 2 users online :: 1 registered, 0 hidden and 1 guest
(based on users active over the past 5 minutes)

Users browsing this forum: Majestic-12 [Bot] and 1 guest