The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Yote Admin Page (YAP)</title>

    <script src="/yote/js"></script>

    <link href="/yote.css" rel="stylesheet" type="text/css" media="all" />
    <link href="/css/main.css" rel="stylesheet" type="text/css" media="all" />

    <META NAME="Author" CONTENT="Eric Wolf, coyocanid@gmail.com">

    <STYLE>
      .mainpanel { top:0px; width:900px; display:inline-block; }
      .tabs {
	      position: relative;
	      min-height: 300px; /* This part sucks */
	      clear: both;
	      margin: 25px 0;
      }
      .tab {
	      float: left;
      }
      .tab label {
	      background: #eee;
	      padding: 10px;
	      border: 1px solid #ccc;
	      margin-left: -1px;
	      position: relative;
	      left: 1px;
      }
      .tab [type=radio] {
	      display: none;
      }
      .content {
	      position: absolute;
	      top: 28px;
	      left: 0;
	      background: white;
	      right: 0;
	      bottom: 0;
	      padding: 20px;
	      border: 1px solid #ccc;
      }
      [type=radio]:checked ~ label {
	      background: white;
	      border-bottom: 1px solid white;
	      z-index: 2;
      }
      [type=radio]:checked ~ label ~ .content {
	      z-index: 1;
      }
      .apppanel {
          margin-left: 150px;
          border:none;
          padding:0!important;
          /*border is optional*/
          border-bottom:1px solid #444;
      }
      ._ct_row { vertical-align: top }
      ._ct_cell { border: 6px rgb(120,226,165) groove }

      tr { vertical-align: top }
    </STYLE>

<!--
there is a beauty that we experience as kids that only leaves tiny hints of itself when we are older.
it hides in smells and in the whispered wind.
if we are our experiences then we are both sides of them.

-->

    <script>
      var root;
	  function msg( ctx, message ) {
	      $( ctx.controls.messages ).empty().append( message );
	  }

      $().ready(function(){
          $.yote.debug = false;
$.yote.debug = true;
	      $.yote.templates.import_templates( '/templates/default_templates.html' );
	      $.yote.templates.import_templates( '/templates/yote_templates.html' );
	      $.yote.init(  );
          window.admin_data = $.yote.default_app.admin_prefetch();
	      $.yote.templates.init();
	      $.yote.templates.refresh();
      });
    </script>



<script type="text/template" class="yote_template_definition" template_name="Entry_Repeat">
  <table border=1><tr>  <th>Interval (mins)</th>     <th>Infinite Repeat</th>   <th>Repeats</th>
                        <th>Delete</th>
                  </tr>
      <$$ ListPaginate Cron_Repeat_Row _|repeats@@ $$>
  </table>
  <$$ Paginator _|repeats@@ $$>
  <$$$ newrep <button type="button">add repeat</button> $$$>
    <?
        $( ctx.controls.newrep ).click( function() {
            ctx.vars._.add_to( { name : 'repeats', items : [ $.yote.fetch_root().new_root_obj()] } );
	        $.yote.templates.refresh();
        } );
    ?>
</script>

<script type="text/template" class="yote_template_definition" template_name="Entry_Repeat_Table">
  <!-- pagination goes here. Under the hood, there must be a context container or a default tag, or even last list -->
</script>

<script type="text/template" class="yote_template_definition" template_name="Cron_Repeat_Row">
  <tr>  <td><$$ edit _ repeat_interval $$></td>  <td><$$ checkbox _ repeat_infinite $$></td>  <td><$$ edit _ repeat_times $$></td>  <td><$$$ delme <a href="#">delete</a>$$$></td> </tr>
    <?
        $( ctx.controls.delme ).click( function() {
            ctx.vars.__.remove_item( ctx.vars._ );
	        $.yote.templates.refresh();            
        } );
    ?>
</script>


