- 07. Tutorial: Creating a Kanban Board
- Accessing Planet Data
- Query Planet Data
- Add column for records without a Trip No and assign planets to it
- Go through each column, and categorise our Planet records
- Instantiate our draggable list
- Changing sort order
- Polling for changes
<html>
<head>
<style>
<!–– CSS Goes here ––>
</style>
</head>
<script type='text/javascript' src='FRToolBox.js'></script>
<script src="jquery-3.4.1.min.js"></script>
<script src="jquery-ui.min.js"></script>
<!–– Import other sources here ––>
<script>
FMLink = 'FM.link';
// This is where variables are set from the given parameters
var RecordsObj = new Object;
FMTableOccurrenceName = '<?Reactor bbdev_TO( $PlanetIDField ) Reactor?>';
FunctionWhereClause = '<?Reactor bbdev_Relationship( bbdev_TO( $PlanetIDField ) ) Reactor?>';
CreationValues = '<?reactor bbdev_relationshipKeyBuilder ( $FMTableOccurrenceName ) reactor?>';
PlanetIDField = '<?Reactor bbdev_Field( $PlanetIDField ) Reactor?>';
PlanetNameField = '<?Reactor bbdev_Field( $PlanetNameField ) Reactor?>';
PlanetDescriptionField = '<?Reactor bbdev_Field( $PlanetDescriptionField ) Reactor?>';
PlanetTripNoField = '<?Reactor bbdev_Field( $PlanetTripNoField ) Reactor?>';
PlanetSortNoField = '<?Reactor bbdev_Field( $PlanetSortNoField ) Reactor?>';
Columns = '<?Reactor $Columns Reactor?>';
</script>
<body>
<div>
<!–– This is the main HTML for the BlackBox ––>
</div>
</body>
</html>
#sortable1, #sortable2 {
border: 1px solid #eee;
width: 142px;
min-height: 20px;
list-style-type: none;
margin: 0;
padding: 5px 0 0 0;
float: left;
margin-right: 10px;
}
#sortable1 li, #sortable2 li {
margin: 0 5px 5px 5px;
padding: 5px;
font-size: 1.2em;
width: 120px;
}
$( function() {
$( "#sortable1, #sortable2" ).sortable({
connectWith: ".connectedSortable"
}).disableSelection();
} );
<ul id="sortable1" class="connectedSortable">
<li class="ui-state-default">Item 1</li>
<li class="ui-state-default">Item 2</li>
<li class="ui-state-default">Item 3</li>
<li class="ui-state-default">Item 4</li>
<li class="ui-state-default">Item 5</li>
</ul>
<ul id="sortable2" class="connectedSortable">
<li class="ui-state-highlight">Item 1</li>
<li class="ui-state-highlight">Item 2</li>
<li class="ui-state-highlight">Item 3</li>
<li class="ui-state-highlight">Item 4</li>
<li class="ui-state-highlight">Item 5</li>
</ul>
<html>
<head>
<style>
#sortable1, #sortable2 {
border: 1px solid #eee;
width: 142px;
min-height: 20px;
list-style-type: none;
margin: 0;
padding: 5px 0 0 0;
float: left;
margin-right: 10px;
}
#sortable1 li, #sortable2 li {
margin: 0 5px 5px 5px;
padding: 5px;
font-size: 1.2em;
width: 120px;
}
</style>
</head>
<script type='text/javascript' src='FRToolBox.js'></script>
<script src="jquery-3.4.1.min.js"></script>
<script src="jquery-ui.min.js"></script>
<script>
FMLink = 'FM.link';
FMTableOccurrenceName = '<?Reactor bbdev_TO( $PlanetIDField ) Reactor?>';
FunctionWhereClause = '<?Reactor bbdev_Relationship( bbdev_TO( $PlanetIDField ) ) Reactor?>';
CreationValues = '<?reactor bbdev_relationshipKeyBuilder ( $FMTableOccurrenceName ) reactor?>';
PlanetIDField = '<?Reactor bbdev_Field( $PlanetIDField ) Reactor?>';
PlanetNameField = '<?Reactor bbdev_Field( $PlanetNameField ) Reactor?>';
PlanetDescriptionField = '<?Reactor bbdev_Field( $PlanetDescriptionField ) Reactor?>';
PlanetTripNoField = '<?Reactor bbdev_Field( $PlanetTripNoField ) Reactor?>';
PlanetSortNoField = '<?Reactor bbdev_Field( $PlanetSortNoField ) Reactor?>';
Columns = '<?Reactor $Columns Reactor?>';
$( function() {
$( "#sortable1, #sortable2" ).sortable({
connectWith: ".connectedSortable"
}).disableSelection();
} );
</script>
<body>
<ul id="sortable1" class="connectedSortable">
<li class="ui-state-default">Item 1</li>
<li class="ui-state-default">Item 2</li>
<li class="ui-state-default">Item 3</li>
<li class="ui-state-default">Item 4</li>
<li class="ui-state-default">Item 5</li>
</ul>
<ul id="sortable2" class="connectedSortable">
<li class="ui-state-highlight">Item 1</li>
<li class="ui-state-highlight">Item 2</li>
<li class="ui-state-highlight">Item 3</li>
<li class="ui-state-highlight">Item 4</li>
<li class="ui-state-highlight">Item 5</li>
</ul>
</body>
</html>
<ul id="sortable1" class="connectedSortable">
<li><div class=name>Item 1</div><div class=desc>The first item</div></li>
<li><div class=name>Item 2</div><div class=desc>The second item</div></li>
<li><div class=name>Item 3</div><div class=desc>The third item</div></li>
<li><div class=name>Item 4</div><div class=desc>The fourth item</div></li>
<li><div class=name>Item 5</div><div class=desc>The fifth item</div></li>
</ul>
<ul id="sortable2" class="connectedSortable">
<li><div class=name>Item 1</div><div class=desc>The first item</div></li>
<li><div class=name>Item 2</div><div class=desc>The second item</div></li>
<li><div class=name>Item 3</div><div class=desc>The third item</div></li>
<li><div class=name>Item 4</div><div class=desc>The fourth item</div></li>
<li><div class=name>Item 5</div><div class=desc>The fifth item</div></li>
</ul>
#sortable1, #sortable2 {
width: 142px;
min-height: 20px;
list-style-type: none;
margin: 0;
padding: 5px 0 0 0;
float: left;
margin-right: 10px;
}
#sortable1 li, #sortable2 li {
margin: 0 5px 5px 5px;
padding: 5px;
width: 120px;
border:black solid 1px;
background-color:#123a53;
color:white;
font-size:16px;
}
Accessing Planet Data
<div id=Kanban></div>
FMLink = 'FM.link';
// This is where variables are set from the given parameters
FMTableOccurrenceName = '<?Reactor bbdev_TO( $PlanetIDField ) Reactor?>';
FunctionWhereClause = '<?Reactor bbdev_Relationship( bbdev_TO( $PlanetIDField ) ) Reactor?>';
CreationValues = '<?reactor bbdev_relationshipKeyBuilder ( $FMTableOccurrenceName ) reactor?>';
PlanetIDField = '<?Reactor bbdev_Field( $PlanetIDField ) Reactor?>';
PlanetNameField = '<?Reactor bbdev_Field( $PlanetNameField ) Reactor?>';
PlanetDescriptionField = '<?Reactor bbdev_Field( $PlanetDescriptionField ) Reactor?>';
PlanetTripNoField = '<?Reactor bbdev_Field( $PlanetTripNoField ) Reactor?>';
PlanetSortNoField = '<?Reactor bbdev_Field( $PlanetSortNoField ) Reactor?>';
Columns = '<?Reactor $Columns Reactor?>';
var PlanetsArr = new Array();
// Populate columns
function findPlanets() {
FRTB.find(
FMTableOccurrenceName + "::" + PlanetIDField,
FMTableOccurrenceName + "::" + PlanetNameField,
FMTableOccurrenceName + "::" + PlanetDescriptionField,
FMTableOccurrenceName + "::" + PlanetTripNoField,
FMTableOccurrenceName + "::" + PlanetSortNoField
).where(FunctionWhereClause).send(function(response) {
for ( var i=0; i < response.data.length; i++) {
ThisPlanetObj = new Object();
ThisPlanetObj.id = response.data[i][FMTableOccurrenceName + "::" + PlanetIDField];
ThisPlanetObj.name = response.data[i][FMTableOccurrenceName + "::" + PlanetNameField];
ThisPlanetObj.description = response.data[i][FMTableOccurrenceName + "::" + PlanetDescriptionField];
ThisPlanetObj.trip_no = response.data[i][FMTableOccurrenceName + "::" + PlanetTripNoField];
ThisPlanetObj.sort_no = response.data[i][FMTableOccurrenceName + "::" + PlanetSortNoField];
PlanetsArr.push(ThisPlanetObj);
}
buildHtml();
PlanetsArr.sort(function(a, b){
return a.sort_no > b.sort_no;
});
});
}
function buildHtml() {
ColumnsArr = Columns.split(",");
htmlString = "";
columnsIDsArray = Array();
htmlString += "<ul id='sortable_unassigned' class='connectedSortable'>";
htmlString += "<div class=Column>Unassigned</div>";
for ( var i=0; i < PlanetsArr.length; i++) {
if (PlanetsArr[i].trip_no == "") {
htmlString += "<li class=name id='" + PlanetsArr[i].id + "'><div>";
htmlString += PlanetsArr[i].name;
htmlString += "</div><div class=desc>";
htmlString += PlanetsArr[i].description;
htmlString += "</div></li>";
}
}
htmlString += "</ul>";
columnsIDsArray[0] = "#sortable_unassigned";
for ( var i=0; i < ColumnsArr.length; i++) {
htmlString += "<ul id='sortable_" + i + "' class='connectedSortable'>";
htmlString += "<div class=Column>" + ColumnsArr[i] + "</div>";
for ( var j=0; j < PlanetsArr.length; j++) {
if (PlanetsArr[j].trip_no == (i+1)) {
htmlString += "<li class=name id='" + PlanetsArr[j].id + "'><div>";
htmlString += PlanetsArr[j].name;
htmlString += "</div><div class=desc>";
htmlString += PlanetsArr[j].description;
htmlString += "</div></li>";
}
}
htmlString += "</ul>";
columnsIDsArray[i+1] = "#sortable_" + i;
}
$('#Kanban').html(htmlString);
$( columnsIDsArray.join() ).sortable({
connectWith: ".connectedSortable"
}).disableSelection();
}
$( function() {
findPlanets();
});
function findPlanets() {
FRTB.find(
FMTableOccurrenceName + "::" + PlanetIDField,
FMTableOccurrenceName + "::" + PlanetNameField,
FMTableOccurrenceName + "::" + PlanetDescriptionField,
FMTableOccurrenceName + "::" + PlanetTripNoField,
FMTableOccurrenceName + "::" + PlanetSortNoField
).where(FunctionWhereClause).send(function(response) { $('#Kanban').html("");
PlanetsArr = new Array();
for ( var i=0; i < response.data.length; i++) {
ThisPlanetObj = new Object();
ThisPlanetObj.id = response.data[i][FMTableOccurrenceName + "::" + PlanetIDField];
ThisPlanetObj.name = response.data[i][FMTableOccurrenceName + "::" + PlanetNameField];
ThisPlanetObj.description = response.data[i][FMTableOccurrenceName + "::" + PlanetDescriptionField];
ThisPlanetObj.trip_no = response.data[i][FMTableOccurrenceName + "::" + PlanetTripNoField];
ThisPlanetObj.sort_no = response.data[i][FMTableOccurrenceName + "::" + PlanetSortNoField];
PlanetsArr.push(ThisPlanetObj);
}
PlanetsArr.sort(function(a, b){
return a.sort_no > b.sort_no;
});
buildHtml();
});
}
ColumnsArr = Columns.split(",");
htmlString = "";
columnsIDsArray = Array();
htmlString += "<ul id='sortable_unassigned' class='connectedSortable'>";
htmlString += "<div class=Column>Unassigned</div>";
for ( var i=0; i < PlanetsArr.length; i++) {
if (PlanetsArr[i].trip_no == "") {
htmlString += "<li class=name id='" + PlanetsArr[i].id + "'><div>";
htmlString += PlanetsArr[i].name;
htmlString += "</div><div class=desc>";
htmlString += PlanetsArr[i].description;
htmlString += "</div></li>";
}
}
htmlString += "</ul>";
columnsIDsArray[0] = "#sortable_unassigned";
for ( var i=0; i < ColumnsArr.length; i++) {
htmlString += "<ul id='sortable_" + i + "' class='connectedSortable'>";
htmlString += "<div class=Column>" + ColumnsArr[i] + "</div>";
for ( var j=0; j < PlanetsArr.length; j++) {
if (PlanetsArr[j].trip_no == (i+1)) {
htmlString += "<li class=name id='" + PlanetsArr[j].id + "'><div>";
htmlString += PlanetsArr[j].name;
htmlString += "</div><div class=desc>";
htmlString += PlanetsArr[j].description;
htmlString += "</div></li>";
}
}
htmlString += "</ul>";
columnsIDsArray[i+1] = "#sortable_" + i;
}
$('#Kanban').html(htmlString);
$( columnsIDsArray.join() ).sortable({
connectWith: ".connectedSortable"
}).disableSelection();
Changing sort order
$( columnsIDsArray.join() ).sortable({
connectWith: ".connectedSortable"
}).disableSelection();
$( columnsIDsArray.join() ).sortable({
connectWith: ".connectedSortable",
receive: function (event,ui) {
// Do something
}
}).disableSelection();
$("#" + event.target.id)[0].childNodes[3].id;
htmlString += "<li class=name id='" + PlanetsArr[j].id + "'><div>";
$( columnsIDsArray.join() ).sortable({
connectWith: ".connectedSortable",
stop: saveLocation,
receive: saveLocation,
}).disableSelection();
function saveLocation(event,ui) {
NewTripNo = PlanetID = $("#" + event.target.id)[0].childNodes[0].innerText.replace("Trip ","");
for (var i=1; i <= $("#" + event.target.id)[0].childNodes.length; i++) {
PlanetID = $("#" + event.target.id)[0].childNodes[i].id;
FRTB.update(
[FMTableOccurrenceName + "::" + PlanetSortNoField, i],
[FMTableOccurrenceName + "::" + PlanetTripNoField, NewTripNo]
).filter(
FMTableOccurrenceName + "::" + PlanetIDField + "=" + PlanetID
).send();
}
}
Polling for changes
).where(FunctionWhereClause).send(function(response) {
).where(FunctionWhereClause).poll(pollChanges).send(function(response) {
function redrawBoard(results) {
if (OverridePoll) return;
if (results.remove.length > 0 || results.create.length > 0 || results.update.length > 0) {
findPlanets();
}
}
).where(FunctionWhereClause).poll(redrawBoard).send(function(response) {
function saveLocation(event,ui) {
var OverridePoll = true;
...}
.send(function(response) {
var OverridePoll = false;
});
...
Columns = '<?Reactor $Columns Reactor?>';
var PlanetsArr = new Array();
var OverridePoll = false;