Roles Editor v3

by Jason Crowther

HTML

<script src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css">
<div class="container">

<h1>Role Assignment Manager Prototype</h1>

<p>
  Legend:
</p>

<p>
<small>Tick checkbox to show only users with that role assigned currently.</small>
</p>


<div id="ll"></div>

<table id="dataTable" class="table table-sm  table-striped table-hover">
<thead>
<tr>
   <th>User</th>
   <th>Email</th>
   <th>Username</th>
   <th>Roles</th>
</tr>
</thead>
<tbody></tbody>
</table>

<!--
<p>
<input type="button" id="saveChangesBtn" value="Save Changes" disabled="disabled" class="btn btn-primary">
</p>
-->

</div>

<div style="display:none" id="saveWidget">
  <div class="alert alert-warning">
    <strong id="changeCount"></strong> Unsaved Role Change<span id="changePlural">s</span>
  <input id="saveChangesBtn" class="btn btn-primary" type="button" value="Save" style="margin-left: 1em">
  <input id="cancelChangesBtn" class="btn btn-secondary" type="button" value="Cancel">
  </div>
</div>

CSS

.roleBlock {
  float: left;
  border: 1px solid #000;
  border-radius: 5px;
  margin: 0 5px;
  cursor: pointer;
  height: 20px;
  width: 20px;
}

#ll .roleBlock {
  height: 15px;
  width: 15px;
  border-radius: 3px;
  margin-top: 4px;
}

#ll { margin-bottom: 1em }

.role1 { background-color: #aa3333;}
.role2 { background-color: #ab8333;}
.role3 { background-color: #83ab33;}
.role4 { background-color: #33ab33;}
.role5 { background-color: #33ab83;}

.changed { font-size: 6px; float: right; margin-right: 2px; margin-top: 2px}
.email { font-size:85% }

        #saveWidget {
            width: 25em;
            bottom: 0;
            left: 0;
            position: fixed;
            margin: 1em;
        }

JavaScript

var roleData = [
	{ id: 1, name: 'Administrator', desc: 'Do administrator type of stuff.', privs: ['Priv A','Priv B']},
  { id: 2, name: 'Processor', desc: 'Process things and stuff.', privs: ['Priv A','Priv F']},
  { id: 3, name: 'Approver', desc: 'Check the details and then say things are good to go.', privs: ['Priv B','Priv C','Priv D']},
  { id: 4, name: 'Manager', desc: 'Make sure everybody else is doing their jobs.', privs: ['Priv C']},
  { id: 5, name: 'Submitter', desc: 'Puts things into the system.', privs: ['Priv C','Priv E']}
];

var roleMap = {};

$.each(roleData,function(){
	roleMap[this.id] = this.name;
});

var data = [];

$(document).ready(function(){

	// fetch data with ajax
 	$.ajax({
  	async: false,
    url: 'http://linode3.purplewire.com/~jason/data/admin.json',
  	dataType: 'json',
  	success: function(d){
    	var id = 1;
			$.each(d,function(){
      	var u = {
        	id: this.i,
          firstName: this.f,
          lastName: this.l,
          roles: this.r,
          email: this.e,
          username: this.u
        }
        data.push(u);
      });
		}
  });

	// build the role legend
  $.each(roleData,function(){
		var d = $('<div class="form-check"></div>');
    
    d.append('<input class="form-check-input" data-r="'+this.id+'" type="checkbox" id="rf'+this.id+'">');
    d.append('<label class="form-check-label" for="rf'+this.id+'"><div class="roleBlock role'+this.id+'"></div>'+this.name+' </label>');
d.append(' <i class="fas fa-question-circle"></i>');

		var c = d.find('i');

		// add a fancy popover that shows details
    // for the role.

  	var pc ='';
    pc += '<p>'+this.desc+'</p>';
    pc += '<hr>';
    pc += '<ul>';
    
    for(i=0; i<this.privs.length; i++) {
    	pc += '<li>'+this.privs[i]+'</li>';
    }
    
    pc += '</ul>';
    
    c.popover({
    	html: true,
    	content: pc,
      placement: 'bottom',
      title: this.name
    });

		$('#ll').append(d);
  });

	// click handler for checkboxes in the legend
 ...