Role Assignment Prototype v1

by Jason Crowther

HTML

<script src="//code.jquery.com/jquery-3.3.1.slim.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">

<p>Legend:</p>
<div id="legend" class="clearfix">
  <div class="roleBlock role1" data-r="1">Administrator</div>
  <div class="roleBlock role2" data-r="2">Processor</div>
  <div class="roleBlock role3" data-r="3">Approver</div>
  <div class="roleBlock role4" data-r="4">Manager</div>
  <div class="roleBlock role5" data-r="5">Submitter</div>
</div>

<table class="table table-sm">
<thead>
   <tr>
     <th>Person</th>
     <th>Roles</th>
   </tr>
</thead>
<tbody>
  <tr>
    <td>Fred Smith</td>
    <td>
      <div class="roleBlock role1" data-r="1" data-a="1"></div>
      <div class="roleBlock" data-r="2" data-a="0"></div>
      <div class="roleBlock role3" data-r="3" data-a="1"></div>
      <div class="roleBlock" data-r="4" data-a="0"></div>
      <div class="roleBlock" data-r="5" data-a="0"></div>
    </td>
  </tr>
  <tr>
    <td>Sally Watson</td>
    <td>
      <div class="roleBlock" data-r="1" data-a="0"></div>
      <div class="roleBlock" data-r="2" data-a="0"></div>
      <div class="roleBlock" data-r="3" data-a="0"></div>
      <div class="roleBlock role4" data-r="4" data-a="1"></div>
      <div class="roleBlock role5" data-r="5" data-a="1"></div>
    </td>
  </tr>
  <tr>
    <td>Jim Houston</td>
    <td>
      <div class="roleBlock" data-r="1" data-a="0"></div>
      <div class="roleBlock" data-r="2" data-a="0"></div>
      <div class="roleBlock" data-r="3" data-a="0"></div>
      <div class="roleBlock" data-r="4" data-a="0"></div>
      <div class="roleBlock" data-r="5" data-a="0"></div>
      
    </td>
 ...

CSS

.roleBlock {
  float: left;
  border: 1px solid #000;
  border-radius: 5px;
  margin: 0 5px;
}

#legend .roleBlock { color: #fff; padding: .5em }
#legend { margin:1em .5em; font-size: 80% }

.roleBlock {
  cursor: pointer;  
}
table .roleBlock {
  height: 20px;
  width: 20px;
}

.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}

JavaScript

var roleData = {
	1 : { name: 'Administrator', desc: 'Do administrator type of stuff.', privs: ['Priv A','Priv B']},
  2 : { name: 'Processor', desc: 'Process things and stuff.', privs: ['Priv A','Priv F']},
  3 : { name: 'Approver', desc: 'Check the details and then say things are good to go.', privs: ['Priv B','Priv C','Priv D']},
  4 : { name: 'Manager', desc: 'Make sure everybody else is doing their jobs.', privs: ['Priv C']},
  5 : { name: 'Submitter', desc: 'Puts things into the system.', privs: ['Priv C','Priv E']}
};
$(document).ready(function(){
	
  $('#legend .roleBlock').each(function(){
  	var c = $(this);
    
    var ri = roleData[c.data('r')]
    var pc ='';
    pc += '<p>'+ri.desc+'</p>';
    pc += '<hr>';
    pc += '<ul>';
    
    for(i=0; i<ri.privs.length; i++) {
    	pc += '<li>'+ri.privs[0]+'</li>';
    }
    
    pc += '</ul>';
    
    c.popover({
    	html: true,
    	content: pc,
      placement: 'bottom',
      title: ri.name
    });
  });
  
	// wire up tool tips for the role checkboxes
	$('table .roleBlock').each(function(){
  	var c = $(this);
    c.tooltip({title: roleData[c.data('r')].name});
	});

	// wire up click handlers for checkboxes
	$('table .roleBlock').click(function(e){
  	var c = $(e.target);
    var roleClass = 'role'+c.data('r');
    
    if( c.data('a') == 1) {
    	// turn off
      c.removeClass(roleClass);
      c.data('a',0);
    } else {
    	// turn on
      c.addClass(roleClass);
      c.data('a',1);
    }
    
    if( c.find('.changed').length ) {
			c.find('.changed').remove();    
    } else {
      c.append('<i class="changed far fa-circle"></i>');
    }
    
    checkForChanges();
    
  });
  
	$('#saveBtn').click(function(){
  	alert('this would send the changes back to the server...');
    $('table .changed').remove();
  })
});

function checkForChanges() {
	var $saveBtn = $('#saveBtn');
  var changeCount = $('table .changed').length;
  if( changeCount > 0 ) {
    $saveBtn.removeAttr('disabled');
  }...