<script type="text/template" class="yote_template_definition" template_name="Cron_Schedule_Row">
  <tr>  <td><$ show $></td> <td><$$$ controls remsched <button type="button">remove</button>$$$></td> </tr>
    <?
        $( ctx.controls.remsched ).click( function() {
            ctx.vars.__.remove_item( ctx.vars.hashkey_or_index );
        } );
    ?>
</script>



  <script type="text/template" class="yote_template_definition" template_name="Attached_Objects">
    <table> <TR> <TH>Object Name</TH> <TH>Class</TH> <TH>Remove</TH> </TR>
      <$$ HashPaginate Attached_Obj_Row admin|attached_objects%% $$>
    </table>
    <$$ Paginator admin|attached_objects%% $$>
    <$$ Add_Attached $$>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Add_Attached">
    <$$$ field <input type="text" placeholder="field"> $$$>
      <$$$ objtype <select> <option value="1">All May Edit</option> <option value="2">User and Root May Edit</option> <option value="3">Root May Edit</option></select> $$$>
	<$$$ add_attached_b <BUTTON type="BUTTON">Attach Object</BUTTON> $$$>
    <?
    $.yote.util.button_actions( 
	{
	    button : ctx.controls.add_attached_b,
	    texts  : [ ctx.controls.field ],
	    action : function() {
		var k  = $( ctx.controls.field ).val();
		var ot = $( ctx.controls.objtype ).val();
		var o = ot == 1 ? $.yote.fetch_root().new_obj() :
		    ot == 2 ? $.yote.fetch_root().new_user_obj() :
		    ot == 3 ? $.yote.fetch_root().new_root_obj() : null;
		if( o ) {
		    ctx.vars._.set( k, o );
		    ctx.vars._.hash( {  name  : '_attached_objects',
                                        key   : k,
					value : o } );
		    $.yote.templates.refresh();
		}
	    } //action
	} );
    ?>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Attached_Obj_Row">
    <$$$ set fieldname <$ hash_key $> $$$>
      <TR>
	<TD><$ hash_key $></TD>
	<TD><?? return ctx.vars._.class; ??></TD>
	<TD><$$$ remove_attached <button type="button">Remove</button> $$$></TD>
      </TR>
    <?
	    var dh = ctx.vars.fieldname;
	    ctx.vars.__.set( dh, null );
	    ctx.vars._.delete_key( { name : '_attached_objects', key : dh } );
	    $.yote.templates.refresh();
    ?>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Email_Settings">
    <table>
      <tr> <td><nobr>Email Validation Required</nobr> </td> <td> <$$ checkbox _ requires_validation $$> </td> </tr>
      <tr> <td><nobr>Validation Email From</nobr> </td> <td> <$$ edit _ validation_email_from $$> </td> </tr>
      <tr> <td><nobr>Validation Subject Template</nobr> </td> <td> <$$ edit _.validation_subject_template text $$> </td> </tr>
      <tr> <td><nobr>Validation Message Template</nobr> </td> <td> <$$ edit _.validation_message_template text $$> </td> </tr>
      <tr> <td><nobr>Validation Link Template</nobr> </td> <td> <$$ edit _.validation_link_template text $$> </td> </tr>
    </table>
  </script>

  <!-- ------------------------------ -->

  <script type="text/template" class="yote_template_definition" template_name="Users">
   <??? 
