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/jquery-2.1.0.js"></script>
    <script src="/yote/js/jquery.base64.min.js"></script>
    <script src="/yote/js/jquery.cookie.js"></script>
    <script src="/yote/js/json2.js"></script>
    <script src="/yote/js/yote.js"></script>
    <script src="/yote/js/yote.util.js"></script>

    <script src="/templates/default_templates.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( args, message ) {
	      $( '#' + args[ 'controls' ][ 'messages' ] ).empty().append( message );
	  }

      $().ready(function(){
	  $.yote.include_templates( '/templates/default_templates.html' );
	  $.yote.util.register_functions( base_templates );

	  $( '#mainpanel' ).hide();
	  $.yote.debug = true;
	  $.yote.init();
	  $.yote.debug = false;
	  root = $.yote.fetch_root();
	  $.yote.app = root;
	  $.yote.util.register_item( 'root', root );
	  // -------------------------------------

	  $.yote.util.register_functions( {
	      ref : function( args ) {
		  return args[ 'default_var' ][ 'class' ];
	      },
	      remove_attached : function( args ) {
		  $.yote.debug = true;
		  var dh = args[ 'vars' ][ 'fieldname' ];
		  args[ 'default_parent' ].set( dh, null );
		  args[ 'default_parent' ].delete_key( { name : '_attached_objects', key : dh } );
		  $.yote.debug = false;
		  $.yote.util.refresh_ui();
	      },
	      setup_attached : function( args ) {
		  $.yote.util.button_actions( 
		      {
			  button : '#' + args[ 'controls' ][ 'add_attached_b' ],
			  texts  : [ '#' + args[ 'controls' ][ 'field' ] ],
			  action : function() {
			      var k  = $( '#' + args[ 'controls' ][ 'field' ] ).val();
			      var ot = $( '#' + args[ '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 ) {
				  args[ 'default_var' ].set( k, o );
				  args[ 'default_var' ].hash( {  name  : '_attached_objects',
								 key   : k,
								 value : o } );
				  $.yote.util.refresh_ui();
			      }
			  } //action
		      } );
	      }, //setup_attached
	      RemovedUsers : function( args ) {
		  var pu = args[ 'default_var' ].count( '_removed_logins' );
		  return pu + ' user logins that have been removed <$$$ var uc ' + pu
		      + ' $$$> <$ button purge_users Flush all removed users $>';
	      }, //RemovedUsers
	      purge_users : function( args ) {
		  var noconfirm = 1*args[ 'vars' ][ 'pu' ] > 0;
		  if( noconfirm || confirm( 'Really purge ' + args[ 'vars' ][ 'uc' ] + ' removed users?' ) ) {
		      args[ 'default_var' ].purge_deleted_logins( '',
							      function(retmsg){ 
								  msg( args, retmsg ) },
							      function(err){ 
								  msg( args, err ) } );
		      $.yote.util.refresh_ui();
		  }
	      },
	      cron_entry_next_time : function( args ) {
		  var entry = args[ 'default_var' ];
		  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';
	      },
	      make_root : function( is_checked, user ) {
		  if( is_checked ) return root.make_root( user );
		  root.remove_root( user, function(){},function(err){ alert(err)} );
	      },
	      root_status : function( args ) {
		  var login = args[ 'default_var' ];
		  if( ! login ) return '';
		  return login.is_master_root() ? 'master root' : '<$ switch make_root ' + (1*login.is_root() != 0 ? '1' : '') + '$>';
	      },
	      is_validated : function( args ) {
		  return args[ 'default_var' ] && args[ 'default_var' ].is_validated() ? "Yes" : "No";
	      },
	      new_schedule:function( args ) {
		  var id = '#' + args[ 'controls' ][ 'new_schedule_time' ];
	      },
	  } );

	  $.yote.util.register_function( 'refresh_all', function() {
	      if( $.yote.is_root() ) {
		  $.yote.util.register_item( 'cron', root.cron() );
		  $.yote.util.register_item( 'root', root );
	      } else {
		  $.yote.util.unregister_item( 'cron' );
		  $.yote.util.unregister_item( 'root' );
	      }
	  } );

	  $.yote.util.refresh_ui();
      });
    </script>



<script type="text/template" class="yote_template_definition" template_name="Entry_Repeat">
 <$@ Entry_Repeat_Table Empty  _ repeats @$>
 Interval (min) : <$$$ new repeat_interval <input type="text"> $$$> <BR>
 Infinite Repeat : <$$$ new repeat_infinite <input type="checkbox"> $$$> <BR>
 Number Repeat Times : <$$$ new repeat_times <input type="text"> $$$> <BR>
 <$ newbutton _ repeats Add Repeat $>
</script>

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

  <table border=1><tr>  <th>Interval (mins)</th>     <th>Infinite Repeat</th>   <th>Repeats</th>
                        <th>Delete</th>
                        <th>Schedule</th> <th>Delete</th>
                  </tr>
      <@ Cron_Repeat_Row 2 @>
  </table>
  <$$ Paginator $$>
  <!-- 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><$ list_remove_button _ repeats $></td>
</script>



<script type="text/template" class="yote_template_definition" template_name="Cron_Schedule_Row">
  <tr>  <td><$ show $></td> <td><$ button remove_scheduled_time Delete $></td> </tr>
</script>



  <script type="text/template" class="yote_template_definition" template_name="Attached_Objects">
    <$% Attached_ObjTab Empty _ _attached_objects %$>
      <$$ Add_Attached $$>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Add_Attached">
    <$$$ control field <input type="text" placeholder="field"> $$$>
      <$$$ control 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> $$$>
	<$$$ control add_attached_b <BUTTON type="BUTTON">Attach Object</BUTTON> $$$>
	  <?? setup_attached ??>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Attached_Obj_Row">
    <$$$ var fieldname <$ hash_key $> $$$>
      <TR>
	<TD><$ hash_key $></TD>
	<TD><? ref ?></TD>
	<TD><$ button remove_attached Remove $></TD>
      </TR>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Attached_ObjTab">
    <table> <TR> <TH>Object Name</TH> <TH>Class</TH> <TH>Remove</TH> </TR>
      <% Attached_Obj_Row 10 %>
    </table>    
  </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">
    <A NAME="Users">
      <H3>Users</H3>
      <$% User_Table Empty _ _handles %$>
	<? RemovedUsers ?>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="User_Table">
    <table border=1><tr>  <th>Handle</th>     <th>Email</th>   <th>Is Root</th>
        <th>Was Validated</th>
      </tr>
      <% User_Row 10 %>
    </table>
    <$$ Paginator $$>
      <$$ SearchHash $$>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="User_Row">
    <tr>   <th><$ hash_key $></th> <th><$ show _ email $></th>   <th><? root_status ?></th>
      <th><? is_validated ?></th> </tr>
  </script>

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

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

    <table border=1><tr>  <th>Scheduled Time</th> <th>Delete</th> </tr>
      <@ Cron_Schedule_Row 2 @>
    </table>
    <$$ Paginator $$>
      <!-- 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">
    <$@ Entry_Schedule_Table _ scheduled_times Empty @$>
    <$$$ control new_schedule_time <input type="datetime-local"> $$$>
    <$ button new_schedule Schedule Time $>
  </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> <? cron_entry_next_time ?> </td>  <td> <$$ Entry_Repeat $$> </td>
      <td> <$$ Entry_Schedule $$> </td>  <td> <$ list_remove_button _ Delete $> </td>
    </tr>
  </script>

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

    <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>
      <@ Cron_Row 5 @>
    </table>
    <$$ Paginator $$>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Cron">
    <A NAME="Cron">
      <H3>Crons</H3>
      <$@ Cron_Table cron entries  Empty @$>
      <$ newbutton cron entries Add Cron $>
  </script>


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

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

  <script type="text/template" class="yote_template_definition" template_name="App_Row">
    <tr>   <td><$ hash_key $></td>     <td><$ edit _ host_name $></td>   <td><$ edit _ host_u2rl $></td>
      <td><?? function(args) { return args.default_var.count('_account_roots'); } ??> </td>   
      <td><$$ Email_Settings $$></td>  <td><$$ Attached_Objects $$></td>
      <td><$$$ controls reset_b <button type="button">Reset</button>$$$></td>
    </tr>
    <?
       function( ctx ) {
	   $( ctx.controls.reset_b ).click( function() {
	       root.purge_app( args.default_var );
	       $.yote.util.refresh_ui();
	   } );
       }
    ?>
  </script>


  <script type="text/template" class="yote_template_definition" template_name="App_Table">
    <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>
      <% App_Row 2 %>
    </table>
    <$$ Paginator $$>
    <BR>
    <$$ SearchHash $$>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="Apps">
    <A NAME="App">
      <H3>Applications Installed</H3>
      <$% App_Table _ _apps Empty %$>
      <??? function( args ) {
	     var pc = args.default_var.count( '_purged_apps' );
	     if( pc > 0 ) {
		 return pc + ' apps thate have been purged <$$$ control purge_apps <button type="button">Flush all Purged Apps</button> $$$>';
	     } 
	     return '';
           } ???>
      <$$ NewApp $$>
      <? function(args) {
	  $( args.controls.purge_apps ).click(function(){
	      args.default_var.flush_purged_apps(undefined,
						 function(){ 
						     msg( args, 'flushed purged apps' ) },
						 function(err){ 
						     msg( args, 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">
    <$$$ control messages <span class="message"></span> $$$>
    <$$ Apps $$>
    <$$ Cron $$>
    <$$ Users $$>
    <A HREF="#Top">Back to Top</A>
  </script>


  <script type="text/template" class="yote_template_definition" template_name="AdminBody">
    <DIV class="mainpanel" id="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>
      <$$ MainAdmin $$>
    </DIV>
  </script>

  <script type="text/template" class="yote_template_definition" template_name="MainBody">
    <?? function( arg ) {
         return $.yote.is_root() ?
	    '<DIV id="errpanel" class="err">Must be logged in with a root account to view this page.</DIV>' :
	    '<$$ AdminBody $$>';
        } 
    ??>
  </script>

  </head>

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