The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<!DOCTYPE html>
<html>
<!-- Bootstrappy and meta. This page could replace itself -->
  <head>
    <title>Yote Admin 2</title>
    <script src="/yote/js/jquery-latest.js"></script>
    <script src="/yote/js/jquery.cookie.js"></script>
    <script src="/yote/js/jquery.base64.min.js"></script>
    <script src="/yote/js/json2.js"></script>

    <script src="/js/main.js"></script>
    <script src="/yote/js/yote.js"></script>
    <script src="/yote/js/yote.util.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; }
      .sidenav { float: left; text-align: center; }
      button.sidenav {     background:none!important; cursor:pointer;
     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 }
    </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;
    $().ready(function(){
	$( '#mainpanel' ).hide();
	$.yote.debug = false;
	$.yote.init();

	$( 'button.sidenav' ).each( function( idx, domEl ) {
	    $(this).click(function(){
		$( '.apppanel' ).hide();
		$( '#' + $(this).attr('id') + '_div' ).show();
	    });
	} );

	attach_login( {
	    attachpoint         : '#logged_in_status',
	    message_attachpoint : '#msg_div',
	    after_login  : check_perms,
	    after_logout : check_perms
	} );

	// -------------------------------------
	var cron, root, apps, users;
	function check_perms() {
	    if( $.yote.is_root() ) {
		$( '#errpanel' ).hide();
		$( '#mainpanel' ).show();
 		root = $.yote.fetch_root();
		cron = root.cron();
		register_templates();
		refresh_all();
	    }
	    else {
		$( '#errpanel' ).show();
		$( '#mainpanel' ).hide();
 	    }
	} //check_perms

	function register_templates() {
	    apps = root.wrap_hash( { collection_name : '_apps', size : 1 } );
	    users = root.wrap_hash( { collection_name : '_handles', size : 1 } );
	    cron_list = cron.wrap_list( { collection_name : 'entries', size : 2 } );
 	    $.yote.util.register_items( {
		apps : apps,
		users : users,
		cron_list : cron_list
	    } );
	}

	function refresh_all() {
	    if( ! apps ) {
		apps  = root.wrap_hash( { collection_name : '_apps', size : 1 } );
		users = root.wrap_hash( { collection_name : '_handles', size : 1 } );
		cron_list = cron.wrap_list( { collection_name : 'entries', size : 2 } );
	    }

	    $.yote.util.register_item( 'apps', apps );
	    $.yote.util.register_item( 'users', users );

	    $.yote.util.register_functions( {
		count_users : function( def_var_app ) {
		    return def_var_app.count('_account_roots');
		},
		make_pag_right: function( collection ) {
		    var ddx = $.yote.util.next_id();
		    '<button type="Button" id="pag_right">&gt;</button>'; // OH no,  this is going to have to be a bit more complex.
		},
		reset_app : function( def_var_app, def_parent, appname ) {
		    if( confirm( "Purge app?" + def_var_app ) ) {
			root.purge_app( def_var_app );
			refresh_all();
		    }
		},
		beep : function( a, b, c ) {
		    console.log( [a,b,c]); //try and get a b and c
		    alert( 'beep' );
		},
		master_root : function( acct ) {
		    //want a checkbox, dammit. Can make with ordinary code, but want with templates. an on_change
		    return acct.is_master_root() ? 'master root' : '<$ switch make_root ' + (1*acct.is_root() != 0 ? '1' : '') + '$>';
		},
		make_root : function( is_checked, user ) {
		    if( is_checked ) {
			root.make_root( user );
		    }
		    else {
			root.remove_root( user, function(){},function(err){ alert(err)} );
		    }
		},
		no_apps : function( apps ) {
		    var sc = apps.get_hashkey_search_criteria();
		    if( sc ) 
			return '<h3>No Apps Found for search "' + sc + '"</h3><$$ Search $$>';
		    return '<h3>No Apps</h3>';
		},
		is_validated : function( acct ) {
		    return acct.is_validated() ? "Yes" : "No";
		},
		cron_entry_next_time : function( entry ) {
		    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';
		}
	    } );

	    $.yote.util.register_templates( {
		Apps : '<%% App_row_top App_row App_row_bottom No_Apps apps %%>',
		Beep : '<$ button beep BeEp $>',
		App_row_top : '<H3>Apps</H3><BR>' +
		    '<table border=1><tr>' + [ 'Name', 'Host', 'Host URL', 'Number of Users', 'Email Settings', 'Reset' ].map( function(h) { return '<td>' + h + '</td>' } ).join('') + '</tr>',
		App_row_bottom : '</table><$$ Beep $$><$$ Search $$><div id="app_pagination"></div>',
		Search : '<input type="text" id="search_val"> <button type="button" id="search_go">Search</button> <BR> ',
		Pagination : '<button type="Button" id="pag_begin">&lt;&lt;</button> ' +
		    '<button type="Button" id="pag_left">&lt;</button> ' +
		    '<button type="Button" id="pag_right">&gt;</button>' +
		    '<button type="Button" id="pag_end">&gt;&gt;</button>',  // <--- should these be in a reused template
		App_row : '<tr><td><$ hash_key $></td>' +
		    '<td><$ edit _ host_name $></td>' +
		    '<td><$ edit _ host_url $></td>' +
		    '<td><? count_users ?></td>' +
		    '<td>Email Validation Required <$ checkbox _ requires_validation $><BR>' +
		    'Validation Email From <$ edit _ validation_email_from $> <BR>' +
		    'Validation Link Template <$ edit _ validation_link_template $> <BR>' +
		    'Validation Message Template <$ edit _ validation_message_template $> <BR>' +
		    'Validation Subject Template <$ edit _ validation_subject_template $> <BR>' +
		    'Recovery Email From <$ edit _  recovery_email_from $> <BR>' +
		    'Recover Subject Template <$ edit _  recovery_subject_template $> <BR>' +
		    'Recovery Message Template <$ edit _  recovery_message_template $> <BR>' +
		    'Recovery Link Template  <$ edit _  recovery_link_template $>' +
		    '</td>' +
		    '<td><$ button reset_app Reset $></td></tr>',
		No_Apps : "<? no_apps ?>",

		Users : '<%% Users_top Users_row Users_bottom No_Users users %%>',

		No_users : '<div id="app_pagination"></div>',

		Users_top : '<h3>Users</h3><BR><table border=1><tr><th>Handle</th><th>Email</th><th>Is Root</th><th>Is Validated</th></tr>',

		Users_row : '<tr><td><$ show _ handle $></td> <td><$ show _ email $></td> <td><? master_root  ?></td> <td><? is_validated ?></td> </tr>',

		Users_bottom : '</table><div id="app_pagination"></div>',

		Cron : '<h3>Crons</h3>All Cron Progrms<BR><@@ Cron_top Cron_row Cron_bottom No_Cron cron_list @@>',

		Cron_top : '<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 : '<tr> <td><$ edit _ name $></td> <td><$ checkbox _ enabled $></td> <td><$ edit _ notes $></td> <td><$ edit _ script $></td> <td><? cron_entry_next_time ?></td> <td><@@ Repeat_top Repeat_row Repeat_bottom Repeat_None _ repeats @@></td>   <td><@@ Schedule_top Schedule_row Schedule_bottom Schedule_None _ scheduled_times @@></td>   <td><$ button delete_cron Delete $></td> </tr>',

		Cron_bottom : '</table> <$ button add_cron New Entry $>',
		
		Schedule_top : '<table><tr><th>Schedule Time</th><th>Delete</th></tr>',

		Schedule_bottom : '</table>',
		
		Schedule_row : '<tr><td></td><td><$ button unschedule Unschedule $></td></tr>',

		Schedule_None : 'Nothing Scheduled',

		Repeat_top : '<table><tr><th>Interval (mins)</th><th>Infinite Repeat</th><th>Repeat Count</th><th>Delete</th></tr>',

		Repeat_bottom : '</table>',
		
		Repeat_row : '<tr><td><$ edit _ repeat_interval $></td><td><$ checkbox _ repeat_infinite $></td><td><$ edit _ repeat_times $></td><td><$ button delete_repeat Delete $></td></tr>',

		Repeat_None : 'Nothing Repeated',

	    } );

	    $( '#admin_parts' ).empty().append( $.yote.util.fill_template( "Apps", apps ) );
	    $( '#admin_parts_2' ).empty().append( $.yote.util.fill_template( "Users", users ) );
	    $( '#admin_parts_3' ).empty().append( $.yote.util.fill_template( "Cron", cron_list ) );

	    $.yote.util.button_actions( {
		button : '#search_go',
		texts  : [ '#search_val' ],
		required : [],
		cleanup_exempt : [ '#search_val' ],
		action : function() {
		    val = $( '#search_val' ).val();
 		    apps.set_hashkey_search_criteria( val );
		    refresh_all();
		    $( '#search_val' ).val( val );
		}
	    } );
//<div id="app_pagination"></div>',
	    if( apps.can_rewind() ) {
		$( '#pag_left' ).attr( 'disabled', false );
		$( '#pag_begin' ).attr( 'disabled', false );
		$( '#pag_left' ).click( function() { apps.back(); refresh_all(); } );
		$( '#pag_begin' ).click( function() { apps.first(); refresh_all(); } );
	    } else {
		$( '#pag_left' ).attr( 'disabled', true );
		$( '#pag_begin' ).attr( 'disabled', true );
	    }
	    if( apps.can_fast_forward() ) {
		$( '#pag_right' ).attr( 'disabled', false );
		$( '#pag_end' ).attr( 'disabled', false );
		$( '#pag_right' ).click( function() { apps.forwards(); refresh_all(); } );
		$( '#pag_end' ).click( function() { apps.last(); refresh_all(); } );
	    } else {
		$( '#pag_right' ).attr( 'disabled', true );
		$( '#pag_end' ).attr( 'disabled', true );
	    }
	    $.yote.util.init_ui();
	}//refresh_all
    });
    </script>
  </head>

  <BODY>

    <DIV class="header">
      <A href="/index.html" style="display:block">
	<img height="70px" width="151px" src="yotelogo.png">
      </A>
      <UL id="top_nav" class="nav"></UL>
      <DIV class="login logged_in" id="logged_in_status"></DIV>
      <DIV id="msg_div"></DIV>
    </DIV>

    <DIV id="errpanel" class="err">
      Must be logged in with a root account to view this page.
    </DIV>

    <DIV class="mainpanel" id="mainpanel">

	<!--
	    accounts, with pagination and search
	    edit motd
            add and edit news
	    show apps
	  -->

	<SECTION>
	  <DIV class="page-header">
	    <H1>Yote Admin Page (YAP)</H1>
	  </DIV>
	  <P>
	    Welcome to the Yote Admin Page. This page manages
            the users, apps and cron.
	  </P>
	</SECTION>

	<DIV class="appwrapper">
	  <DIV id="sidenav" class="sidenav">
            <UL>
	      <LI><BUTTON class="sidenav" disabled id="app_b">Apps</BUTTON></LI>
	      <LI><BUTTON class="sidenav" disabled id="user_b">Users</BUTTON></LI>
	      <LI><BUTTON class="sidenav" disabled id="cron_b">Cron</BUTTON></LI>
            </UL>
	  </DIV>

	  <DIV id="user_b_div"></div>

	  <DIV id="app_b_div"></div>

	  <DIV id="cron_b_div"></div>

	</DIV>

    </DIV>

    <hr>

    <div id="admin_parts"></div>
    <div id="admin_parts_2"></div>
    <div id="admin_parts_3"></div>

    <footer>
    </footer>
  </body>
</html>