/*
      ctx.vars.handles = $.yote.wrap_hash( { 
             hash  : '_handles',
             obj   : ctx._app_,
             ctx   : ctx
          } );
*/
    ???>

    <a NAME="Users">
      <h3>Users</h3>
      <table border=1><tr>  
          <th>Handle</th>
          <th>Email</th>
          <th>Is Root</th>
          <th>Was Validated</th>
          <th>Reset Password</th>
        </tr>
        <$$ HashPaginate User_Row admin_data|handles%% 10 $$>
      </table>
      <$$ Paginator admin_data|handles%% $$> <br>
       <$$ SearchHash admin_data|handles%% values handle email $$>
       <br>
       user logins removed : <$$$ rl <span></span> $$$><br>
       <$$$ purge_users <button type="button">Flush all removed users</button> $$$>
       <?
           var pu = 1*ctx._app_.count( { name : '_removed_logins' } );
           $( ctx.controls.rl ).text( pu );
           if( pu == 0 ) {
               $( ctx.controls.purge_users ).prop( 'disabled', true );
           }
           $( ctx.controls.purge_users ).click( function() {
               if( confirm( 'Really purge ' + pu + ' removed users?' ) ) {
                   ctx._app_.purge_deleted_logins( '',
                                                   function(retmsg){ 
                                                       msg( ctx, retmsg ) },
                                                   function(err){ 
                                                       msg( ctx, err ) } );
                   $.yote.templates.refresh();
               }
           } );
       ?>
   </script>

   <script type="text/template" class="yote_template_definition" template_name="User_Row">
     <tr>   
       <th><$ _hashkey_ $></th>
       <th><$ _.email $></th>
       <th><???
          var login = ctx.vars._;
          return login ? login.is_master_root() ? 'master root' : 
                            '<$$$ toggle <input type="checkbox"> $$$>' : ''; 
          ???></th>
       <th><???
               return ctx.vars._ && ctx.vars._.is_validated() ? 'Yes' : 'No <$$$ makevalid <button type="button">validate</button>$$$>' ???>
       </th> 
       <th> <$$$ newp <input type="password" placeholder="new password">$$$> <$$$ newpup <button type="button">Update</button>$$$></th>
     </tr>
     <?
         if( ctx.vars._.get_is_root()*1 == 1 ) {
             $( ctx.controls.toggle ).attr( 'checked', true );
         }
         $( ctx.controls.toggle ).change( function() {
             if( $(this).is( ':checked' ) ) {
                 ctx._app_.make_root( ctx.vars._, function(){}, function(err){ alert(err) } );
             } else {
                 ctx._app_.remove_root( ctx.vars._, function(){},function(err){ alert(err)} )
             }
             $.yote.templates.refresh();
         } );
         $( ctx.controls.makevalid ).click( function() {
             ctx._app_.root_validate( { l : ctx.vars._ },
                                 function( pass ) { 
                                     msg( ctx, pass );$.yote.templates.refresh();
                                 }, function( err ) { msg( ctx, err ); } );
         } );
         $( ctx.controls.newpup ).click( function() {
             ctx._app_.root_reset_password( { p : $( ctx.controls.newp ).val(), l : ctx.vars._ },
                                     function( pass ) { 
                                         msg( ctx, pass ); $.yote.templates.refresh();
                                     }, function( err ) { msg( ctx, err ); } );
         } );
     ?>
   </script>

   <!------------------------------------------->
   <!----                 CRON               --->
   <!------------------------------------------->

   <script type="text/template" class="yote_template_definition" template_name="Entry_Schedule_Table">

       <!-- pagination goes here. Under the hood, there must be a context container or a default tag, or even last list -->
   </script>

   <script type="text/template" class="yote_template_definition" template_name="Entry_Schedule">

     <table border=1><tr>  <th>Scheduled Time</th> <th>Delete</th> </tr>
       <$$ ListPaginate Cron_Schedule_Row _|scheduled_times@@ 10 $$>
     </table>
     <$$ Paginator _|scheduled_times@@ $$>
     <$$$ new_schedule_time <input type="datetime-local"> $$$>
     <$$$ new_schedule <button type="button">Schedule Time</button> $$$>
     <?
         $( ctx.controls.new_schedule_time ).click( function() {
             alert( $( ctx.controls.new_schedule_time ).val() );
            
         } );
     ?>
   </script>

   <script type="text/template" class="yote_template_definition" template_name="checkbox"></script>

   <script type="text/template" class="yote_template_definition" template_name="Cron_Row">
     <tr> <td> <$$ edit _ name $$> </td>  <td> <$$ checkbox _ enabled $$> </td>  
       <td> <$$ edit _ notes $$> </td> <td> <$$ edit _ script $$> </td>  
       <td> <??
           var entry = ctx.vars._;
           if( ! entry ) return '';
           return entry.get( 'next_time' ) > 0 ? '<nobr>' +  $.yote.util.format_date( new Date( 60 * 1000 * entry.get( 'next_time' ) ), "h:m Y-M-D" ) + '</nobr>' : 'Not Scheduled';
           ??> </td>  <td> <$$ Entry_Repeat $$> </td>
       <td> <$$ Entry_Schedule $$> </td>  <td> <$$$ del <button type="button">delete</button> $$$> </td>
     </tr>
    <?
        ctx.vars.cron.update_entry( ctx.vars._ );
        $( ctx.controls.del ).click( function() {
            ctx.vars.cron.remove_from( { name : 'entries', items : [ ctx.vars._ ] } );
            $.yote.templates.refresh();
        } );
    ?>    
   </script>

   <script type="text/template" class="yote_template_definition" template_name="Cron_Table">

   </script>

   <script type="text/template" class="yote_template_definition" template_name="Cron">
     <??? ctx.vars.cron = ctx.vars.admin_data.get('cron'); ???>
     <A NAME="Cron">
       <H3>Crons</H3>
       <table border=1><tr>  <th>Name</th>     <th>Enabled</th>   <th>Notes</th>
           <th>Script</th>   <th>Next Run</th>  <th>Repeat</th>
           <th>Schedule</th> <th>Delete</th>
         </tr>
         <$$ ListPaginate Cron_Row cron|entries@@ 10 $$>
       </table>
       <$$ Paginator cron|entries@@ $$> <br>

       <$$$ newbutton <button type="button">Add Cron</button>$$$>
       <?
               $( ctx.controls.newbutton ).click( function() {
                   var newc = ctx.vars.cron.new_with_same_permissions();
                   ctx.vars.cron.add_entry( newc );
                   $.yote.templates.refresh();
               } );
        ?>
   </script>


   <!------------------------------------------->
   <!----                 APPS               --->
   <!------------------------------------------->

   <script type="text/template" class="yote_template_definition" template_name="NewApp">
     <div class="newapp">
       <h3>Create a new App</h3>
       App Name <$$$ name <input type="text"> $$$><BR>
       App Class <$$$ appclass <input type="text" value="Yote::AppRoot"> $$$><BR>
       <$$$ new_app_b <button type="BUTTON">Register App</BUTTON> $$$>
     </div>
     <?
     $.yote.util.button_actions( {
         button :   ctx.controls.new_app_b,
         texts  : [ ctx.controls.name ],
         action : function() {
         var newapp = ctx.vars.root.register_app(
             { 'name'    : $( ctx.controls.name ).val(),
               'class' : $( ctx.controls.appclass ).val() 
             },
             function() { $.yote.templates.refresh() },
             function(err) { msg( ctx, err ); }
         );
         } 
     } );
    ?>
   </script>

   <script type="text/template" class="yote_template_definition" template_name="App_Row">
     <???
        ctx.vars.admin = ctx.vars._.admin_prefetch();
      ???>
     <tr>   <td><$ _hashkey_ $></td>     <td><$$ edit _ host_name $$></td>   <td><$$ edit _ host_u2rl $$></td>
       <td><?? return ctx.vars._.count( { name : '_account_roots' } ); ??> </td>   
       <td><$$ Email_Settings $$></td>  <td><$$ Attached_Objects $$></td>
       <td><$$$ reset_b <button type="button">Reset</button>$$$></td>
     </tr>
     <?
        $( ctx.controls.reset_b ).click( function() {
            if( confirm( 'really purge app ' + ctx.hashkey ) ) {
            ctx.vars.root.purge_app( ctx.vars._ );
            $.yote.templates.refresh();
            }
        } )
     ?>
   </script>


   <script type="text/template" class="yote_template_definition" template_name="Apps">
    <A NAME="App">
    <H3>Applications Installed</H3>
    <???
