Creating your own web-page based on JQuery + UB Server
This charter of the tutorial demonstrates how to create the client-side part for your application using JQuery + Bootstrap
and how to establish its connection with the UB server.
Our application will:
- have an authorization form
- display the list of applications that are available for the current user
- allow the user to edit responses from applications
Let's look at how our future app will look.
The Welcome page:

The Authorization form:

The list of requests to user:

Creating the web-page using a single HTML file
To create the web-page using a single HTML file you need to go through the following steps:
Prepare the project structure
- Create a
www
subdirectory in the project folder
- Create
index.html
in it
- Add the
"inetPub"
property to the "httpServer"
section in ubConfig.json
with a link to the directory
where the HTML-code is stored:
Add the necessary scripts
In the index.html
file,
- Add a link to the
lodash
module:
- Add a link to the
ub
module:
- Connect the necessary styles and scripts to work with Bootstrap and jquery-UI styles:
- Add styles and scripts for the JSGrid plug-in:
Describe the page view using Bootstrap
Create the body section for the index.html
file
as follows:
For more info about Bootstrap, see https://getbootstrap.com/
Create the <script></script>
section with the following code:
Establish a connection to UB server
Add to the <script></script>
section the following:
For more info about the connection to UB server, see the documentation
Describe authorization functionality
In order to create an authorization pop-up window and authentication verification,
add the following to the <script></script>
section:
Describe the data loading from the UB server
The following snip of code demonstrates how to load data from the UB server and how to display it using JSGrid fields.
Add it to the <script></script>
section.
var MyDateField = function (config) {
jsGrid.Field.call(this, config);
};
MyDateField.prototype = new jsGrid.Field({
itemTemplate: function (value) {
return new Date(value).toDateString();
}
})
jsGrid.fields.myDateField = MyDateField;
function objectDiff(original, modified) {
let diff = {};
let modifiedKeys = Object.keys(modified)
for (let i = 0, l = modifiedKeys.length; i < l; i++) {
let key = modifiedKeys[i];
if (original[key] !== modified[key])
diff[key] = modified[key];
}
return diff;
}
const REQ_ENTITY = 'req_reqList'
const REQ_ATTRS = ['ID', 'reqDate', 'status', 'applicantInfo', 'reqText', 'answer', 'mi_modifyDate']
function getMyRequests () {
window.$conn.Repository(REQ_ENTITY).attrs(REQ_ATTRS).select()
.then(function (data) {
$("#jsGrid").jsGrid({
width: "100%",
paging: true,
autoload: true,
editing: true,
controller: {
loadData: function () {
return data
},
updateItem: function(newData) {
var d = $.Deferred();
let original = _.find(data, {ID: newData.ID})
let diff = objectDiff(original, newData)
diff.ID = newData.ID
diff.mi_modifyDate = original.mi_modifyDate
window.$conn.update({
entity: REQ_ENTITY,
fieldList: REQ_ATTRS,
lockType: 'Temp',
execParams: diff
}).then((response) => {
let responseAsObject = UB.LocalDataStore.selectResultToArrayOfObjects(response)[0]
d.resolve(responseAsObject)
})
return d.promise();
}
},
fields: [
{name: "reqDate", type: "myDateField", width: 100, editing: false, title: 'Request date'},
{name: "status", type: "text", width: 50, editing: false, title: 'Status'},
{name: "applicantInfo", type: "text", width: 50, editing: false, title: 'Applicant info'},
{name: "reqText", type: "text", width: 150, editing: false, title: 'Text of request'},
{name: "answer", type: "text", width: 150, title: 'Answer'},
{
type: "control",
itemTemplate: function (value, item) {
var $result = $([]);
return $result.add(this._createEditButton(item));
}
}
]
});
})
}
For more info about JSGrid plugin, see http://js-grid.com/docs/
The full code of the web-page can be found here.
Building a project using webpack
Webpack is a module bundler.
Webpack takes modules with dependencies and generates static files that represent these modules.
In this section we will build the same web-page using Webpack
.
To install the webpack
run the following command:
If you have installed the webpack
globally then you need to set the system variable NODE_PATH
.
For Windows users it is looks as follows:

To configure the webpack, create a configuration file in the project root named webpack.config.js
with the following code:
In this project, the webpack
uses the babel-loader
and babel's preset-env
.
You can read more about loaders here.
To install these packages run the following commands:
In the www
folder create the src/app.js
file.
Cut the code inside the "main" <script></script>
from the index.html
file and paste it into the app.js
file.
Also, include the ub-pub
module:
The full code of app.js
must look like this:
const UB = require('@unitybase/ub-pub')
$(function () {
ubAuth()
$('#btn-login-nav').click(function () {
ubAuth()
})
$('#btn-login-j').click(function () {
ubAuth()
})
$('#btn-get-req').click(function () {
getMyRequests()
})
$('#btn-logout-nav').click(function () {
if (window.$conn) window.$conn.logout().then(function () {
getNonAuthContainers()
})
})
function customConfirm() {
return new Promise(function (resolve, reject) {
$("#popUp")
.html('<input type="text" class="form-control" placeholder="Username" id="login" style = "margin: 10px">' +
'<input type="password" class="form-control" placeholder="Password" id="pwd" style = "margin: 10px">'
)
.dialog({
resizable: true,
modal: true,
buttons: {
"Login": function () {
$(this).dialog("close");
resolve({
authSchema: 'UB',
login: document.getElementById('login').value,
password: document.getElementById('pwd').value
})
},
"Cancel": function () {
$(this).dialog("close");
reject();
}
},
focus: function () {
$('#pwd').keydown(function (eventObject) {
if (event.keyCode == 13) {
$('#popUp').dialog("close");
resolve({
authSchema: 'UB',
login: document.getElementById('login').value,
password: document.getElementById('pwd').value
})
}
});
},
})
})
}
var MyDateField = function (config) {
jsGrid.Field.call(this, config);
};
MyDateField.prototype = new jsGrid.Field({
itemTemplate: function (value) {
return new Date(value).toDateString();
}
})
jsGrid.fields.myDateField = MyDateField;
function objectDiff(original, modified) {
let diff = {};
let modifiedKeys = Object.keys(modified)
for (let i = 0, l = modifiedKeys.length; i < l; i++) {
let key = modifiedKeys[i];
if (original[key] !== modified[key])
diff[key] = modified[key];
}
return diff;
}
const REQ_ENTITY = 'req_reqList'
const REQ_ATTRS = ['ID', 'reqDate', 'status', 'applicantInfo', 'reqText', 'answer', 'mi_modifyDate']
function getMyRequests() {
window.$conn.Repository(REQ_ENTITY).attrs(REQ_ATTRS).select()
.then(function (data) {
$("#jsGrid").jsGrid({
width: "100%",
paging: true,
autoload: true,
editing: true,
controller: {
loadData: function () {
return data
},
updateItem: function (newData) {
var d = $.Deferred();
let original = _.find(data, {ID: newData.ID})
let diff = objectDiff(original, newData)
diff.ID = newData.ID
diff.mi_modifyDate = original.mi_modifyDate
window.$conn.update({
entity: REQ_ENTITY,
fieldList: REQ_ATTRS,
lockType: 'Temp',
execParams: diff
}).then((response) => {
let responseAsObject = UB.LocalDataStore.selectResultToArrayOfObjects(response)[0]
d.resolve(responseAsObject)
})
return d.promise();
}
},
fields: [
{name: "reqDate", type: "myDateField", width: 100, editing: false, title: 'Request date'},
{name: "status", type: "text", width: 50, editing: false, title: 'Status'},
{name: "applicantInfo", type: "text", width: 50, editing: false, title: 'Applicant info'},
{name: "reqText", type: "text", width: 150, editing: false, title: 'Text of request'},
{name: "answer", type: "text", width: 150, title: 'Answer'},
{
type: "control",
itemTemplate: function (value, item) {
var $result = $([]);
return $result.add(this._createEditButton(item));
}
}
]
});
})
}
function getAuthContainers() {
$("#btn-login-nav").css({"display": "none"});
$("#btn-logout-nav").css({"display": "inline"});
$("#welcome-container").css({"display": "none"});
$("#requests-container").css({"display": "inline"});
}
function getNonAuthContainers() {
$("#btn-login-nav").css({"display": "inline"});
$("#btn-logout-nav").css({"display": "none"});
$("#welcome-container").addClass("jumbotron").css({"display": "block"});
$("#requests-container").css({"display": "none"});
}
function ubAuth() {
UB.connect({
host: window.location.origin,
allowSessionPersistent: true,
onCredentialRequired: function (conn, isRepeat) {
return isRepeat
? Promise.reject(new UB.UBAbortError('invalid password or username'))
: customConfirm();
},
onAuthorizationFail: function (reason) {
$("#errDialog")
.html('<b>' + reason + '</b>')
.dialog({
resizable: true,
modal: true,
buttons: {
"Retry": function () {
$(this).dialog("close");
customConfirm();
},
"Cancel": function () {
$(this).dialog("close");
}
}
})
}
}).then(function (conn) {
window.$conn = conn
if ($('#popUp').hasClass('ui-dialog-content')) {
$('#popUp').dialog("close");
}
getAuthContainers()
getMyRequests()
})
}
});
In the console in the root of the project, run the webpack
command:
As the result the app.min.js
file will be created.
In the <head></head>
section of index.html
file,
add:
and remove:
because it is already included in app.min.js
.
Creating a -dev version of the project
To create the -dev version of the project perform the following steps:
- Create the
www/index-dev.html
file and copy the code from index.html
into it.
- Change the link:
to:
- Return the link:
- Remove the include of the
ub-pub
module from app.js
:
Now, at http://localhost:8881/index-dev.html
, the project is available for debugging.
Next step