I am developing a microservice that enables business partners to order systems for common customers:
/*
ordering.js - Terminal ordering JavaScript library.
(C) 2017 HOMEINFO - Digitale Informationssysteme GmbH
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this library. If not, see <http://www.gnu.org/licenses/>.
Maintainer: Richard Neumann <r dot neumann at homeinfo period de>
Requires:
* jquery.js
* sweetalert.js
* homeinfo.js
* his.js
*/
'use strict';
var ordering = ordering || {};
/*
Static globals.
*/
ordering._BASE_URL = 'https://top.secret.com/endpoint';
ordering._ORDERS_ENDPOINT = ordering._BASE_URL + '/order';
ordering._CUSTOMERS_ENDPOINT = ordering._BASE_URL + '/customers';
ordering._CLASSES_ENDPOINT = ordering._BASE_URL + '/classes';
ordering._OSS_ENDPOINT = ordering._BASE_URL + '/oss';
/*
Runtime globals.
*/
ordering.orders = ordering.orders || [];
ordering.customers = ordering.customers || [];
ordering.classes = ordering.classes || [];
ordering.oss = ordering.oss || [];
/*
Displays an error using sweetalert.
*/
ordering.error = function (title, text, type) {
return function () {
swal({
title: title,
text: text,
type: type || 'error'
});
};
};
/*
Queries orders from the API.
*/
ordering._getOrders = function () {
return his.auth.get(ordering._ORDERS_ENDPOINT).then(
function (orders) {
ordering.orders = orders;
},
ordering.error('Fehler.', 'Konnte verfügbare Bestellungen nicht abfragen.')
);
};
/*
Queries customers from the API.
*/
ordering._getCustomers = function () {
return his.auth.get(ordering._CUSTOMERS_ENDPOINT).then(
function (customers) {
ordering.customers = customers;
},
ordering.error('Fehler.', 'Konnte verfügbare Kunden nicht abfragen.')
);
};
/*
Queries classes from the API.
*/
ordering._getClasses = function () {
return his.auth.get(ordering._CLASSES_ENDPOINT).then(
function (classes) {
ordering.classes = classes;
},
ordering.error('Fehler.', 'Konnte verfügbare Terminal-Klassen nicht abfragen.')
);
};
/*
Queries classes from the API.
*/
ordering._getOSs = function () {
return his.auth.get(ordering._OSS_ENDPOINT).then(
function (oss) {
ordering.oss = oss;
},
ordering.error('Fehler.', 'Konnte verfügbare Betriebssysteme nicht abfragen.')
);
};
/*
Performs a HIS login.
*/
ordering._login = function () {
var queryString = new homeinfo.QueryString();
return his.session.login(queryString.userName, queryString.passwd);
};
/*
Initializes the page.
*/
ordering.init = function () {
ordering._login().then(
ordering._getData().then(
ordering._initPage
)
);
};
/*
Submit form.
*/
ordering._submitForm = function (event) {
event.preventDefault(); // Avoid to execute the actual submit of the form.
his.auth.post(ordering._ORDERS_ENDPOINT, jQuery('#orders').serialize()).then(ordering._resetForm);
};
/*
Resets the form.
*/
ordering._resetForm = function () {
document.getElementById('orders').reset();
ordering.init();
};
/*
Initialization function.
*/
ordering._getData = function () {
var getOrders = ordering._getOrders();
var getCustomers = ordering._getCustomers();
var getClasses = ordering._getClasses();
var getOSs = ordering._getOSs();
return Promise.all([getOrders, getCustomers, getClasses, getOSs]);
};
/*
Refreshes the orders list.
*/
ordering._renderList = function () {
var tableContainer = document.getElementById('tableContainer');
tableContainer.innerHTML = '';
tableContainer.appendChild(ordering._dom.list());
};
/*
Renders the orders input.
*/
ordering._renderOrders = function () {
var formContainer = document.getElementById('formContainer');
formContainer.innerHTML = '';
formContainer.appendChild(ordering._dom.orders());
};
/*
Initializes the page.
*/
ordering._initPage = function () {
ordering._renderList();
ordering._renderOrders();
jQuery('#orders').submit(ordering._submitForm);
};
/*
Deletes the respective order.
*/
ordering._deleteOrder = function (id) {
return his.auth.delete(ordering._ORDERS_ENDPOINT + '/' + id).then(ordering._getData).then(ordering._renderList);
};
/*
Adds an order.
*/
ordering._addOrderForm = function () {
var orderForms = document.getElementById('orderForms');
var order = ordering._dom.order(true);
orderForms.appendChild(order);
};
/*
Deletes the respective order form.
*/
ordering._deleteOrderForm = function (index) {
var orderForms = document.getElementById('orderForms');
var order = document.getElementById('order_' + index);
orderForms.removeChild(order);
};
/*
DOM model.
*/
ordering._dom = ordering._dom || {};
ordering._dom.COLUMNS = [
'Konto', 'Bestelldatum', 'Bearbeitungsstatus', 'Kunde', 'Klasse', 'Betriebssystem', 'Adresse', 'Anmerkung',
'Stornieren'];
/*
ID of orders form.
*/
ordering._dom.ORDERS = 0;
/*
Builds an order set.
*/
ordering._dom.orders = function () {
var form = document.createElement('form');
form.setAttribute('id', 'orders');
var orderForms = document.createElement('div');
orderForms.setAttribute('id', 'orderForms');
orderForms.setAttribute('class', 'row row-center');
var firstOrder = ordering._dom.order();
orderForms.appendChild(firstOrder);
form.appendChild(orderForms);
form.appendChild(ordering._dom.buttonAddOrderForm());
form.appendChild(document.createTextNode(' '));
form.appendChild(ordering._dom.submit());
return form;
};
/*
Creates a button to add an order form input for a further terminal.
*/
ordering._dom.buttonAddOrderForm = function () {
var button = document.createElement('button');
button.setAttribute('class', 'btn btn-success');
button.setAttribute('onclick', 'ordering._addOrderForm();');
button.textContent = 'Weiteres Terminal hinzufügen.';
return button;
};
/*
Creates a button to delete the respective oder inputs.
*/
ordering._dom.buttonDeleteOrderForm = function (index) {
var buttonDeleteOrderForm = document.createElement('button');
buttonDeleteOrderForm.setAttribute('onclick', 'ordering._deleteOrderForm(' + index + ');');
buttonDeleteOrderForm.setAttribute('class', 'btn btn-danger');
buttonDeleteOrderForm.textContent = 'X';
return buttonDeleteOrderForm;
};
/*
Creates a button to delete the respective order.
*/
ordering._dom.buttonDeleteOrder = function (id) {
var button = document.createElement('button');
button.setAttribute('class', 'btn btn-danger');
button.setAttribute('onclick', 'ordering._deleteOrder(' + id + ');');
button.textContent = 'X';
return button;
};
/*
Creates the title for the terminal order.
*/
ordering._dom.caption = function (index, additional) {
var caption = document.createElement('legend');
var textNode = document.createTextNode('Terminal ');
caption.appendChild(textNode);
if (additional) {
caption.appendChild(ordering._dom.buttonDeleteOrderForm(index));
}
return caption;
};
/*
Builds a single order.
*/
ordering._dom.order = function (additional) {
if (additional == null) {
additional = false;
}
var index = ordering._dom.ORDERS;
ordering._dom.ORDERS += 1;
var order = document.createElement('fieldset');
order.setAttribute('id', 'order_' + index);
order.setAttribute('class', 'row');
var caption = ordering._dom.caption(index, additional);
order.appendChild(caption);
var columnSelects = document.createElement('div');
columnSelects.setAttribute('class', 'col-md-6');
var customerSelect = ordering._dom.customerSelect(index);
columnSelects.appendChild(customerSelect);
var classSelect = ordering._dom.classSelect(index);
columnSelects.appendChild(classSelect);
var osSelect = ordering._dom.osSelect(index);
columnSelects.appendChild(osSelect);
var columnAddress = document.createElement('div');
columnAddress.setAttribute('class', 'col-md-6');
var address = ordering._dom.address(index);
columnAddress.appendChild(address);
order.append(columnSelects);
order.append(columnAddress);
return order;
};
/*
Builds a default option for a dropdown list.
*/
ordering._dom.defaultOption = function (text) {
var defaultOption = document.createElement('option');
var attributeSelected = document.createAttribute('selected');
defaultOption.setAttributeNode(attributeSelected);
var attributeDisabled = document.createAttribute('disabled');
defaultOption.setAttributeNode(attributeDisabled);
defaultOption.textContent = text;
return defaultOption;
};
/*
Builds the customer selection dropdown menu.
*/
ordering._dom.customerSelect = function (index) {
var select = document.createElement('select');
select.setAttribute('required', true);
select.setAttribute('name', 'customer_' + index);
select.setAttribute('class', 'form-control');
var defaultOption = ordering._dom.defaultOption('Kunde*');
select.appendChild(defaultOption);
for (var i = 0; i < ordering.customers.length; i++) {
var customer = ordering.customers[i];
var option = document.createElement('option');
option.setAttribute('value', customer.id);
option.textContent = customer.company.name;
select.appendChild(option);
}
return select;
};
/*
Builds the class selection dropdown menu.
*/
ordering._dom.classSelect = function (index) {
var select = document.createElement('select');
select.setAttribute('required', true);
select.setAttribute('name', 'class_' + index);
select.setAttribute('class', 'form-control');
var defaultOption = ordering._dom.defaultOption('Klasse*');
select.appendChild(defaultOption);
for (var i = 0; i < ordering.classes.length; i++) {
var class_ = ordering.classes[i];
var option = document.createElement('option');
option.setAttribute('value', class_.id);
option.textContent = class_.full_name;
select.appendChild(option);
}
return select;
};
/*
Builds the operating system selection dropdown menu.
*/
ordering._dom.osSelect = function (index) {
var select = document.createElement('select');
select.setAttribute('required', true);
select.setAttribute('name', 'os_' + index);
select.setAttribute('class', 'form-control');
var defaultOption = ordering._dom.defaultOption('Betriebssystem*');
select.appendChild(defaultOption);
for (var i = 0; i < ordering.oss.length; i++) {
var os = ordering.oss[i];
var option = document.createElement('option');
option.setAttribute('value', os.id);
option.textContent = os.name + ' ' + os.version;
select.appendChild(option);
}
return select;
};
/*
Builds the address input fields.
*/
ordering._dom.address = function (index) {
var address = document.createElement('fieldset');
address.setAttribute('class', 'form-group');
var street = document.createElement('input');
street.setAttribute('type', 'text');
street.setAttribute('required', true);
street.setAttribute('name', 'street_' + index);
street.setAttribute('placeholder', 'Straße*');
address.appendChild(street);
var houseNumber = document.createElement('input');
houseNumber.setAttribute('type', 'text');
houseNumber.setAttribute('required', true);
houseNumber.setAttribute('name', 'houseNumber_' + index);
houseNumber.setAttribute('placeholder', 'Hausnummer*');
address.appendChild(houseNumber);
var zipCode = document.createElement('input');
zipCode.setAttribute('type', 'text');
zipCode.setAttribute('required', true);
zipCode.setAttribute('name', 'zipCode_' + index);
zipCode.setAttribute('placeholder', 'PLZ*');
address.appendChild(zipCode);
var city = document.createElement('input');
city.setAttribute('type', 'text');
city.setAttribute('required', true);
city.setAttribute('name', 'city_' + index);
city.setAttribute('placeholder', 'Ort*');
address.appendChild(city);
var annotation = document.createElement('input');
annotation.setAttribute('type', 'text');
annotation.setAttribute('name', 'annotation_' + index);
annotation.setAttribute('placeholder', 'Anmerkung');
address.appendChild(annotation);
return address;
};
/*
Builds a submit button.
*/
ordering._dom.submit = function () {
var submit = document.createElement('input');
submit.setAttribute('type', 'submit');
submit.setAttribute('value', 'Kostenpflichtig bestellen.');
submit.setAttribute('class', 'btn btn-primary');
return submit;
};
/*
Builds the list of existing orders.
*/
ordering._dom.list = function () {
var table = document.createElement('table');
table.setAttribute('id', 'list');
table.setAttribute('class', 'table table-hover');
var thead = document.createElement('thead');
var tr = document.createElement('tr');
var th;
for (var i = 0; i < ordering._dom.COLUMNS.length; i++) {
th = document.createElement('th');
th.setAttribute('scope', 'col');
th.textContent = ordering._dom.COLUMNS[i];
tr.appendChild(th);
}
thead.appendChild(tr);
var tbody = document.createElement('tbody');
var empty = true;
for (var attr in ordering.orders) {
if (ordering.orders.hasOwnProperty(attr)) {
empty = false;
tbody.appendChild(ordering._dom.listItem(ordering.orders[attr]));
}
}
if (empty) {
var h2 = document.createElement('h2');
h2.setAttribute('align', 'center');
h2.textContent = 'Keine Bestellungen vorhanden.';
return h2;
}
table.appendChild(thead);
table.appendChild(tbody);
return table;
};
/*
Builds the list items for each existing order.
*/
ordering._dom.listItem = function (order) {
var row = document.createElement('tr');
var columnAccount = document.createElement('td');
columnAccount.textContent = order.account.name;
row.appendChild(columnAccount);
var columnIssued = document.createElement('td');
columnIssued.textContent = order.issued;
row.appendChild(columnIssued);
var columnAccepted = document.createElement('td');
var notProcessedYet = 'Noch nicht bearbeitet.';
switch (order.accepted) {
case null:
columnAccepted.textContent = notProcessedYet;
break;
case undefined:
columnAccepted.textContent = notProcessedYet;
break;
case true:
columnAccepted.textContent = 'Angelegt.';
break;
case false:
columnAccepted.textContent = 'Auftrag abgewiesen.';
break;
}
row.appendChild(columnAccepted);
var columnCustomer = document.createElement('td');
columnCustomer.textContent = order.customer.company.name + ' (' + order.customer.id + ')';
row.appendChild(columnCustomer);
var columnClass = document.createElement('td');
columnClass.textContent = order.class_.name;
row.appendChild(columnClass);
var columnOs = document.createElement('td');
columnOs.textContent = order.os.name + ' ' + order.os.version;
row.appendChild(columnOs);
var columnAddress = document.createElement('td');
var address = order.address;
columnAddress.textContent = address.street + ' ' + address.house_number + ', ' + address.zip_code + ' ' + address.city;
row.appendChild(columnAddress);
var columnAnnotation = document.createElement('td');
columnAnnotation.textContent = order.annotation || '-';
row.appendChild(columnAnnotation);
var columnDelete = document.createElement('td');
columnDelete.appendChild(ordering._dom.buttonDeleteOrder(order.id));
row.appendChild(columnDelete);
return row;
};
jQuery(document).ready(ordering.init);
The corresponsing HTML document is:
<!DOCTYPE HTML>
<head>
<meta charset="utf-8"/>
<title>Terminal Bestellung</title>
<link rel="stylesheet" href="https://libraries.homeinfo.de/bootstrap/latest/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://libraries.homeinfo.de/sweetalert/dist/sweetalert.css">
<script src="https://libraries.homeinfo.de/jquery/jquery-latest.min.js"></script>
<script src="https://libraries.homeinfo.de/bootstrap/latest/js/bootstrap.min.js"></script>
<script src="https://libraries.homeinfo.de/sweetalert/dist/sweetalert.min.js"></script>
<script src="https://javascript.homeinfo.de/homeinfo.min.js"></script>
<script src="https://javascript.homeinfo.de/his/his.js"></script>
<script src="https://javascript.homeinfo.de/his/session.js"></script>
<script src="ordering.js"></script>
</head>
<body>
<h1 align="center">Ihre Bestellungen bei HOMEINFO</h1>
<br>
<div class="container">
<div id="tableContainer" class="row"></div>
<br>
<div id="formContainer" class="row"></div>
</div>
</body>
I'd like to have general feedback especially on the JavaScript code.