/*
        ctx.vars.apps = $.yote.wrap_hash( { 
            hash  : '_apps',
            obj   : ctx._app_,
            ctx   : ctx,
            size  : 3
        } );
*/
console.log( ctx.parse( 'admin_data' ), ctx.parse( 'admin_data|apps%%' ), "P" );
    ???>
    <table border=1><tr>  <th>Name</th>     <th>Host</th>   <th>Host URL</th>
        <th>Number of Users</th>   <th>Email Settings</th> 
        <th>Attached Objects</th>  <th>Reset</th>
      </tr>
      <$$ HashPaginate App_Row admin_data|apps%% 3 $$>
    </table>
    <$$ Paginator admin_data|apps%% $$> <br>
    <$$ SearchHash admin_data|apps%% keys $$>
    <???
        var pc = $.yote.fetch_root().count( { name : '_purged_apps' } );
        if( pc > 0 ) {
            return pc + ' apps thate have been purged <$$$ purge_apps <button type="button">Flush all Purged Apps</button> $$$>';
	    } 
	    return '';
    ???>
    <$$ NewApp $$> <br>
    <$$$ flush_obj_cache <button type="button">Flush Object Cache</button>$$$> <BR>
    <$$$ flush_old_login <button type="button">Flush Old Login Tokens</button>$$$>

    <?
	    $( ctx.controls.purge_apps ).click(function(){
	        ctx.vars.root.flush_purged_apps(
                undefined,
		        function(){ $( ctx.controls.messages ).empty().append( 'flushed purged apps' ) },
		        function(err){ $( ctx.controls.messages ).empty().append( err ) }
	        ); 
        } );
	    $( ctx.controls.flush_obj_cache ).click(function(){
	        ctx.vars.root.reset_connections(
                undefined,
		        function(){ $( ctx.controls.messages ).empty().append( 'flushed object cache' ) },
		        function(err){ $( ctx.controls.messages ).empty().append( err ) }
	        ); 
        } );
	    $( ctx.controls.flush_old_login ).click(function(){
	        ctx.vars.root.clear_old_tokens(
                undefined,
		        function(){ $( ctx.controls.messages ).empty().append( 'flushed old tokens' ) },
		        function(err){ $( ctx.controls.messages ).empty().append( err ) }
	        ); 
        } );
    ?>
    </script>


  <!------------------------------------------->
  <!----                 MAIN               --->
  <!------------------------------------------->

  <script type="text/template" class="yote_template_definition" template_name="Empty">
     None Found
  </script>

  <script type="text/template" class="yote_template_definition" template_name="MainAdmin">
  </script>


  <script type="text/template" class="yote_template_definition" template_name="AdminBody">
    <???
       ctx.vars.admin_data = window.admin_data;
       ctx.vars.root = $.yote.default_app;
     ???>
    <DIV class="mainpanel">
      <SECTION>
	<DIV class="page-header">
	  <H1>Yote Admin Page (YAP)</H1>
	</DIV>
	<P>
	  Welcome to the Yote Admin Page. This page manages
          the <A HREF="#Users">users</A>, <A HREF="#App">apps</A> and <A HREF="#Cron">cron</A>.
	</P>
      </SECTION>
      <hr>
       <$$$ messages <span class="message"></span> $$$>
       <$$ Apps $$>
       <hr>
       <$$ Cron $$>
       <hr>
       <$$ Users $$>
     <BR>
      <A HREF="#Top">Back to Top</A>
     </DIV>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="MainBody">
    <???
         return $.yote.has_root_permissions() ?
	    '<$$ AdminBody $$>' :
	    '<DIV id="errpanel" class="err">Must be logged in with a root account to view this page. ' + ( $.yote.is_logged_in() ? '<$$$ lo <a href="#">$$$>logout</a>' : '' ) + '</DIV>';
    ???>
    <? $( ctx.controls.lo ).click( function() { $.yote.logout() } ); ?>
  </script>

  </head>

  <BODY>
    <DIV class="yote_template" template="YoteHeaderAdmin"></div>
    <A NAME="Top"/>
    <DIV class="yote_template main" template="MainBody"></div>
  </body>
</html>