Push changes to frontend

This commit is contained in:
Thilina Hasantha
2019-02-03 13:57:59 +01:00
parent 96b0ad8496
commit 067af27b76
139 changed files with 69635 additions and 12 deletions
+2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+4
View File
@@ -0,0 +1,4 @@
import { AttendanceAdapter, AttendanceStatusAdapter } from './lib';
window.AttendanceAdapter = AttendanceAdapter;
window.AttendanceStatusAdapter = AttendanceStatusAdapter;
+289
View File
@@ -0,0 +1,289 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
import FormValidation from '../../../api/FormValidation';
class AttendanceAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.photoAttendance = false;
}
getDataMapping() {
return [
'id',
'employee',
'in_time',
'out_time',
'note',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Time-In' },
{ sTitle: 'Time-Out' },
{ sTitle: 'Note' },
];
}
getFormFields() {
return [
['employee', {
label: 'Employee', type: 'select2', 'allow-null': false, 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
['id', { label: 'ID', type: 'hidden' }],
['in_time', { label: 'Time-In', type: 'datetime' }],
['out_time', { label: 'Time-Out', type: 'datetime', validation: 'none' }],
['note', { label: 'Note', type: 'textarea', validation: 'none' }],
];
}
getFilters() {
return [
['employee', {
label: 'Employee', type: 'select2', 'allow-null': false, 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
];
}
setPhotoAttendance(val) {
this.photoAttendance = parseInt(val, 10);
}
getCustomTableParams() {
const that = this;
const dataTableParams = {
aoColumnDefs: [
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 2);
},
aTargets: [2],
},
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 3);
},
aTargets: [3],
},
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 4);
},
aTargets: [4],
},
{
fnRender: that.getActionButtons,
aTargets: [that.getDataMapping().length],
},
],
};
return dataTableParams;
}
preProcessRemoteTableData(data, cell, id) {
if (id === 2) {
if (cell === '0000-00-00 00:00:00' || cell === '' || cell === undefined || cell == null) {
return '';
}
return Date.parse(cell).toString('yyyy MMM d <b>HH:mm</b>');
} if (id === 3) {
if (cell === '0000-00-00 00:00:00' || cell === '' || cell === undefined || cell == null) {
return '';
}
return Date.parse(cell).toString('MMM d <b>HH:mm</b>');
} if (id === 4) {
if (cell !== undefined && cell !== null) {
if (cell.length > 10) {
return `${cell.substring(0, 10)}..`;
}
}
return cell;
}
}
save() {
const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' });
if (validator.checkValues()) {
const params = validator.getFormParameters();
const msg = this.doCustomValidation(params);
if (msg == null) {
const id = $(`#${this.getTableName()}_submit #id`).val();
if (id != null && id !== undefined && id !== '') {
params.id = id;
}
const reqJson = JSON.stringify(params);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'saveSuccessCallback';
callBackData.callBackFail = 'saveFailCallback';
this.customAction('savePunch', 'admin=attendance', reqJson, callBackData);
} else {
const label = $(`#${this.getTableName()}Form .label`);
label.html(msg);
label.show();
}
}
}
saveSuccessCallback(callBackData) {
this.get(callBackData);
}
saveFailCallback(callBackData) {
this.showMessage('Error saving attendance entry', callBackData);
}
isSubProfileTable() {
return this.user.user_level !== 'Admin';
}
showPunchImages(id) {
const reqJson = JSON.stringify({ id });
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getImagesSuccessCallback';
callBackData.callBackFail = 'getImagesFailCallback';
this.customAction('getImages', 'admin=attendance', reqJson, callBackData);
}
getImagesSuccessCallback(callBackData) {
$('#attendancePhotoModel').modal('show');
$('#attendnaceCanvasEmp').html(callBackData.employee_Name);
if (callBackData.in_time) {
$('#attendnaceCanvasPunchInTime').html(Date.parse(callBackData.in_time).toString('yyyy MMM d <b>HH:mm</b>'));
}
if (callBackData.image_in) {
const myCanvas = document.getElementById('attendnaceCanvasIn');
const ctx = myCanvas.getContext('2d');
const img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0); // Or at whatever offset you like
};
img.src = callBackData.image_in;
}
if (callBackData.out_time) {
$('#attendnaceCanvasPunchOutTime').html(Date.parse(callBackData.out_time).toString('yyyy MMM d <b>HH:mm</b>'));
}
if (callBackData.image_out) {
const myCanvas = document.getElementById('attendnaceCanvasOut');
const ctx = myCanvas.getContext('2d');
const img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0); // Or at whatever offset you like
};
img.src = callBackData.image_out;
}
}
getImagesFailCallback(callBackData) {
this.showMessage('Error', callBackData);
}
getActionButtonsHtml(id, data) {
const editButton = '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img>';
const deleteButton = '<img class="tableActionButton" src="_BASE_images/delete.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Delete" onclick="modJs.deleteRow(_id_);return false;"></img>';
const photoButton = '<img class="tableActionButton" src="_BASE_images/cam.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Show Photo" onclick="modJs.showPunchImages(_id_);return false;"></img>';
let html;
if (this.photoAttendance === 1) {
html = '<div style="width:80px;">_edit__delete__photo_</div>';
} else {
html = '<div style="width:80px;">_edit__delete_</div>';
}
html = html.replace('_photo_', photoButton);
if (this.showDelete) {
html = html.replace('_delete_', deleteButton);
} else {
html = html.replace('_delete_', '');
}
if (this.showEdit) {
html = html.replace('_edit_', editButton);
} else {
html = html.replace('_edit_', '');
}
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
}
/*
Attendance Status
*/
class AttendanceStatusAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'employee',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Clocked In Status' },
];
}
getFormFields() {
return [
];
}
getFilters() {
return [
['employee', {
label: 'Employee', type: 'select2', 'allow-null': false, 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
];
}
getActionButtonsHtml(id, data) {
let html = '<div class="online-button-_COLOR_"></div>';
html = html.replace(/_BASE_/g, this.baseUrl);
if (data[2] == 'Not Clocked In') {
html = html.replace(/_COLOR_/g, 'gray');
} else if (data[2] == 'Clocked Out') {
html = html.replace(/_COLOR_/g, 'yellow');
} else if (data[2] == 'Clocked In') {
html = html.replace(/_COLOR_/g, 'green');
}
return html;
}
isSubProfileTable() {
return this.user.user_level !== 'Admin';
}
}
module.exports = { AttendanceAdapter, AttendanceStatusAdapter };
+4
View File
@@ -0,0 +1,4 @@
import { CompanyStructureAdapter, CompanyGraphAdapter } from './lib';
window.CompanyStructureAdapter = CompanyStructureAdapter;
window.CompanyGraphAdapter = CompanyGraphAdapter;
+311
View File
@@ -0,0 +1,311 @@
/* eslint-disable prefer-destructuring */
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/* global d3, nv */
import AdapterBase from '../../../api/AdapterBase';
class CompanyStructureAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'title',
'address',
'type',
'country',
'timezone',
'parent',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Address', bSortable: false },
{ sTitle: 'Type' },
{ sTitle: 'Country', sClass: 'center' },
{ sTitle: 'Time Zone' },
{ sTitle: 'Parent Structure' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden', validation: '' }],
['title', { label: 'Name', type: 'text', validation: '' }],
['description', { label: 'Details', type: 'textarea', validation: '' }],
['address', { label: 'Address', type: 'textarea', validation: 'none' }],
['type', { label: 'Type', type: 'select', source: [['Company', 'Company'], ['Head Office', 'Head Office'], ['Regional Office', 'Regional Office'], ['Department', 'Department'], ['Unit', 'Unit'], ['Sub Unit', 'Sub Unit'], ['Other', 'Other']] }],
['country', { label: 'Country', type: 'select2', 'remote-source': ['Country', 'code', 'name'] }],
['timezone', {
label: 'Time Zone', type: 'select2', 'allow-null': false, 'remote-source': ['Timezone', 'name', 'details'],
}],
['parent', {
label: 'Parent Structure', type: 'select', 'allow-null': true, 'remote-source': ['CompanyStructure', 'id', 'title'],
}],
['heads', {
label: 'Heads', type: 'select2multi', 'allow-null': true, 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
];
}
postRenderForm(object, $tempDomObj) {
if (object === undefined
|| object === null
|| object.id === null
|| object.id === undefined || object.id === ''
) {
$tempDomObj.find('#field_heads').hide();
}
}
}
/*
* Company Graph
*/
class CompanyGraphAdapter extends CompanyStructureAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.nodeIdCounter = 0;
}
convertToTree(data) {
const ice = {};
ice.id = -1;
ice.title = '';
ice.name = '';
ice.children = [];
let parent = null;
const added = {};
for (let i = 0; i < data.length; i++) {
data[i].name = data[i].title;
if (data[i].parent != null && data[i].parent !== undefined) {
parent = this.findParent(data, data[i].parent);
if (parent != null) {
if (parent.children === undefined || parent.children == null) {
parent.children = [];
}
parent.children.push(data[i]);
}
}
}
for (let i = 0; i < data.length; i++) {
if (data[i].parent == null || data[i].parent === undefined) {
ice.children.push(data[i]);
}
}
return ice;
}
findParent(data, parent) {
for (let i = 0; i < data.length; i++) {
if (data[i].title === parent || data[i].title === parent) {
return data[i];
}
}
return null;
}
createTable(elementId) {
$('#tabPageCompanyGraph').html('');
const that = this;
const sourceData = this.sourceData;
// this.fixCyclicParent(sourceData);
const treeData = this.convertToTree(sourceData);
const m = [20, 120, 20, 120];
const w = 5000 - m[1] - m[3];
const h = 1000 - m[0] - m[2];
const tree = d3.layout.tree()
.size([h, w]);
this.diagonal = d3.svg.diagonal()
.projection(d => [d.y, d.x]);
this.vis = d3.select('#tabPageCompanyGraph').append('svg:svg')
.attr('width', w + m[1] + m[3])
.attr('height', h + m[0] + m[2])
.append('svg:g')
.attr('transform', `translate(${m[3]},${m[0]})`);
const root = treeData;
root.x0 = h / 2;
root.y0 = 0;
function toggleAll(d) {
if (d.children) {
console.log(d.name);
d.children.forEach(toggleAll);
that.toggle(d);
}
}
this.update(root, tree, root);
}
update(source, tree, root) {
const that = this;
const duration = d3.event && d3.event.altKey ? 5000 : 500;
// Compute the new tree layout.
const nodes = tree.nodes(root).reverse();
// Normalize for fixed-depth.
nodes.forEach((d) => { d.y = d.depth * 180; });
// Update the nodes
const node = that.vis.selectAll('g.node')
.data(nodes, d => d.id || (d.id = ++that.nodeIdCounter));
// Enter any new nodes at the parent's previous position.
const nodeEnter = node.enter().append('svg:g')
.attr('class', 'node')
.attr('transform', d => `translate(${source.y0},${source.x0})`)
.on('click', (d) => { that.toggle(d); that.update(d, tree, root); });
nodeEnter.append('svg:circle')
.attr('r', 1e-6)
.style('fill', d => (d._children ? 'lightsteelblue' : '#fff'));
nodeEnter.append('svg:text')
.attr('x', d => (d.children || d._children ? -10 : 10))
.attr('dy', '.35em')
.attr('text-anchor', d => (d.children || d._children ? 'end' : 'start'))
.text(d => d.name)
.style('fill-opacity', 1e-6);
// Transition nodes to their new position.
const nodeUpdate = node.transition()
.duration(duration)
.attr('transform', d => `translate(${d.y},${d.x})`);
nodeUpdate.select('circle')
.attr('r', 4.5)
.style('fill', d => (d._children ? 'lightsteelblue' : '#fff'));
nodeUpdate.select('text')
.style('fill-opacity', 1);
// Transition exiting nodes to the parent's new position.
const nodeExit = node.exit().transition()
.duration(duration)
.attr('transform', d => `translate(${source.y},${source.x})`)
.remove();
nodeExit.select('circle')
.attr('r', 1e-6);
nodeExit.select('text')
.style('fill-opacity', 1e-6);
// Update the links
const link = that.vis.selectAll('path.link')
.data(tree.links(nodes), d => d.target.id);
// Enter any new links at the parent's previous position.
link.enter().insert('svg:path', 'g')
.attr('class', 'link')
.attr('d', (d) => {
const o = { x: source.x0, y: source.y0 };
return that.diagonal({ source: o, target: o });
})
.transition()
.duration(duration)
.attr('d', that.diagonal);
// Transition links to their new position.
link.transition()
.duration(duration)
.attr('d', that.diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr('d', (d) => {
const o = { x: source.x, y: source.y };
return that.diagonal({ source: o, target: o });
})
.remove();
// Stash the old positions for transition.
nodes.forEach((d) => {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children.
toggle(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
}
getSourceDataById(id) {
for (let i = 0; i < this.sourceData.length; i++) {
if (this.sourceData[i].id == id) {
return this.sourceData[i];
}
}
return null;
}
fixCyclicParent(sourceData) {
let errorMsg = '';
for (let i = 0; i < sourceData.length; i++) {
const obj = sourceData[i];
let curObj = obj;
const parentIdArr = {};
parentIdArr[curObj.id] = 1;
while (curObj.parent != null && curObj.parent != undefined) {
const parent = this.getSourceDataById(curObj.parent);
if (parent == null) {
break;
} else if (parentIdArr[parent.id] == 1) {
errorMsg = `${obj.title}'s parent structure set to ${parent.title}<br/>`;
obj.parent = null;
break;
}
parentIdArr[parent.id] = 1;
curObj = parent;
}
}
if (errorMsg !== '') {
this.showMessage('Company Structure is having a cyclic dependency', `We found a cyclic dependency due to following reasons:<br/>${errorMsg}`);
return false;
}
return true;
}
getHelpLink() {
return 'https://thilinah.gitbooks.io/icehrm-guide/content/employee-information-setup.html';
}
}
module.exports = { CompanyStructureAdapter, CompanyGraphAdapter };
+3
View File
@@ -0,0 +1,3 @@
import { DashboardAdapter } from './lib';
window.DashboardAdapter = DashboardAdapter;
+56
View File
@@ -0,0 +1,56 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
class DashboardAdapter extends AdapterBase {
getDataMapping() {
return [];
}
getHeaders() {
return [];
}
getFormFields() {
return [];
}
get(callBackData) {
}
getInitData() {
const that = this;
const object = {};
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getInitDataSuccessCallBack';
callBackData.callBackFail = 'getInitDataFailCallBack';
this.customAction('getInitData', 'admin=dashboard', reqJson, callBackData);
}
getInitDataSuccessCallBack(data) {
$('#numberOfEmployees').html(`${data.numberOfEmployees} Employees`);
$('#numberOfCompanyStuctures').html(`${data.numberOfCompanyStuctures} Departments`);
$('#numberOfUsers').html(`${data.numberOfUsers} Users`);
$('#numberOfProjects').html(`${data.numberOfProjects} Active Projects`);
$('#numberOfAttendanceLastWeek').html(`${data.numberOfAttendanceLastWeek} Entries Last Week`);
$('#numberOfLeaves').html(`${data.numberOfLeaves} Upcoming`);
$('#numberOfTimeEntries').html(data.numberOfTimeEntries);
$('#numberOfCandidates').html(`${data.numberOfCandidates} Candidates`);
$('#numberOfJobs').html(`${data.numberOfJobs} Active`);
$('#numberOfCourses').html(`${data.numberOfCourses} Courses`);
}
getInitDataFailCallBack(callBackData) {
}
}
module.exports = { DashboardAdapter };
+4
View File
@@ -0,0 +1,4 @@
import { DataImportAdapter, DataImportFileAdapter } from './lib';
window.DataImportAdapter = DataImportAdapter;
window.DataImportFileAdapter = DataImportFileAdapter;
+185
View File
@@ -0,0 +1,185 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/* global dependOnField */
import AdapterBase from '../../../api/AdapterBase';
/**
* DataImportAdapter
*/
class DataImportAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'dataType',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Data Type' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['dataType', { label: 'Data Type', type: 'text', validation: '' }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
['columns', {
label: 'Columns',
type: 'datagroup',
form: [
['name', { label: 'Name', type: 'text', validation: '' }],
['title', { label: 'Filed Title', type: 'text', validation: 'none' }],
['type', {
label: 'Type', type: 'select', sort: 'none', source: [['Normal', 'Normal'], ['Reference', 'Reference'], ['Attached', 'Attached']],
}],
['dependOn', {
label: 'Depends On',
type: 'select',
'allow-null': true,
'null-label': 'N/A',
source: [['EmergencyContact', 'Emergency Contacts'], ['Ethnicity', 'Ethnicity'], ['Nationality', 'Nationality'], ['JobTitle', 'JobTitle'], ['PayFrequency', 'PayFrequency'], ['PayGrade', 'PayGrade'], ['EmploymentStatus', 'EmploymentStatus'], ['CompanyStructure', 'CompanyStructure'], ['Employee', 'Employee']],
}],
['dependOnField', { label: 'Depends On Field', type: 'text', validation: 'none' }],
['isKeyField', {
label: 'Is Key Field', type: 'select', validation: '', source: [['No', 'No'], ['Yes', 'Yes']],
}],
['idField', {
label: 'Is ID Field', type: 'select', validation: '', source: [['No', 'No'], ['Yes', 'Yes']],
}],
],
html: '<div id="#_id_#" class="panel panel-default"><div class="panel-heading"><b>#_name_#</b> #_delete_##_edit_#</div><div class="panel-body"><b>Header Title: </b>#_title_#<br/><span style="color:#999;font-size:11px;font-weight:bold">Type: #_type_# </span><br/></div></div>',
validation: 'none',
'custom-validate-function': function (data) {
const res = {};
res.params = data;
res.valid = true;
if (data.type === 'Reference') {
if (data.dependOn === 'NULL') {
res.message = 'If the type is Reference this field should referring another table';
res.valid = false;
} else if (dependOnField === null || dependOnField === undefined) {
res.message = "If the type is Reference then 'Depends On Field' can not be empty";
res.valid = false;
}
}
return res;
},
}],
];
}
}
/**
* DataImportFileAdapter
*/
class DataImportFileAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'data_import_definition',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Data Import Definition' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['data_import_definition', { label: 'Data Import Definitions', type: 'select', 'remote-source': ['DataImport', 'id', 'name'] }],
['file', {
label: 'File to Import', type: 'fileupload', validation: '', filetypes: 'csv,txt',
}],
['details', { label: 'Last Export Result', type: 'textarea', validation: 'none' }],
];
}
getActionButtonsHtml(id, data) {
const editButton = '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img>';
const processButton = '<img class="tableActionButton" src="_BASE_images/run.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Process" onclick="modJs.process(_id_,\'_status_\');return false;"></img>';
const deleteButton = '<img class="tableActionButton" src="_BASE_images/delete.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Delete" onclick="modJs.deleteRow(_id_);return false;"></img>';
const cloneButton = '<img class="tableActionButton" src="_BASE_images/clone.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Copy" onclick="modJs.copyRow(_id_);return false;"></img>';
let html = '<div style="width:120px;">_edit__process__clone__delete_</div>';
if (this.showAddNew) {
html = html.replace('_clone_', cloneButton);
} else {
html = html.replace('_clone_', '');
}
if (this.showDelete) {
html = html.replace('_delete_', deleteButton);
} else {
html = html.replace('_delete_', '');
}
if (this.showEdit) {
html = html.replace('_edit_', editButton);
} else {
html = html.replace('_edit_', '');
}
if (data[3] === 'Not Processed') {
html = html.replace('_process_', processButton);
} else {
html = html.replace('_process_', '');
}
html = html.replace(/_id_/g, id);
html = html.replace(/_status_/g, data[6]);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
process(id) {
const that = this;
const object = { id };
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'processSuccessCallBack';
callBackData.callBackFail = 'processFailCallBack';
this.customAction('processDataFile', 'admin=data', reqJson, callBackData);
}
processSuccessCallBack(callBackData) {
this.showMessage('Success', 'File imported successfully.');
}
processFailCallBack(callBackData) {
this.showMessage('Error', `File import unsuccessful. Result:${callBackData}`);
}
}
module.exports = { DataImportAdapter, DataImportFileAdapter };
+39
View File
@@ -0,0 +1,39 @@
import {
EmployeeAdapter,
TerminatedEmployeeAdapter,
ArchivedEmployeeAdapter,
EmployeeSkillAdapter,
EmployeeEducationAdapter,
EmployeeCertificationAdapter,
EmployeeLanguageAdapter,
EmployeeDependentAdapter,
EmergencyContactAdapter,
EmployeeImmigrationAdapter,
EmployeeSubSkillsAdapter,
EmployeeSubEducationAdapter,
EmployeeSubCertificationAdapter,
EmployeeSubLanguageAdapter,
EmployeeSubDependentAdapter,
EmployeeSubEmergencyContactAdapter,
EmployeeSubDocumentAdapter,
EmployeeDocumentAdapter,
} from './lib';
window.EmployeeAdapter = EmployeeAdapter;
window.TerminatedEmployeeAdapter = TerminatedEmployeeAdapter;
window.ArchivedEmployeeAdapter = ArchivedEmployeeAdapter;
window.EmployeeSkillAdapter = EmployeeSkillAdapter;
window.EmployeeEducationAdapter = EmployeeEducationAdapter;
window.EmployeeCertificationAdapter = EmployeeCertificationAdapter;
window.EmployeeLanguageAdapter = EmployeeLanguageAdapter;
window.EmployeeDependentAdapter = EmployeeDependentAdapter;
window.EmergencyContactAdapter = EmergencyContactAdapter;
window.EmployeeImmigrationAdapter = EmployeeImmigrationAdapter;
window.EmployeeSubSkillsAdapter = EmployeeSubSkillsAdapter;
window.EmployeeSubEducationAdapter = EmployeeSubEducationAdapter;
window.EmployeeSubCertificationAdapter = EmployeeSubCertificationAdapter;
window.EmployeeSubLanguageAdapter = EmployeeSubLanguageAdapter;
window.EmployeeSubDependentAdapter = EmployeeSubDependentAdapter;
window.EmployeeSubEmergencyContactAdapter = EmployeeSubEmergencyContactAdapter;
window.EmployeeSubDocumentAdapter = EmployeeSubDocumentAdapter;
window.EmployeeDocumentAdapter = EmployeeDocumentAdapter;
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
import { FieldNameAdapter, CustomFieldAdapter } from './lib';
window.FieldNameAdapter = FieldNameAdapter;
window.CustomFieldAdapter = CustomFieldAdapter;
+47
View File
@@ -0,0 +1,47 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
import CustomFieldAdapter from '../../../api/CustomFieldAdapter';
/**
* FieldNameAdapter
*/
class FieldNameAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'textOrig',
'textMapped',
'display',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Original Text' },
{ sTitle: 'Mapped Text' },
{ sTitle: 'Display Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['type', { label: 'Type', type: 'placeholder', validation: '' }],
['name', { label: 'Name', type: 'placeholder', validation: '' }],
['textOrig', { label: 'Original Text', type: 'placeholder', validation: '' }],
['textMapped', { label: 'Mapped Text', type: 'text', validation: '' }],
['display', { label: 'Display Status', type: 'select', source: [['Form', 'Show'], ['Hidden', 'Hidden']] }],
];
}
}
module.exports = { FieldNameAdapter, CustomFieldAdapter };
+5
View File
@@ -0,0 +1,5 @@
import { JobTitleAdapter, PayGradeAdapter, EmploymentStatusAdapter } from './lib';
window.JobTitleAdapter = JobTitleAdapter;
window.PayGradeAdapter = PayGradeAdapter;
window.EmploymentStatusAdapter = EmploymentStatusAdapter;
+124
View File
@@ -0,0 +1,124 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* JobTitleAdapter
*/
class JobTitleAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'code',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Code' },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['code', { label: 'Job Title Code', type: 'text' }],
['name', { label: 'Job Title', type: 'text' }],
['description', { label: 'Description', type: 'textarea' }],
['specification', { label: 'Specification', type: 'textarea' }],
];
}
getHelpLink() {
return 'http://blog.icehrm.com/docs/jobdetails/';
}
}
/**
* PayGradeAdapter
*/
class PayGradeAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'currency',
'min_salary',
'max_salary',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Currency' },
{ sTitle: 'Min Salary' },
{ sTitle: 'Max Salary' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Pay Grade Name', type: 'text' }],
['currency', { label: 'Currency', type: 'select2', 'remote-source': ['CurrencyType', 'code', 'name'] }],
['min_salary', { label: 'Min Salary', type: 'text', validation: 'float' }],
['max_salary', { label: 'Max Salary', type: 'text', validation: 'float' }],
];
}
doCustomValidation(params) {
try {
if (parseFloat(params.min_salary) > parseFloat(params.max_salary)) {
return 'Min Salary should be smaller than Max Salary';
}
} catch (e) {
// D/N
}
return null;
}
}
/**
* EmploymentStatusAdapter
*/
class EmploymentStatusAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID' },
{ sTitle: 'Name' },
{ sTitle: 'Description' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Employment Status', type: 'text' }],
['description', { label: 'Description', type: 'textarea', validation: '' }],
];
}
}
module.exports = { JobTitleAdapter, PayGradeAdapter, EmploymentStatusAdapter };
+7
View File
@@ -0,0 +1,7 @@
import {
CompanyLoanAdapter,
EmployeeCompanyLoanAdapter,
} from './lib';
window.CompanyLoanAdapter = CompanyLoanAdapter;
window.EmployeeCompanyLoanAdapter = EmployeeCompanyLoanAdapter;
+101
View File
@@ -0,0 +1,101 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* CompanyLoanAdapter
*/
class CompanyLoanAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
}
/*
* EmployeeCompanyLoanAdapter
*/
class EmployeeCompanyLoanAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'employee',
'loan',
'start_date',
'period_months',
'currency',
'amount',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Loan Type' },
{ sTitle: 'Loan Start Date' },
{ sTitle: 'Loan Period (Months)' },
{ sTitle: 'Currency' },
{ sTitle: 'Amount' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
['loan', { label: 'Loan Type', type: 'select', 'remote-source': ['CompanyLoan', 'id', 'name'] }],
['start_date', { label: 'Loan Start Date', type: 'date', validation: '' }],
['last_installment_date', { label: 'Last Installment Date', type: 'date', validation: 'none' }],
['period_months', { label: 'Loan Period (Months)', type: 'text', validation: 'number' }],
['currency', { label: 'Currency', type: 'select2', 'remote-source': ['CurrencyType', 'id', 'name'] }],
['amount', { label: 'Loan Amount', type: 'text', validation: 'float' }],
['monthly_installment', { label: 'Monthly Installment', type: 'text', validation: 'float' }],
['status', { label: 'Status', type: 'select', source: [['Approved', 'Approved'], ['Paid', 'Paid'], ['Suspended', 'Suspended']] }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
getFilters() {
return [
['employee', {
label: 'Employee', type: 'select2', 'allow-null': true, 'null-label': 'All Employees', 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
['loan', {
label: 'Loan Type', type: 'select', 'allow-null': true, 'null-label': 'All Loan Types', 'remote-source': ['CompanyLoan', 'id', 'name'],
}],
];
}
}
module.exports = {
CompanyLoanAdapter,
EmployeeCompanyLoanAdapter,
};
+15
View File
@@ -0,0 +1,15 @@
import {
CountryAdapter,
ProvinceAdapter,
CurrencyTypeAdapter,
NationalityAdapter,
ImmigrationStatusAdapter,
EthnicityAdapter,
} from './lib';
window.CountryAdapter = CountryAdapter;
window.ProvinceAdapter = ProvinceAdapter;
window.CurrencyTypeAdapter = CurrencyTypeAdapter;
window.NationalityAdapter = NationalityAdapter;
window.ImmigrationStatusAdapter = ImmigrationStatusAdapter;
window.EthnicityAdapter = EthnicityAdapter;
+142
View File
@@ -0,0 +1,142 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
import IdNameAdapter from '../../../api/IdNameAdapter';
/**
* CountryAdapter
*/
class CountryAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'code',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Code' },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['code', { label: 'Code', type: 'text', validation: '' }],
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
}
/**
* ProvinceAdapter
*/
class ProvinceAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'code',
'name',
'country',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Code' },
{ sTitle: 'Name' },
{ sTitle: 'Country' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['code', { label: 'Code', type: 'text', validation: '' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['country', { label: 'Country', type: 'select2', 'remote-source': ['Country', 'code', 'name'] }],
];
}
getFilters() {
return [
['country', { label: 'Country', type: 'select2', 'remote-source': ['Country', 'code', 'name'] }],
];
}
}
/**
* CurrencyTypeAdapter
*/
class CurrencyTypeAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'code',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Code' },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['code', { label: 'Code', type: 'text', validation: '' }],
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
}
/**
* NationalityAdapter
*/
class NationalityAdapter extends IdNameAdapter {
}
/**
* ImmigrationStatusAdapter
*/
class ImmigrationStatusAdapter extends IdNameAdapter {
}
/**
* EthnicityAdapter
*/
class EthnicityAdapter extends IdNameAdapter {
}
module.exports = {
CountryAdapter,
ProvinceAdapter,
CurrencyTypeAdapter,
NationalityAdapter,
ImmigrationStatusAdapter,
EthnicityAdapter,
};
+4
View File
@@ -0,0 +1,4 @@
import { ModuleAdapter, UsageAdapter } from './lib';
window.ModuleAdapter = ModuleAdapter;
window.UsageAdapter = UsageAdapter;
+133
View File
@@ -0,0 +1,133 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* ModuleAdapter
*/
class ModuleAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'label',
'menu',
'mod_group',
'mod_order',
'status',
'version',
'update_path',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Menu', bVisible: false },
{ sTitle: 'Group' },
{ sTitle: 'Order' },
{ sTitle: 'Status' },
{ sTitle: 'Version', bVisible: false },
{ sTitle: 'Path', bVisible: false },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['label', { label: 'Label', type: 'text', validation: '' }],
['status', { label: 'Status', type: 'select', source: [['Enabled', 'Enabled'], ['Disabled', 'Disabled']] }],
['user_levels', { label: 'User Levels', type: 'select2multi', source: [['Admin', 'Admin'], ['Manager', 'Manager'], ['Employee', 'Employee'], ['Other', 'Other']] }],
['user_roles', { label: 'User Roles', type: 'select2multi', 'remote-source': ['UserRole', 'id', 'name'] }],
];
}
getActionButtonsHtml(id, data) {
const nonEditableFields = {};
nonEditableFields['admin_Company Structure'] = 1;
nonEditableFields.admin_Employees = 1;
nonEditableFields['admin_Job Details Setup'] = 1;
nonEditableFields.admin_Leaves = 1;
nonEditableFields['admin_Manage Modules'] = 1;
nonEditableFields.admin_Projects = 1;
nonEditableFields.admin_Qualifications = 1;
nonEditableFields.admin_Settings = 1;
nonEditableFields.admin_Users = 1;
nonEditableFields.admin_Upgrade = 1;
nonEditableFields.admin_Dashboard = 1;
nonEditableFields['user_Basic Information'] = 1;
nonEditableFields.user_Dashboard = 1;
if (nonEditableFields[`${data[3]}_${data[1]}`] === 1) {
return '';
}
let html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"/></div>';
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
}
/**
* UsageAdapter
*/
class UsageAdapter extends AdapterBase {
getDataMapping() {
return [];
}
getHeaders() {
return [];
}
getFormFields() {
return [];
}
get(callBackData) {
}
saveUsage() {
const object = {};
const arr = [];
$('.module-check').each(function () {
if ($(this).is(':checked')) {
arr.push($(this).val());
}
});
if (arr.length === 0) {
alert('Please select one or more module groups');
return;
}
object.groups = arr.join(',');
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getInitDataSuccessCallBack';
callBackData.callBackFail = 'getInitDataFailCallBack';
this.customAction('saveUsage', 'admin=modules', reqJson, callBackData);
}
saveUsageSuccessCallBack(data) {
}
saveUsageFailCallBack(callBackData) {
}
}
module.exports = { ModuleAdapter, UsageAdapter };
+7
View File
@@ -0,0 +1,7 @@
import {
OvertimeCategoryAdapter,
EmployeeOvertimeAdminAdapter,
} from './lib';
window.OvertimeCategoryAdapter = OvertimeCategoryAdapter;
window.EmployeeOvertimeAdminAdapter = EmployeeOvertimeAdminAdapter;
+100
View File
@@ -0,0 +1,100 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
import ApproveAdminAdapter from '../../../api/ApproveAdminAdapter';
/**
* OvertimeCategoryAdapter
*/
class OvertimeCategoryAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
}
/**
* EmployeeOvertimeAdminAdapter
*/
class EmployeeOvertimeAdminAdapter extends ApproveAdminAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'OvertimeRequest';
this.itemNameLower = 'overtimerequest';
this.modulePathName = 'overtime';
}
getDataMapping() {
return [
'id',
'employee',
'category',
'start_time',
'end_time',
'project',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Category' },
{ sTitle: 'Start Time' },
{ sTitle: 'End Time' },
{ sTitle: 'Project' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', {
label: 'Employee',
type: 'select2',
sort: 'none',
'allow-null': false,
'remote-source': ['Employee', 'id', 'first_name+last_name', 'getActiveSubordinateEmployees'],
}],
['category', {
label: 'Category', type: 'select2', 'allow-null': false, 'remote-source': ['OvertimeCategory', 'id', 'name'],
}],
['start_time', { label: 'Start Time', type: 'datetime', validation: '' }],
['end_time', { label: 'End Time', type: 'datetime', validation: '' }],
['project', {
label: 'Project', type: 'select2', 'allow-null': true, 'null=label': 'none', 'remote-source': ['Project', 'id', 'name'],
}],
['notes', { label: 'Notes', type: 'textarea', validation: 'none' }],
];
}
}
module.exports = {
OvertimeCategoryAdapter,
EmployeeOvertimeAdminAdapter,
};
+21
View File
@@ -0,0 +1,21 @@
import {
PaydayAdapter,
PayrollAdapter,
PayrollDataAdapter,
PayrollColumnAdapter,
PayrollColumnTemplateAdapter,
PayrollEmployeeAdapter,
DeductionAdapter,
DeductionGroupAdapter,
PayslipTemplateAdapter,
} from './lib';
window.PaydayAdapter = PaydayAdapter;
window.PayrollAdapter = PayrollAdapter;
window.PayrollDataAdapter = PayrollDataAdapter;
window.PayrollColumnAdapter = PayrollColumnAdapter;
window.PayrollColumnTemplateAdapter = PayrollColumnTemplateAdapter;
window.PayrollEmployeeAdapter = PayrollEmployeeAdapter;
window.DeductionAdapter = DeductionAdapter;
window.DeductionGroupAdapter = DeductionGroupAdapter;
window.PayslipTemplateAdapter = PayslipTemplateAdapter;
+631
View File
@@ -0,0 +1,631 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/* global modJs, modJsList */
import AdapterBase from '../../../api/AdapterBase';
import TableEditAdapter from '../../../api/TableEditAdapter';
/**
* PaydayAdapter
*/
class PaydayAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Select Pay Frequency' },
];
}
getFormFields() {
return [
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
getAddNewLabel() {
return 'Run Payroll';
}
createTable(elementId) {
$('#payday_all').off();
super.createTable(elementId);
$('#payday_all').off().on('click', function () {
if ($(this).is(':checked')) {
$('.paydayCheck').prop('checked', true);
} else {
$('.paydayCheck').prop('checked', false);
}
});
}
getActionButtonsHtml(id, data) {
const editButton = '<input type="checkbox" class="paydayCheck" id="payday__id_" name="payday__id_" value="checkbox_payday__id_"/>';
let html = '<div style="width:120px;">_edit_</div>';
html = html.replace('_edit_', editButton);
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
getActionButtonHeader() {
return { sTitle: '<input type="checkbox" id="payday_all" name="payday_all" value="checkbox_payday_all"/>', sClass: 'center' };
}
}
/**
* PayrollAdapter
*/
class PayrollAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'pay_period',
'department',
'date_start',
'date_end',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Pay Frequency' },
{ sTitle: 'Department' },
{ sTitle: 'Date Start' },
{ sTitle: 'Date End' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['pay_period', {
label: 'Pay Frequency', type: 'select', 'remote-source': ['PayFrequency', 'id', 'name'], sort: 'none',
}],
['deduction_group', {
label: 'Calculation Group', type: 'select', 'remote-source': ['DeductionGroup', 'id', 'name'], sort: 'none',
}],
['payslipTemplate', { label: 'Payslip Template', type: 'select', 'remote-source': ['PayslipTemplate', 'id', 'name'] }],
['department', {
label: 'Department', type: 'select2', 'remote-source': ['CompanyStructure', 'id', 'title'], sort: 'none',
}],
['date_start', { label: 'Start Date', type: 'date', validation: '' }],
['date_end', { label: 'End Date', type: 'date', validation: '' }],
// [ "column_template", {"label":"Report Column Template","type":"select","remote-source":["PayrollColumnTemplate","id","name"]}],
['columns', { label: 'Payroll Columns', type: 'select2multi', 'remote-source': ['PayrollColumn', 'id', 'name'] }],
['status', {
label: 'Status', type: 'select', source: [['Draft', 'Draft'], ['Completed', 'Completed']], sort: 'none',
}],
];
}
postRenderForm(object, $tempDomObj) {
if (object != null && object !== undefined && object.id !== undefined && object.id != null) {
$tempDomObj.find('#pay_period').attr('disabled', 'disabled');
$tempDomObj.find('#department').attr('disabled', 'disabled');
// $tempDomObj.find("#date_start").attr('disabled','disabled');
// $tempDomObj.find("#date_end").attr('disabled','disabled');
// $tempDomObj.find("#column_template").attr('disabled','disabled');
}
}
process(id, status) {
// eslint-disable-next-line no-global-assign
modJs = modJsList.tabPayrollData;
modJs.setCurrentPayroll(id);
$('#Payroll').hide();
$('#PayrollData').show();
$('#PayrollDataButtons').show();
if (status === 'Completed') {
$('.completeBtnTable').hide();
$('.saveBtnTable').hide();
} else {
$('.completeBtnTable').show();
$('.saveBtnTable').show();
}
modJs.get([]);
}
getActionButtonsHtml(id, data) {
const editButton = '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img>';
const processButton = '<img class="tableActionButton" src="_BASE_images/run.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Process" onclick="modJs.process(_id_,\'_status_\');return false;"></img>';
const deleteButton = '<img class="tableActionButton" src="_BASE_images/delete.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Delete" onclick="modJs.deleteRow(_id_);return false;"></img>';
const cloneButton = '<img class="tableActionButton" src="_BASE_images/clone.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Copy" onclick="modJs.copyRow(_id_);return false;"></img>';
let html = '<div style="width:120px;">_edit__process__clone__delete_</div>';
if (this.showAddNew) {
html = html.replace('_clone_', cloneButton);
} else {
html = html.replace('_clone_', '');
}
if (this.showDelete) {
html = html.replace('_delete_', deleteButton);
} else {
html = html.replace('_delete_', '');
}
if (this.showEdit) {
html = html.replace('_edit_', editButton);
} else {
html = html.replace('_edit_', '');
}
html = html.replace('_process_', processButton);
html = html.replace(/_id_/g, id);
html = html.replace(/_status_/g, data[6]);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
get(callBackData) {
$('#PayrollData').hide();
$('#PayrollForm').hide();
$('#PayrollDataButtons').hide();
$('#Payroll').show();
modJsList.tabPayrollData.setCurrentPayroll(null);
super.get(callBackData);
}
}
/**
* PayrollDataAdapter
*/
class PayrollDataAdapter extends TableEditAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.cellDataUpdates = {};
this.payrollId = null;
}
validateCellValue(element, evt, newValue) {
modJs.addCellDataUpdate(element.data('colId'), element.data('rowId'), newValue);
return true;
}
setCurrentPayroll(val) {
this.payrollId = val;
}
addAdditionalRequestData(type, req) {
if (type === 'updateData') {
req.payrollId = this.payrollId;
} else if (type === 'updateAllData') {
req.payrollId = this.payrollId;
} else if (type === 'getAllData') {
req.payrollId = this.payrollId;
}
return req;
}
modifyCSVHeader(header) {
header.unshift('');
return header;
}
getCSVData() {
let csv = '';
for (let i = 0; i < this.csvData.length; i++) {
csv += this.csvData[i].join(',');
if (i < this.csvData.length - 1) {
csv += '\r\n';
}
}
return csv;
}
downloadPayroll() {
const element = document.createElement('a');
element.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(this.getCSVData())}`);
element.setAttribute('download', `payroll_${this.payrollId}.csv`);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
}
/**
* PayrollColumnAdapter
*/
class PayrollColumnAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'colorder',
'calculation_hook',
'deduction_group',
'editable',
'enabled',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Column Order' },
{ sTitle: 'Calculation Method' },
{ sTitle: 'Calculation Group' },
{ sTitle: 'Editable' },
{ sTitle: 'Enabled' },
];
}
getFormFields() {
const fucntionColumnList = ['calculation_columns', {
label: 'Calculation Columns',
type: 'datagroup',
form: [
['name', { label: 'Name', type: 'text', validation: '' }],
['column', { label: 'Column', type: 'select2', 'remote-source': ['PayrollColumn', 'id', 'name'] }],
],
html: '<div id="#_id_#" class="panel panel-default">#_delete_##_edit_#<div class="panel-body">#_renderFunction_#</div></div>',
validation: 'none',
render(item) {
const output = `Variable:${item.name}`;
return output;
},
}];
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['calculation_hook', {
label: 'Predefined Calculations', type: 'select2', 'allow-null': true, 'null-label': 'None', 'remote-source': ['CalculationHook', 'code', 'name'],
}],
['deduction_group', {
label: 'Calculation Group', type: 'select2', 'allow-null': true, 'null-label': 'Common', 'remote-source': ['DeductionGroup', 'id', 'name'],
}],
['salary_components', { label: 'Salary Components', type: 'select2multi', 'remote-source': ['SalaryComponent', 'id', 'name'] }],
['deductions', { label: 'Calculation Method', type: 'select2multi', 'remote-source': ['Deduction', 'id', 'name'] }],
['add_columns', { label: 'Columns to Add', type: 'select2multi', 'remote-source': ['PayrollColumn', 'id', 'name'] }],
['sub_columns', { label: 'Columns to Subtract', type: 'select2multi', 'remote-source': ['PayrollColumn', 'id', 'name'] }],
['colorder', { label: 'Column Order', type: 'text', validation: 'number' }],
['editable', { label: 'Editable', type: 'select', source: [['Yes', 'Yes'], ['No', 'No']] }],
['enabled', { label: 'Enabled', type: 'select', source: [['Yes', 'Yes'], ['No', 'No']] }],
['default_value', { label: 'Default Value', type: 'text', validation: '' }],
fucntionColumnList,
['calculation_function', { label: 'Function', type: 'text', validation: 'none' }],
];
}
getFilters() {
return [
['deduction_group', {
label: 'Calculation Group', type: 'select2', 'allow-null': true, 'null-label': 'Any', 'remote-source': ['DeductionGroup', 'id', 'name'],
}],
];
}
}
/**
* PayrollColumnTemplateAdapter
*/
class PayrollColumnTemplateAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: true },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['columns', { label: 'Payroll Columns', type: 'select2multi', 'remote-source': ['PayrollColumn', 'id', 'name'] }],
];
}
}
/*
* PayrollEmployeeAdapter
*/
class PayrollEmployeeAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'employee',
'pay_frequency',
'deduction_group',
'currency',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Pay Frequency' },
{ sTitle: 'Calculation Group' },
{ sTitle: 'Currency' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
['pay_frequency', { label: 'Pay Frequency', type: 'select2', 'remote-source': ['PayFrequency', 'id', 'name'] }],
['currency', { label: 'Currency', type: 'select2', 'remote-source': ['CurrencyType', 'id', 'code'] }],
['deduction_group', {
label: 'Calculation Group', type: 'select2', 'allow-null': true, 'null-label': 'None', 'remote-source': ['DeductionGroup', 'id', 'name'],
}],
['deduction_exemptions', {
label: 'Calculation Exemptions', type: 'select2multi', 'remote-source': ['Deduction', 'id', 'name'], validation: 'none',
}],
['deduction_allowed', {
label: 'Calculations Assigned', type: 'select2multi', 'remote-source': ['Deduction', 'id', 'name'], validation: 'none',
}],
];
}
getFilters() {
return [
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
];
}
}
/**
* DeductionAdapter
*/
class DeductionAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'deduction_group',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Calculation Group' },
];
}
getFormFields() {
const rangeAmounts = ['rangeAmounts', {
label: 'Calculation Process',
type: 'datagroup',
form: [
['lowerCondition', { label: 'Lower Limit Condition', type: 'select', source: [['No Lower Limit', 'No Lower Limit'], ['gt', 'Greater than'], ['gte', 'Greater than or Equal']] }],
['lowerLimit', { label: 'Lower Limit', type: 'text', validation: 'float' }],
['upperCondition', { label: 'Upper Limit Condition', type: 'select', source: [['No Upper Limit', 'No Upper Limit'], ['lt', 'Less than'], ['lte', 'Less than or Equal']] }],
['upperLimit', { label: 'Upper Limit', type: 'text', validation: 'float' }],
['amount', { label: 'Value', type: 'text', validation: '' }],
],
html: '<div id="#_id_#" class="panel panel-default">#_delete_##_edit_#<div class="panel-body">#_renderFunction_#</div></div>',
validation: 'none',
'custom-validate-function': function (data) {
const res = {};
res.valid = true;
if (data.lowerCondition === 'No Lower Limit') {
data.lowerLimit = 0;
}
if (data.upperCondition === 'No Upper Limit') {
data.upperLimit = 0;
}
res.params = data;
return res;
},
render(item) {
let output = '';
const getSymbol = function (text) {
const map = {};
map.gt = '>';
map.gte = '>=';
map.lt = '<';
map.lte = '<=';
return map[text];
};
if (item.lowerCondition !== 'No Lower Limit') {
output += `${item.lowerLimit} ${getSymbol(item.lowerCondition)} `;
}
if (item.upperCondition !== 'No Upper Limit') {
output += ' and ';
output += `${getSymbol(item.upperCondition)} ${item.upperLimit} `;
}
if (output === '') {
return `Deduction is ${item.amount} for all ranges`;
}
return `If salary component ${output} deduction is ${item.amount}`;
},
}];
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['componentType', {
label: 'Salary Component Type', type: 'select2multi', 'allow-null': true, 'remote-source': ['SalaryComponentType', 'id', 'name'],
}],
['component', {
label: 'Salary Component', type: 'select2multi', 'allow-null': true, 'remote-source': ['SalaryComponent', 'id', 'name'],
}],
['payrollColumn', {
label: 'Payroll Report Column', type: 'select2', 'allow-null': true, 'remote-source': ['PayrollColumn', 'id', 'name'],
}],
rangeAmounts,
['deduction_group', {
label: 'Calculation Group', type: 'select2', 'allow-null': true, 'null-label': 'None', 'remote-source': ['DeductionGroup', 'id', 'name'],
}],
];
}
}
/*
* DeductionGroupAdapter
*/
class DeductionGroupAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['description', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
}
/*
* PayslipTemplateAdapter
*/
class PayslipTemplateAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
];
}
getFormFields() {
const payslipFields = ['data', {
label: 'Payslip Fields',
type: 'datagroup',
form: [
['type', {
label: 'Type', type: 'select', sort: 'none', source: [['Payroll Column', 'Payroll Column'], ['Text', 'Text'], ['Company Name', 'Company Name'], ['Company Logo', 'Company Logo'], ['Separators', 'Separators']],
}],
['payrollColumn', {
label: 'Payroll Column', type: 'select2', sort: 'none', 'allow-null': true, 'null-label': 'None', 'remote-source': ['PayrollColumn', 'id', 'name'],
}],
['label', { label: 'Label', type: 'text', validation: 'none' }],
['text', { label: 'Text', type: 'textarea', validation: 'none' }],
['status', {
label: 'Status', type: 'select', sort: 'none', source: [['Show', 'Show'], ['Hide', 'Hide']],
}],
],
// "html":'<div id="#_id_#" class="panel panel-default">#_delete_##_edit_#<div class="panel-body"><table class="table table-striped"><tr><td>Type</td><td>#_type_#</td></tr><tr><td>Label</td><td>#_label_#</td></tr><tr><td>Text</td><td>#_text_#</td></tr><tr><td>Font Size</td><td>#_fontSize_#</td></tr><tr><td>Font Style</td><td>#_fontStyle_#</td></tr><tr><td>Font Color</td><td>#_fontColor_#</td></tr><tr><td>Status</td><td>#_status_#</td></tr></table> </div></div>',
html: '<div id="#_id_#" class="panel panel-default">#_delete_##_edit_#<div class="panel-body">#_type_# #_label_# <br/> #_text_#</div></div>',
validation: 'none',
'custom-validate-function': function (data) {
const res = {};
res.valid = true;
if (data.type === 'Payroll Column') {
if (data.payrollColumn === 'NULL') {
res.valid = false;
res.message = 'Please select payroll column';
} else {
data.payrollColumn = 'NULL';
}
} else if (data.type === 'Text') {
if (data.text === '') {
res.valid = false;
res.message = 'Text can not be empty';
}
}
res.params = data;
return res;
},
}];
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
payslipFields,
];
}
}
module.exports = {
PaydayAdapter,
PayrollAdapter,
PayrollDataAdapter,
PayrollColumnAdapter,
PayrollColumnTemplateAdapter,
PayrollEmployeeAdapter,
DeductionAdapter,
DeductionGroupAdapter,
PayslipTemplateAdapter,
};
+3
View File
@@ -0,0 +1,3 @@
import { PermissionAdapter } from './lib';
window.PermissionAdapter = PermissionAdapter;
+73
View File
@@ -0,0 +1,73 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* PermissionAdapter
*/
class PermissionAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'user_level',
'module_id',
'permission',
'value',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'User Level' },
{ sTitle: 'Module' },
{ sTitle: 'Permission' },
{ sTitle: 'Value' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['user_level', { label: 'User Level', type: 'placeholder', validation: 'none' }],
['module_id', { label: 'Module', type: 'placeholder', 'remote-source': ['Module', 'id', 'menu+name'] }],
['permission', { label: 'Permission', type: 'placeholder', validation: 'none' }],
['value', { label: 'Value', type: 'text', validation: 'none' }],
];
}
getFilters() {
return [
['module_id', {
label: 'Module', type: 'select2', 'allow-null': true, 'null-label': 'All Modules', 'remote-source': ['Module', 'id', 'menu+name'],
}],
];
}
getActionButtonsHtml(id, data) {
let html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img></div>';
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
getMetaFieldForRendering(fieldName) {
if (fieldName === 'value') {
return 'meta';
}
return '';
}
fillForm(object) {
super.fillForm(object);
$('#helptext').html(object.description);
}
}
module.exports = { PermissionAdapter };
+9
View File
@@ -0,0 +1,9 @@
import {
ClientAdapter,
ProjectAdapter,
EmployeeProjectAdapter,
} from './lib';
window.ClientAdapter = ClientAdapter;
window.ProjectAdapter = ProjectAdapter;
window.EmployeeProjectAdapter = EmployeeProjectAdapter;
+163
View File
@@ -0,0 +1,163 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* ClientAdapter
*/
class ClientAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'details',
'address',
'contact_number',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Details' },
{ sTitle: 'Address' },
{ sTitle: 'Contact Number' },
];
}
getFormFields() {
if (this.showSave) {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
['address', { label: 'Address', type: 'textarea', validation: 'none' }],
['contact_number', { label: 'Contact Number', type: 'text', validation: 'none' }],
['contact_email', { label: 'Contact Email', type: 'text', validation: 'none' }],
['company_url', { label: 'Company Url', type: 'text', validation: 'none' }],
['status', { label: 'Status', type: 'select', source: [['Active', 'Active'], ['Inactive', 'Inactive']] }],
['first_contact_date', { label: 'First Contact Date', type: 'date', validation: 'none' }],
];
}
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'placeholder' }],
['details', { label: 'Details', type: 'placeholder', validation: 'none' }],
['address', { label: 'Address', type: 'placeholder', validation: 'none' }],
['contact_number', { label: 'Contact Number', type: 'placeholder', validation: 'none' }],
['contact_email', { label: 'Contact Email', type: 'placeholder', validation: 'none' }],
['company_url', { label: 'Company Url', type: 'placeholder', validation: 'none' }],
['status', { label: 'Status', type: 'placeholder', source: [['Active', 'Active'], ['Inactive', 'Inactive']] }],
['first_contact_date', { label: 'First Contact Date', type: 'placeholder', validation: 'none' }],
];
}
getHelpLink() {
return 'http://blog.icehrm.com/docs/projects/';
}
}
/**
* ProjectAdapter
*/
class ProjectAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'client',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Client' },
];
}
getFormFields() {
if (this.showSave) {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['client', {
label: 'Client', type: 'select2', 'allow-null': true, 'remote-source': ['Client', 'id', 'name'],
}],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
['status', { label: 'Status', type: 'select', source: [['Active', 'Active'], ['On Hold', 'On Hold'], ['Completed', 'Completed'], ['Dropped', 'Dropped']] }],
];
}
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'placeholder' }],
['client', {
label: 'Client', type: 'placeholder', 'allow-null': true, 'remote-source': ['Client', 'id', 'name'],
}],
['details', { label: 'Details', type: 'placeholder', validation: 'none' }],
['status', { label: 'Status', type: 'select', source: [['Active', 'Active'], ['On Hold', 'On Hold'], ['Completed', 'Completed'], ['Dropped', 'Dropped']] }],
];
}
getHelpLink() {
return 'http://blog.icehrm.com/docs/projects/';
}
}
/*
* EmployeeProjectAdapter
*/
class EmployeeProjectAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'employee',
'project',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Project' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
['project', { label: 'Project', type: 'select2', 'remote-source': ['Project', 'id', 'name'] }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
getFilters() {
return [
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
];
}
getHelpLink() {
return 'http://blog.icehrm.com/docs/projects/';
}
}
module.exports = {
ClientAdapter,
ProjectAdapter,
EmployeeProjectAdapter,
};
+11
View File
@@ -0,0 +1,11 @@
import {
SkillAdapter,
EducationAdapter,
CertificationAdapter,
LanguageAdapter,
} from './lib';
window.SkillAdapter = SkillAdapter;
window.EducationAdapter = EducationAdapter;
window.CertificationAdapter = CertificationAdapter;
window.LanguageAdapter = LanguageAdapter;
+140
View File
@@ -0,0 +1,140 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* SkillAdapter
*/
class SkillAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Description' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['description', { label: 'Description', type: 'textarea', validation: '' }],
];
}
getHelpLink() {
return 'http://blog.icehrm.com/docs/qualifications/';
}
}
/**
* EducationAdapter
*/
class EducationAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Description' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['description', { label: 'Description', type: 'textarea', validation: '' }],
];
}
}
/**
* CertificationAdapter
*/
class CertificationAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Description' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['description', { label: 'Description', type: 'textarea', validation: '' }],
];
}
}
/**
* LanguageAdapter
*/
class LanguageAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Description' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text' }],
['description', { label: 'Description', type: 'textarea', validation: '' }],
];
}
}
module.exports = {
SkillAdapter,
EducationAdapter,
CertificationAdapter,
LanguageAdapter,
};
+4
View File
@@ -0,0 +1,4 @@
import { ReportAdapter, ReportGenAdapter } from './lib';
window.ReportAdapter = ReportAdapter;
window.ReportGenAdapter = ReportGenAdapter;
+372
View File
@@ -0,0 +1,372 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/* global SignaturePad, modJs */
/* eslint-disable no-underscore-dangle */
import AdapterBase from '../../../api/AdapterBase';
/**
* ReportAdapter
*/
class ReportAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this._construct();
}
_construct() {
this._formFileds = [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'label', validation: '' }],
['parameters', { label: 'Parameters', type: 'fieldset', validation: 'none' }],
];
this.remoteFieldsExists = false;
}
_initLocalFormFields() {
this._formFileds = [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'label', validation: '' }],
['parameters', { label: 'Parameters', type: 'fieldset', validation: 'none' }],
];
}
setRemoteFieldExists(val) {
this.remoteFieldsExists = val;
}
getDataMapping() {
return [
'id',
'icon',
'name',
'details',
'parameters',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: '', bSortable: false, sWidth: '22px' },
{ sTitle: 'Name', sWidth: '30%' },
{ sTitle: 'Details' },
{ sTitle: 'Parameters', bVisible: false },
];
}
getFormFields() {
return this._formFileds;
}
processFormFieldsWithObject(object) {
const that = this;
this._initLocalFormFields();
const len = this._formFileds.length;
const fieldIDsToDelete = [];
const fieldsToDelete = [];
this.remoteFieldsExists = false;
for (let i = 0; i < len; i++) {
if (this._formFileds[i][1].type === 'fieldset') {
const newFields = JSON.parse(object[this._formFileds[i][0]]);
fieldsToDelete.push(this._formFileds[i][0]);
newFields.forEach((entry) => {
that._formFileds.push(entry);
if (entry[1]['remote-source'] !== undefined && entry[1]['remote-source'] != null) {
that.remoteFieldsExists = true;
}
});
}
}
const tempArray = [];
that._formFileds.forEach((entry) => {
if (jQuery.inArray(entry[0], fieldsToDelete) < 0) {
tempArray.push(entry);
}
});
that._formFileds = tempArray;
}
renderForm(object) {
const that = this;
this.processFormFieldsWithObject(object);
if (this.remoteFieldsExists) {
const cb = function () {
that.renderFormNew(object);
};
this.initFieldMasterData(cb);
} else {
this.initFieldMasterData();
that.renderFormNew(object);
}
this.currentReport = object;
}
renderFormNew(object) {
const that = this;
const signatureIds = [];
if (object == null || object === undefined) {
this.currentId = null;
}
this.preRenderForm(object);
let formHtml = this.templates.formTemplate;
let html = '';
const fields = this.getFormFields();
for (let i = 0; i < fields.length; i++) {
const metaField = this.getMetaFieldForRendering(fields[i][0]);
if (metaField === '' || metaField === undefined) {
html += this.renderFormField(fields[i]);
} else {
const metaVal = object[metaField];
if (metaVal !== '' && metaVal != null && metaVal !== undefined && metaVal.trim() !== '') {
html += this.renderFormField(JSON.parse(metaVal));
} else {
html += this.renderFormField(fields[i]);
}
}
}
formHtml = formHtml.replace(/_id_/g, `${this.getTableName()}_submit`);
formHtml = formHtml.replace(/_fields_/g, html);
let $tempDomObj;
const randomFormId = this.generateRandom(14);
if (!this.showFormOnPopup) {
$tempDomObj = $(`#${this.getTableName()}Form`);
} else {
$tempDomObj = $('<div class="reviewBlock popupForm" data-content="Form"></div>');
$tempDomObj.attr('id', randomFormId);
}
$tempDomObj.html(formHtml);
$tempDomObj.find('.datefield').datepicker({ viewMode: 2 });
$tempDomObj.find('.timefield').datetimepicker({
language: 'en',
pickDate: false,
});
$tempDomObj.find('.datetimefield').datetimepicker({
language: 'en',
});
$tempDomObj.find('.colorpick').colorpicker();
// $tempDomObj.find('.select2Field').select2();
$tempDomObj.find('.select2Field').each(function () {
$(this).select2().select2('val', $(this).find('option:eq(0)').val());
});
$tempDomObj.find('.select2Multi').each(function () {
$(this).select2().on('change', function (e) {
const parentRow = $(this).parents('.row');
const height = parentRow.find('.select2-choices').height();
parentRow.height(parseInt(height, 10));
});
});
$tempDomObj.find('.signatureField').each(function () {
// $(this).data('signaturePad',new SignaturePad($(this)));
signatureIds.push($(this).attr('id'));
});
for (let i = 0; i < fields.length; i++) {
if (fields[i][1].type === 'datagroup') {
$tempDomObj.find(`#${fields[i][0]}`).data('field', fields[i]);
}
}
if (this.showSave === false) {
$tempDomObj.find('.saveBtn').remove();
} else {
$tempDomObj.find('.saveBtn').off();
$tempDomObj.find('.saveBtn').data('modJs', this);
$tempDomObj.find('.saveBtn').on('click', function () {
if ($(this).data('modJs').saveSuccessItemCallback != null && $(this).data('modJs').saveSuccessItemCallback !== undefined) {
$(this).data('modJs').save($(this).data('modJs').retriveItemsAfterSave(), $(this).data('modJs').saveSuccessItemCallback);
} else {
$(this).data('modJs').save();
}
return false;
});
}
if (this.showCancel === false) {
$tempDomObj.find('.cancelBtn').remove();
} else {
$tempDomObj.find('.cancelBtn').off();
$tempDomObj.find('.cancelBtn').data('modJs', this);
$tempDomObj.find('.cancelBtn').on('click', function () {
$(this).data('modJs').cancel();
return false;
});
}
if (!this.showFormOnPopup) {
$(`#${this.getTableName()}Form`).show();
$(`#${this.getTableName()}`).hide();
for (let i = 0; i < signatureIds.length; i++) {
$(`#${signatureIds[i]}`)
.data('signaturePad',
new SignaturePad(document.getElementById(signatureIds[i])));
}
if (object !== undefined && object != null) {
this.fillForm(object);
}
} else {
// var tHtml = $tempDomObj.wrap('<div>').parent().html();
// this.showMessage("Edit",tHtml,null,null,true);
this.showMessage('Edit', '', null, null, true);
$('#plainMessageModel .modal-body').html('');
$('#plainMessageModel .modal-body').append($tempDomObj);
for (let i = 0; i < signatureIds.length; i++) {
$(`#${signatureIds[i]}`)
.data('signaturePad',
new SignaturePad(document.getElementById(signatureIds[i])));
}
if (object !== undefined && object != null) {
this.fillForm(object, `#${randomFormId}`);
}
}
this.postRenderForm(object, $tempDomObj);
}
getActionButtonsHtml(id, data) {
let html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/download.png" style="cursor:pointer;" rel="tooltip" title="Download" onclick="modJs.edit(_id_);return false;"></img></div>';
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
addSuccessCallBack(callBackData, serverData) {
const fileName = serverData[0];
let link;
if (fileName.indexOf('https:') === 0) {
link = `<a href="${fileName}" target="_blank" style="font-size:14px;font-weight:bold;">Download Report <img src="_BASE_images/download.png"></img> </a>`;
} else {
link = `<a href="${modJs.getCustomActionUrl('download', { file: fileName })}" target="_blank" style="font-size:14px;font-weight:bold;">Download Report <img src="_BASE_images/download.png"></img> </a>`;
}
link = link.replace(/_BASE_/g, this.baseUrl);
if (this.currentReport.output === 'PDF' || this.currentReport.output === 'JSON') {
this.showMessage('Download Report', link);
} else {
if (serverData[1].length === 0) {
this.showMessage('Empty Report', 'There were no data for selected filters');
return;
}
const tableHtml = `${link}<br/><br/><div class="box-body table-responsive" style="overflow-x:scroll;padding: 5px;border: solid 1px #DDD;"><table id="tempReportTable" cellpadding="0" cellspacing="0" border="0" class="table table-bordered table-striped"></table></div>`;
// Delete existing temp report table
$('#tempReportTable').remove();
// this.showMessage("Report",tableHtml);
$(`#${this.table}`).html(tableHtml);
$(`#${this.table}`).show();
$(`#${this.table}Form`).hide();
// Prepare headers
const headers = [];
for (const index in serverData[1]) {
headers.push({ sTitle: serverData[1][index] });
}
const data = serverData[2];
const dataTableParams = {
oLanguage: {
sLengthMenu: '_MENU_ records per page',
},
aaData: data,
aoColumns: headers,
bSort: false,
iDisplayLength: 15,
iDisplayStart: 0,
};
$('#tempReportTable').dataTable(dataTableParams);
$('.dataTables_paginate ul').addClass('pagination');
$('.dataTables_length').hide();
$('.dataTables_filter input').addClass('form-control');
$('.dataTables_filter input').attr('placeholder', 'Search');
$('.dataTables_filter label').contents().filter(function () {
return (this.nodeType === 3);
}).remove();
$('.tableActionButton').tooltip();
}
}
fillForm(object) {
const fields = this.getFormFields();
for (let i = 0; i < fields.length; i++) {
if (fields[i][1].type === 'label') {
$(`#${this.getTableName()}Form #${fields[i][0]}`).html(object[fields[i][0]]);
} else {
$(`#${this.getTableName()}Form #${fields[i][0]}`).val(object[fields[i][0]]);
}
}
}
}
class ReportGenAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
];
}
getActionButtonsHtml(id, data) {
let html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/download.png" style="cursor:pointer;" rel="tooltip" title="Download" onclick="download(_name_);return false;"></img></div>';
html = html.replace(/_id_/g, id);
html = html.replace(/_name_/g, data[1]);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
}
module.exports = { ReportAdapter, ReportGenAdapter };
+9
View File
@@ -0,0 +1,9 @@
import {
SalaryComponentTypeAdapter,
SalaryComponentAdapter,
EmployeeSalaryAdapter,
} from './lib';
window.SalaryComponentTypeAdapter = SalaryComponentTypeAdapter;
window.SalaryComponentAdapter = SalaryComponentAdapter;
window.EmployeeSalaryAdapter = EmployeeSalaryAdapter;
+120
View File
@@ -0,0 +1,120 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* SalaryComponentTypeAdapter
*/
class SalaryComponentTypeAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'code',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Code' },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['code', { label: 'Code', type: 'text', validation: '' }],
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
}
/**
* SalaryComponentAdapter
*/
class SalaryComponentAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'componentType',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Salary Component Type' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['componentType', { label: 'Salary Component Type', type: 'select2', 'remote-source': ['SalaryComponentType', 'id', 'name'] }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
}
/*
* EmployeeSalaryAdapter
*/
class EmployeeSalaryAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'employee',
'component',
'amount',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Salary Component' },
{ sTitle: 'Amount' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
['component', { label: 'Salary Component', type: 'select2', 'remote-source': ['SalaryComponent', 'id', 'name'] }],
['amount', { label: 'Amount', type: 'text', validation: 'float' }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
getFilters() {
return [
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
];
}
}
module.exports = {
SalaryComponentTypeAdapter,
SalaryComponentAdapter,
EmployeeSalaryAdapter,
};
+3
View File
@@ -0,0 +1,3 @@
import { SettingAdapter } from './lib';
window.SettingAdapter = SettingAdapter;
+109
View File
@@ -0,0 +1,109 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
/**
* SettingAdapter
*/
class SettingAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'value',
'description',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Value' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['value', { label: 'Value', type: 'text', validation: 'none' }],
];
}
getActionButtonsHtml(id, data) {
let html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img></div>';
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
getMetaFieldForRendering(fieldName) {
if (fieldName === 'value') {
return 'meta';
}
return '';
}
edit(id) {
this.loadRemoteDataForSettings();
super.edit(id);
}
fillForm(object) {
const metaField = this.getMetaFieldForRendering('value');
const metaVal = object[metaField];
let formFields = null;
if (metaVal !== '' && metaVal !== undefined) {
formFields = [
['id', { label: 'ID', type: 'hidden' }],
JSON.parse(metaVal),
];
}
super.fillForm(object, null, formFields);
$('#helptext').html(object.description);
}
loadRemoteDataForSettings() {
const fields = [];
let field = null;
fields.push(['country', { label: 'Country', type: 'select2multi', 'remote-source': ['Country', 'id', 'name'] }]);
fields.push(['countryCompany', { label: 'Country', type: 'select2', 'remote-source': ['Country', 'code', 'name'] }]);
fields.push(['currency', { label: 'Currency', type: 'select2multi', 'remote-source': ['CurrencyType', 'id', 'code+name'] }]);
fields.push(['nationality', { label: 'Nationality', type: 'select2multi', 'remote-source': ['Nationality', 'id', 'name'] }]);
fields.push(['supportedLanguage', {
label: 'Value', type: 'select2', 'allow-null': false, 'remote-source': ['SupportedLanguage', 'name', 'description'],
}]);
for (const index in fields) {
field = fields[index];
if (field[1]['remote-source'] !== undefined && field[1]['remote-source'] !== null) {
const key = `${field[1]['remote-source'][0]}_${field[1]['remote-source'][1]}_${field[1]['remote-source'][2]}`;
this.fieldMasterDataKeys[key] = false;
this.sourceMapping[field[0]] = field[1]['remote-source'];
const callBackData = {};
callBackData.callBack = 'initFieldMasterDataResponse';
callBackData.callBackData = [key];
this.getFieldValues(field[1]['remote-source'], callBackData);
}
}
}
getHelpLink() {
return 'http://blog.icehrm.com/docs/settings/';
}
}
module.exports = { SettingAdapter };
+11
View File
@@ -0,0 +1,11 @@
import {
ImmigrationDocumentAdapter,
EmployeeImmigrationAdapter,
EmployeeTravelRecordAdminAdapter,
CustomFieldAdapter,
} from './lib';
window.ImmigrationDocumentAdapter = ImmigrationDocumentAdapter;
window.EmployeeImmigrationAdapter = EmployeeImmigrationAdapter;
window.EmployeeTravelRecordAdminAdapter = EmployeeTravelRecordAdminAdapter;
window.CustomFieldAdapter = CustomFieldAdapter;
+195
View File
@@ -0,0 +1,195 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from '../../../api/AdapterBase';
import CustomFieldAdapter from '../../../api/CustomFieldAdapter';
import ApproveAdminAdapter from '../../../api/ApproveAdminAdapter';
/**
* ImmigrationDocumentAdapter
*/
class ImmigrationDocumentAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'details',
'required',
'alert_on_missing',
'alert_before_expiry',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Details' },
{ sTitle: 'Compulsory' },
{ sTitle: 'Alert If Not Found' },
{ sTitle: 'Alert Before Expiry' },
];
}
getFormFields() {
const fields = [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
['required', { label: 'Compulsory', type: 'select', source: [['No', 'No'], ['Yes', 'Yes']] }],
['alert_on_missing', { label: 'Alert If Not Found', type: 'select', source: [['No', 'No'], ['Yes', 'Yes']] }],
['alert_before_expiry', { label: 'Alert Before Expiry', type: 'select', source: [['No', 'No'], ['Yes', 'Yes']] }],
['alert_before_day_number', { label: 'Days for Expiry Alert', type: 'text', validation: '' }],
];
for (let i = 0; i < this.customFields.length; i++) {
fields.push(this.customFields[i]);
}
return fields;
}
}
/**
* EmployeeImmigrationAdapter
*/
class EmployeeImmigrationAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'employee',
'document',
'documentname',
'valid_until',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Document' },
{ sTitle: 'Document Id' },
{ sTitle: 'Valid Until' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
['document', { label: 'Document', type: 'select2', 'remote-source': ['ImmigrationDocument', 'id', 'name'] }],
['documentname', { label: 'Document Id', type: 'text', validation: '' }],
['valid_until', { label: 'Valid Until', type: 'date', validation: 'none' }],
['status', { label: 'Status', type: 'select', source: [['Active', 'Active'], ['Inactive', 'Inactive'], ['Draft', 'Draft']] }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
['attachment1', { label: 'Attachment 1', type: 'fileupload', validation: 'none' }],
['attachment2', { label: 'Attachment 2', type: 'fileupload', validation: 'none' }],
['attachment3', { label: 'Attachment 3', type: 'fileupload', validation: 'none' }],
];
}
getFilters() {
return [
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }],
];
}
}
/**
* EmployeeTravelRecordAdminAdapter
*/
class EmployeeTravelRecordAdminAdapter extends ApproveAdminAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'TravelRequest';
this.itemNameLower = 'travelrequest';
this.modulePathName = 'travel';
}
getDataMapping() {
return [
'id',
'employee',
'type',
'purpose',
'travel_from',
'travel_to',
'travel_date',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee' },
{ sTitle: 'Travel Type' },
{ sTitle: 'Purpose' },
{ sTitle: 'From' },
{ sTitle: 'To' },
{ sTitle: 'Travel Date' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return this.addCustomFields([
['id', { label: 'ID', type: 'hidden' }],
['employee', {
label: 'Employee',
type: 'select2',
sort: 'none',
'allow-null': false,
'remote-source': ['Employee', 'id', 'first_name+last_name', 'getActiveSubordinateEmployees'],
}],
['type', {
label: 'Means of Transportation',
type: 'select',
source: [
['Plane', 'Plane'],
['Rail', 'Rail'],
['Taxi', 'Taxi'],
['Own Vehicle', 'Own Vehicle'],
['Rented Vehicle', 'Rented Vehicle'],
['Other', 'Other'],
],
}],
['purpose', { label: 'Purpose of Travel', type: 'textarea', validation: '' }],
['travel_from', { label: 'Travel From', type: 'text', validation: '' }],
['travel_to', { label: 'Travel To', type: 'text', validation: '' }],
['travel_date', { label: 'Travel Date', type: 'datetime', validation: '' }],
['return_date', { label: 'Return Date', type: 'datetime', validation: '' }],
['details', { label: 'Notes', type: 'textarea', validation: 'none' }],
['currency', {
label: 'Currency', type: 'select2', 'allow-null': false, 'remote-source': ['CurrencyType', 'id', 'code'],
}],
['funding', {
label: 'Total Funding Proposed', type: 'text', validation: 'float', default: '0.00', mask: '9{0,10}.99',
}],
['attachment1', { label: 'Attachment', type: 'fileupload', validation: 'none' }],
['attachment2', { label: 'Attachment', type: 'fileupload', validation: 'none' }],
['attachment3', { label: 'Attachment', type: 'fileupload', validation: 'none' }],
]);
}
}
module.exports = {
ImmigrationDocumentAdapter,
EmployeeImmigrationAdapter,
EmployeeTravelRecordAdminAdapter,
CustomFieldAdapter,
};
+7
View File
@@ -0,0 +1,7 @@
import {
UserAdapter,
UserRoleAdapter,
} from './lib';
window.UserAdapter = UserAdapter;
window.UserRoleAdapter = UserRoleAdapter;
+201
View File
@@ -0,0 +1,201 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import FormValidation from '../../../api/FormValidation';
import AdapterBase from '../../../api/AdapterBase';
class UserAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'username',
'email',
'employee',
'user_level',
];
}
getHeaders() {
return [
{ sTitle: 'ID' },
{ sTitle: 'User Name' },
{ sTitle: 'Authentication Email' },
{ sTitle: 'Employee' },
{ sTitle: 'User Level' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden', validation: '' }],
['username', { label: 'User Name', type: 'text', validation: 'username' }],
['email', { label: 'Email', type: 'text', validation: 'email' }],
['employee', {
label: 'Employee', type: 'select2', 'allow-null': true, 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
['user_level', { label: 'User Level', type: 'select', source: [['Admin', 'Admin'], ['Manager', 'Manager'], ['Employee', 'Employee'], ['Other', 'Other']] }],
['user_roles', { label: 'User Roles', type: 'select2multi', 'remote-source': ['UserRole', 'id', 'name'] }],
['lang', {
label: 'Language', type: 'select2', 'allow-null': true, 'remote-source': ['SupportedLanguage', 'id', 'description'],
}],
['default_module', {
label: 'Default Module', type: 'select2', 'null-label': 'No Default Module', 'allow-null': true, 'remote-source': ['Module', 'id', 'menu+label'],
}],
];
}
postRenderForm(object, $tempDomObj) {
if (object == null || object === undefined) {
$tempDomObj.find('#changePasswordBtn').remove();
}
}
changePassword() {
$('#adminUsersModel').modal('show');
$('#adminUsersChangePwd #newpwd').val('');
$('#adminUsersChangePwd #conpwd').val('');
}
saveUserSuccessCallBack(callBackData, serverData) {
const user = callBackData[0];
if (callBackData[1]) {
this.showMessage('Create User', `An email has been sent to ${user.email} with a temporary password to login to IceHrm.`);
} else {
this.showMessage('Create User', 'User created successfully. But there was a problem sending welcome email.');
}
this.get([]);
}
saveUserFailCallBack(callBackData, serverData) {
this.showMessage('Error', callBackData);
}
doCustomValidation(params) {
let msg = null;
if ((params.user_level !== 'Admin' && params.user_level !== 'Other') && params.employee === 'NULL') {
msg = 'For this user type, you have to assign an employee when adding or editing the user.<br/>';
msg += " You may create a new employee through 'Admin'->'Employees' menu";
}
return msg;
}
save() {
const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' });
if (validator.checkValues()) {
const params = validator.getFormParameters();
const msg = this.doCustomValidation(params);
if (msg == null) {
const id = $(`#${this.getTableName()}_submit #id`).val();
params.csrf = $(`#${this.getTableName()}Form`).data('csrf');
if (id != null && id !== undefined && id !== '') {
params.id = id;
this.add(params, []);
} else {
const reqJson = JSON.stringify(params);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'saveUserSuccessCallBack';
callBackData.callBackFail = 'saveUserFailCallBack';
this.customAction('saveUser', 'admin=users', reqJson, callBackData);
}
} else {
// $("#"+this.getTableName()+'Form .label').html(msg);
// $("#"+this.getTableName()+'Form .label').show();
this.showMessage('Error Saving User', msg);
}
}
}
changePasswordConfirm() {
$('#adminUsersChangePwd_error').hide();
const passwordValidation = function (str) {
return str.length > 7;
};
const password = $('#adminUsersChangePwd #newpwd').val();
if (!passwordValidation(password)) {
$('#adminUsersChangePwd_error').html('Password should be longer than 7 characters');
$('#adminUsersChangePwd_error').show();
return;
}
const conPassword = $('#adminUsersChangePwd #conpwd').val();
if (conPassword !== password) {
$('#adminUsersChangePwd_error').html("Passwords don't match");
$('#adminUsersChangePwd_error').show();
return;
}
const req = { id: this.currentId, pwd: conPassword };
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'changePasswordSuccessCallBack';
callBackData.callBackFail = 'changePasswordFailCallBack';
this.customAction('changePassword', 'admin=users', reqJson, callBackData);
}
closeChangePassword() {
$('#adminUsersModel').modal('hide');
}
changePasswordSuccessCallBack(callBackData, serverData) {
this.closeChangePassword();
this.showMessage('Password Change', 'Password changed successfully');
}
changePasswordFailCallBack(callBackData, serverData) {
this.closeChangePassword();
this.showMessage('Error', callBackData);
}
}
/**
* UserRoleAdapter
*/
class UserRoleAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
];
}
postRenderForm(object, $tempDomObj) {
$tempDomObj.find('#changePasswordBtn').remove();
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
}
module.exports = {
UserAdapter,
UserRoleAdapter,
};
+497
View File
@@ -0,0 +1,497 @@
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* AES implementation in JavaScript (c) Chris Veness 2005-2014 / MIT Licence */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* jshint node:true *//* global define */
/**
* AES (Rijndael cipher) encryption routines,
*
* Reference implementation of FIPS-197 http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf.
*
* @namespace
*/
var Aes = {};
/**
* AES Cipher function: encrypt 'input' state with Rijndael algorithm [§5.1];
* applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage.
*
* @param {number[]} input - 16-byte (128-bit) input state array.
* @param {number[][]} w - Key schedule as 2D byte-array (Nr+1 x Nb bytes).
* @returns {number[]} Encrypted output state array.
*/
Aes.cipher = function (input, w) {
const Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
const Nr = w.length / Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
let state = [[], [], [], []]; // initialise 4xNb byte-array 'state' with input [§3.4]
for (var i = 0; i < 4 * Nb; i++) state[i % 4][Math.floor(i / 4)] = input[i];
state = Aes.addRoundKey(state, w, 0, Nb);
for (let round = 1; round < Nr; round++) {
state = Aes.subBytes(state, Nb);
state = Aes.shiftRows(state, Nb);
state = Aes.mixColumns(state, Nb);
state = Aes.addRoundKey(state, w, round, Nb);
}
state = Aes.subBytes(state, Nb);
state = Aes.shiftRows(state, Nb);
state = Aes.addRoundKey(state, w, Nr, Nb);
const output = new Array(4 * Nb); // convert state to 1-d array before returning [§3.4]
for (var i = 0; i < 4 * Nb; i++) output[i] = state[i % 4][Math.floor(i / 4)];
return output;
};
/**
* Perform key expansion to generate a key schedule from a cipher key [§5.2].
*
* @param {number[]} key - Cipher key as 16/24/32-byte array.
* @returns {number[][]} Expanded key schedule as 2D byte-array (Nr+1 x Nb bytes).
*/
Aes.keyExpansion = function (key) {
const Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
const Nk = key.length / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
const Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
const w = new Array(Nb * (Nr + 1));
let temp = new Array(4);
// initialise first Nk words of expanded key with cipher key
for (var i = 0; i < Nk; i++) {
const r = [key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]];
w[i] = r;
}
// expand the key into the remainder of the schedule
for (var i = Nk; i < (Nb * (Nr + 1)); i++) {
w[i] = new Array(4);
for (var t = 0; t < 4; t++) temp[t] = w[i - 1][t];
// each Nk'th word has extra transformation
if (i % Nk == 0) {
temp = Aes.subWord(Aes.rotWord(temp));
for (var t = 0; t < 4; t++) temp[t] ^= Aes.rCon[i / Nk][t];
}
// 256-bit key has subWord applied every 4th word
else if (Nk > 6 && i % Nk == 4) {
temp = Aes.subWord(temp);
}
// xor w[i] with w[i-1] and w[i-Nk]
for (var t = 0; t < 4; t++) w[i][t] = w[i - Nk][t] ^ temp[t];
}
return w;
};
/**
* Apply SBox to state S [§5.1.1]
* @private
*/
Aes.subBytes = function (s, Nb) {
for (let r = 0; r < 4; r++) {
for (let c = 0; c < Nb; c++) s[r][c] = Aes.sBox[s[r][c]];
}
return s;
};
/**
* Shift row r of state S left by r bytes [§5.1.2]
* @private
*/
Aes.shiftRows = function (s, Nb) {
const t = new Array(4);
for (let r = 1; r < 4; r++) {
for (var c = 0; c < 4; c++) t[c] = s[r][(c + r) % Nb]; // shift into temp copy
for (var c = 0; c < 4; c++) s[r][c] = t[c]; // and copy back
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
return s; // see asmaes.sourceforge.net/rijndael/rijndaelImplementation.pdf
};
/**
* Combine bytes of each col of state S [§5.1.3]
* @private
*/
Aes.mixColumns = function (s, Nb) {
for (let c = 0; c < 4; c++) {
const a = new Array(4); // 'a' is a copy of the current column from 's'
const b = new Array(4); // 'b' is a•{02} in GF(2^8)
for (let i = 0; i < 4; i++) {
a[i] = s[i][c];
b[i] = s[i][c] & 0x80 ? s[i][c] << 1 ^ 0x011b : s[i][c] << 1;
}
// a[n] ^ b[n] is a•{03} in GF(2^8)
s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // {02}•a0 + {03}•a1 + a2 + a3
s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 • {02}•a1 + {03}•a2 + a3
s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + {02}•a2 + {03}•a3
s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // {03}•a0 + a1 + a2 + {02}•a3
}
return s;
};
/**
* Xor Round Key into state S [§5.1.4]
* @private
*/
Aes.addRoundKey = function (state, w, rnd, Nb) {
for (let r = 0; r < 4; r++) {
for (let c = 0; c < Nb; c++) state[r][c] ^= w[rnd * 4 + c][r];
}
return state;
};
/**
* Apply SBox to 4-byte word w
* @private
*/
Aes.subWord = function (w) {
for (let i = 0; i < 4; i++) w[i] = Aes.sBox[w[i]];
return w;
};
/**
* Rotate 4-byte word w left by one byte
* @private
*/
Aes.rotWord = function (w) {
const tmp = w[0];
for (let i = 0; i < 3; i++) w[i] = w[i + 1];
w[3] = tmp;
return w;
};
// sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [§5.1.1]
Aes.sBox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16];
// rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
Aes.rCon = [[0x00, 0x00, 0x00, 0x00],
[0x01, 0x00, 0x00, 0x00],
[0x02, 0x00, 0x00, 0x00],
[0x04, 0x00, 0x00, 0x00],
[0x08, 0x00, 0x00, 0x00],
[0x10, 0x00, 0x00, 0x00],
[0x20, 0x00, 0x00, 0x00],
[0x40, 0x00, 0x00, 0x00],
[0x80, 0x00, 0x00, 0x00],
[0x1b, 0x00, 0x00, 0x00],
[0x36, 0x00, 0x00, 0x00]];
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if (typeof module !== 'undefined' && module.exports) module.exports = Aes; // CommonJs export
if (typeof define === 'function' && define.amd) define([], () => Aes); // AMD
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* AES Counter-mode implementation in JavaScript (c) Chris Veness 2005-2014 / MIT Licence */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* jshint node:true *//* global define, escape, unescape, btoa, atob */
'use strict';
if (typeof module !== 'undefined' && module.exports) var Aes = require('./aes'); // CommonJS (Node.js)
/**
* Aes.Ctr: Counter-mode (CTR) wrapper for AES.
*
* This encrypts a Unicode string to produces a base64 ciphertext using 128/192/256-bit AES,
* and the converse to decrypt an encrypted ciphertext.
*
* See http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*
* @augments Aes
*/
Aes.Ctr = {};
/**
* Encrypt a text using AES encryption in Counter mode of operation.
*
* Unicode multi-byte character safe
*
* @param {string} plaintext - Source text to be encrypted.
* @param {string} password - The password to use to generate a key.
* @param {number} nBits - Number of bits to be used in the key; 128 / 192 / 256.
* @returns {string} Encrypted text.
*
* @example
* var encr = Aes.Ctr.encrypt('big secret', 'pāşšŵōřđ', 256); // encr: 'lwGl66VVwVObKIr6of8HVqJr'
*/
Aes.Ctr.encrypt = function (plaintext, password, nBits) {
const blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
if (!(nBits == 128 || nBits == 192 || nBits == 256)) return ''; // standard allows 128/192/256 bit keys
plaintext = String(plaintext).utf8Encode();
password = String(password).utf8Encode();
// use AES itself to encrypt password to get cipher key (using plain password as source for key
// expansion) - gives us well encrypted key (though hashed key might be preferred for prod'n use)
const nBytes = nBits / 8; // no bytes in key (16/24/32)
const pwBytes = new Array(nBytes);
for (var i = 0; i < nBytes; i++) { // use 1st 16/24/32 chars of password for key
pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
}
let key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); // gives us 16-byte key
key = key.concat(key.slice(0, nBytes - 16)); // expand key to 16/24/32 bytes long
// initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A §B.2): [0-1] = millisec,
// [2-3] = random, [4-7] = seconds, together giving full sub-millisec uniqueness up to Feb 2106
const counterBlock = new Array(blockSize);
const nonce = (new Date()).getTime(); // timestamp: milliseconds since 1-Jan-1970
const nonceMs = nonce % 1000;
const nonceSec = Math.floor(nonce / 1000);
const nonceRnd = Math.floor(Math.random() * 0xffff);
// for debugging: nonce = nonceMs = nonceSec = nonceRnd = 0;
for (var i = 0; i < 2; i++) counterBlock[i] = (nonceMs >>> i * 8) & 0xff;
for (var i = 0; i < 2; i++) counterBlock[i + 2] = (nonceRnd >>> i * 8) & 0xff;
for (var i = 0; i < 4; i++) counterBlock[i + 4] = (nonceSec >>> i * 8) & 0xff;
// and convert it to a string to go on the front of the ciphertext
let ctrTxt = '';
for (var i = 0; i < 8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
// generate key schedule - an expansion of the key into distinct Key Rounds for each round
const keySchedule = Aes.keyExpansion(key);
const blockCount = Math.ceil(plaintext.length / blockSize);
const ciphertxt = new Array(blockCount); // ciphertext as array of strings
for (let b = 0; b < blockCount; b++) {
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
// done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
for (var c = 0; c < 4; c++) counterBlock[15 - c] = (b >>> c * 8) & 0xff;
for (var c = 0; c < 4; c++) counterBlock[15 - c - 4] = (b / 0x100000000 >>> c * 8);
const cipherCntr = Aes.cipher(counterBlock, keySchedule); // -- encrypt counter block --
// block size is reduced on final block
const blockLength = b < blockCount - 1 ? blockSize : (plaintext.length - 1) % blockSize + 1;
const cipherChar = new Array(blockLength);
for (var i = 0; i < blockLength; i++) { // -- xor plaintext with ciphered counter char-by-char --
cipherChar[i] = cipherCntr[i] ^ plaintext.charCodeAt(b * blockSize + i);
cipherChar[i] = String.fromCharCode(cipherChar[i]);
}
ciphertxt[b] = cipherChar.join('');
}
// use Array.join() for better performance than repeated string appends
let ciphertext = ctrTxt + ciphertxt.join('');
ciphertext = ciphertext.base64Encode();
return ciphertext;
};
/**
* Decrypt a text encrypted by AES in counter mode of operation
*
* @param {string} ciphertext - Source text to be encrypted.
* @param {string} password - Password to use to generate a key.
* @param {number} nBits - Number of bits to be used in the key; 128 / 192 / 256.
* @returns {string} Decrypted text
*
* @example
* var decr = Aes.Ctr.encrypt('lwGl66VVwVObKIr6of8HVqJr', 'pāşšŵōřđ', 256); // decr: 'big secret'
*/
Aes.Ctr.decrypt = function (ciphertext, password, nBits) {
const blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
if (!(nBits == 128 || nBits == 192 || nBits == 256)) return ''; // standard allows 128/192/256 bit keys
ciphertext = String(ciphertext).base64Decode();
password = String(password).utf8Encode();
// use AES to encrypt password (mirroring encrypt routine)
const nBytes = nBits / 8; // no bytes in key
const pwBytes = new Array(nBytes);
for (var i = 0; i < nBytes; i++) {
pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
}
let key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes));
key = key.concat(key.slice(0, nBytes - 16)); // expand key to 16/24/32 bytes long
// recover nonce from 1st 8 bytes of ciphertext
const counterBlock = new Array(8);
const ctrTxt = ciphertext.slice(0, 8);
for (var i = 0; i < 8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
// generate key schedule
const keySchedule = Aes.keyExpansion(key);
// separate ciphertext into blocks (skipping past initial 8 bytes)
const nBlocks = Math.ceil((ciphertext.length - 8) / blockSize);
const ct = new Array(nBlocks);
for (var b = 0; b < nBlocks; b++) ct[b] = ciphertext.slice(8 + b * blockSize, 8 + b * blockSize + blockSize);
ciphertext = ct; // ciphertext is now array of block-length strings
// plaintext will get generated block-by-block into array of block-length strings
const plaintxt = new Array(ciphertext.length);
for (var b = 0; b < nBlocks; b++) {
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
for (var c = 0; c < 4; c++) counterBlock[15 - c] = ((b) >>> c * 8) & 0xff;
for (var c = 0; c < 4; c++) counterBlock[15 - c - 4] = (((b + 1) / 0x100000000 - 1) >>> c * 8) & 0xff;
const cipherCntr = Aes.cipher(counterBlock, keySchedule); // encrypt counter block
const plaintxtByte = new Array(ciphertext[b].length);
for (var i = 0; i < ciphertext[b].length; i++) {
// -- xor plaintxt with ciphered counter byte-by-byte --
plaintxtByte[i] = cipherCntr[i] ^ ciphertext[b].charCodeAt(i);
plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]);
}
plaintxt[b] = plaintxtByte.join('');
}
// join array of blocks into single plaintext string
let plaintext = plaintxt.join('');
plaintext = plaintext.utf8Decode(); // decode from UTF8 back to Unicode multi-byte chars
return plaintext;
};
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/** Extend String object with method to encode multi-byte string to utf8
* - monsur.hossa.in/2012/07/20/utf-8-in-javascript.html */
if (typeof String.prototype.utf8Encode === 'undefined') {
String.prototype.utf8Encode = function () {
return unescape(encodeURIComponent(this));
};
}
/** Extend String object with method to decode utf8 string to multi-byte */
if (typeof String.prototype.utf8Decode === 'undefined') {
String.prototype.utf8Decode = function () {
try {
return decodeURIComponent(escape(this));
} catch (e) {
return this; // invalid UTF-8? return as-is
}
};
}
/** Extend String object with method to encode base64
* - developer.mozilla.org/en-US/docs/Web/API/window.btoa, nodejs.org/api/buffer.html
* note: if btoa()/atob() are not available (eg IE9-), try github.com/davidchambers/Base64.js */
if (typeof String.prototype.base64Encode === 'undefined') {
String.prototype.base64Encode = function () {
if (typeof btoa !== 'undefined') return btoa(this); // browser
if (typeof Buffer !== 'undefined') return new Buffer(this, 'utf8').toString('base64'); // Node.js
throw new Error('No Base64 Encode');
};
}
/** Extend String object with method to decode base64 */
if (typeof String.prototype.base64Decode === 'undefined') {
String.prototype.base64Decode = function () {
if (typeof atob !== 'undefined') return atob(this); // browser
if (typeof Buffer !== 'undefined') return new Buffer(this, 'base64').toString('utf8'); // Node.js
throw new Error('No Base64 Decode');
};
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if (typeof module !== 'undefined' && module.exports) module.exports = Aes.Ctr; // CommonJs export
if (typeof define === 'function' && define.amd) define(['Aes'], () => Aes.Ctr); // AMD
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Encrypt/decrypt files */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
function encryptFile(file) {
// use FileReader.readAsArrayBuffer to handle binary files
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (evt) {
$('body').css({ cursor: 'wait' });
// Aes.Ctr.encrypt expects a string, but converting binary file directly to string could
// give invalid Unicode sequences, so convert bytestream ArrayBuffer to single-byte chars
const contentBytes = new Uint8Array(reader.result); // ≡ evt.target.result
let contentStr = '';
for (let i = 0; i < contentBytes.length; i++) {
contentStr += String.fromCharCode(contentBytes[i]);
}
const password = $('#password-file').val();
const t1 = new Date();
const ciphertext = Aes.Ctr.encrypt(contentStr, password, 256);
const t2 = new Date();
// use Blob to save encrypted file
const blob = new Blob([ciphertext], { type: 'text/plain' });
const filename = `${file.name}.encrypted`;
saveAs(blob, filename);
$('#encrypt-file-time').html(`${(t2 - t1) / 1000}s`); // display time taken
$('body').css({ cursor: 'default' });
};
}
function decryptFile(file) {
// use FileReader.ReadAsText to read (base64-encoded) ciphertext file
const reader = new FileReader();
reader.readAsText(file);
reader.onload = function (evt) {
$('body').css({ cursor: 'wait' });
const content = reader.result; // ≡ evt.target.result
const password = $('#password-file').val();
const t1 = new Date();
const plaintext = Aes.Ctr.decrypt(content, password, 256);
const t2 = new Date();
// convert single-byte character stream to ArrayBuffer bytestream
const contentBytes = new Uint8Array(plaintext.length);
for (let i = 0; i < plaintext.length; i++) {
contentBytes[i] = plaintext.charCodeAt(i);
}
// use Blob to save decrypted file
const blob = new Blob([contentBytes], { type: 'application/octet-stream' });
const filename = `${file.name.replace(/\.encrypted$/, '')}.decrypted`;
saveAs(blob, filename);
$('#decrypt-file-time').html(`${(t2 - t1) / 1000}s`); // display time taken
$('body').css({ cursor: 'default' });
};
}
export default Aes;
+124
View File
@@ -0,0 +1,124 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
class NotificationManager {
constructor() {
this.baseUrl = '';
this.templates = {};
}
setBaseUrl(url) {
this.baseUrl = url;
}
setTemplates(data) {
this.templates = data;
}
setTimeUtils(timeUtils) {
this.timeUtils = timeUtils;
}
getNotifications(name, data) {
const that = this;
$.getJSON(this.baseUrl, { a: 'getNotifications' }, (_data) => {
if (_data.status === 'SUCCESS') {
that.renderNotifications(_data.data[1], _data.data[0]);
}
});
}
clearPendingNotifications(name, data) {
const that = this;
$.getJSON(this.baseUrl, { a: 'clearNotifications' }, (_data) => {
});
}
renderNotifications(notifications, unreadCount) {
if (notifications.length === 0) {
return;
}
let t = this.templates.notifications;
if (unreadCount > 0) {
t = t.replace('#_count_#', unreadCount);
if (unreadCount > 1) {
t = t.replace('#_header_#', `You have ${unreadCount} new notifications`);
} else {
t = t.replace('#_header_#', `You have ${unreadCount} new notification`);
}
} else {
t = t.replace('#_count_#', '');
t = t.replace('#_header_#', 'You have no new notifications');
}
let notificationStr = '';
for (const index in notifications) {
notificationStr += this.renderNotification(notifications[index]);
}
t = t.replace('#_notifications_#', notificationStr);
const $obj = $(t);
if (unreadCount === 0) {
$obj.find('.label-danger').remove();
}
$obj.attr('id', 'notifications');
const k = $('#notifications');
k.replaceWith($obj);
$('.navbar .menu').slimscroll({
height: '320px',
alwaysVisible: false,
size: '3px',
}).css('width', '100%');
this.timeUtils.convertToRelativeTime($('.notificationTime'));
}
renderNotification(notification) {
let t = this.templates.notification;
t = t.replace('#_image_#', notification.image);
try {
const json = JSON.parse(notification.action);
t = t.replace('#_url_#', this.baseUrl.replace('service.php', '?') + json.url);
} catch (e) {
t = t.replace('#_url_#', '');
}
t = t.replace('#_time_#', notification.time);
t = t.replace('#_fromName_#', notification.type);
t = t.replace('#_message_#', this.getLineBreakString(notification.message, 27));
return t;
}
getLineBreakString(str, len) {
let t = '';
try {
const arr = str.split(' ');
let count = 0;
for (let i = 0; i < arr.length; i++) {
count += arr[i].length + 1;
if (count > len) {
t += `${arr[i]}<br/>`;
count = 0;
} else {
t += `${arr[i]} `;
}
}
} catch (e) {
// Do nothing
}
return t;
}
}
export default NotificationManager;
+69
View File
@@ -0,0 +1,69 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/**
* RequestCache
*/
class RequestCache {
getKey(url, params) {
let key = `${url}|`;
for (const index in params) {
key += `${index}=${params[index]}|`;
}
return key;
}
invalidateTable(table) {
let key;
for (let i = 0; i < localStorage.length; i++) {
key = localStorage.key(i);
if (key.indexOf(`t=${table}`) > 0) {
localStorage.removeItem(key);
}
}
}
getData(key) {
let data;
if (typeof (Storage) === 'undefined') {
return null;
}
const strData = localStorage.getItem(key);
if (strData !== undefined && strData != null && strData !== '') {
data = JSON.parse(strData);
if (data === undefined || data == null) {
return null;
}
if (data.status !== undefined && data.status != null && data.status !== 'SUCCESS') {
return null;
}
return data;
}
return null;
}
setData(key, data) {
if (typeof (Storage) === 'undefined') {
return null;
}
if (data.status !== undefined && data.status != null && data.status !== 'SUCCESS') {
return null;
}
const strData = JSON.stringify(data);
localStorage.setItem(key, strData);
return strData;
}
}
export default RequestCache;
+143
View File
@@ -0,0 +1,143 @@
/* eslint-disable camelcase,brace-style */
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
class TimeUtils {
setServerGMToffset(serverGMToffset) {
this.serverGMToffset = serverGMToffset;
}
getMySQLFormatDate(date) {
const format = function (val) {
if (val < 10) { return `0${val}`; }
return val;
};
return `${date.getUTCFullYear()}-${format(date.getUTCMonth() + 1)}-${format(date.getUTCDate())}`;
}
convertToRelativeTime(selector) {
const that = this;
const getAmPmTime = function (curHour, curMin) {
let amPm = 'am';
let amPmHour = curHour;
if (amPmHour >= 12) {
amPm = 'pm';
if (amPmHour > 12) {
amPmHour -= 12;
}
}
let prefixCurMin = '';
if (curMin < 10) {
prefixCurMin = '0';
}
let prefixCurHour = '';
if (curHour === 0) {
prefixCurHour = '0';
}
return ` at ${prefixCurHour}${amPmHour}:${prefixCurMin}${curMin}${amPm}`;
};
const getBrowserTimeZone = function () {
const current_date = new Date();
const gmt_offset = current_date.getTimezoneOffset() / 60;
return -gmt_offset;
};
const curDate = new Date();
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const timezoneDiff = this.serverGMToffset - getBrowserTimeZone();
const timezoneTimeDiff = timezoneDiff * 60 * 60 * 1000;
selector.each(function () {
try {
const thisValue = $(this).html();
// Split value into date and time
const thisValueArray = thisValue.split(' ');
const thisValueDate = thisValueArray[0];
const thisValueTime = thisValueArray[1];
// Split date into components
const thisValueDateArray = thisValueDate.split('-');
const curYear = thisValueDateArray[0];
const curMonth = thisValueDateArray[1] - 1;
const curDay = thisValueDateArray[2];
// Split time into components
const thisValueTimeArray = thisValueTime.split(':');
const curHour = thisValueTimeArray[0];
const curMin = thisValueTimeArray[1];
const curSec = thisValueTimeArray[2];
// Create this date
const thisDate = new Date(curYear, curMonth, curDay, curHour, curMin, curSec);
const thisTime = thisDate.getTime();
const tzDate = new Date(thisTime - timezoneTimeDiff);
// var tzDay = tzDate.getDay();//getDay will return the day of the week not the month
// var tzDay = tzDate.getUTCDate(); //getUTCDate will return the day of the month
const tzDay = tzDate.toString('d'); //
const tzYear = tzDate.getFullYear();
const tzHour = tzDate.getHours();
const tzMin = tzDate.getMinutes();
// Create the full date
// var fullDate = days[tzDate.getDay()] + ", " + months[tzDate.getMonth()] + " " + tzDay + ", " + tzYear + getAmPmTime(tzHour, tzMin);
const fullDate = `${days[tzDate.getDay()]}, ${months[tzDate.getMonth()]} ${tzDay}, ${tzYear}${getAmPmTime(tzHour, tzMin)}`;
// Get the time different
const timeDiff = (curDate.getTime() - tzDate.getTime()) / 1000;
const minDiff = Math.abs(timeDiff / 60);
const hourDiff = Math.abs(timeDiff / (60 * 60));
const dayDiff = Math.abs(timeDiff / (60 * 60 * 24));
const yearDiff = Math.abs(timeDiff / (60 * 60 * 24 * 365));
// If more than a day old, display the month, day and time (and year, if applicable)
let fbDate = '';
if (dayDiff > 1) {
// fbDate = curDay + " " + months[tzDate.getMonth()].substring(0,3);
fbDate = `${tzDay} ${months[tzDate.getMonth()].substring(0, 3)}`;
// Add the year, if applicable
if (yearDiff > 1) {
fbDate = `${fbDate} ${curYear}`;
}
// Add the time
fbDate += getAmPmTime(tzHour, tzMin);
}
// Less than a day old, and more than an hour old
else if (hourDiff >= 1) {
const roundedHour = Math.round(hourDiff);
if (roundedHour === 1) fbDate = 'about an hour ago';
else fbDate = `${roundedHour} hours ago`;
}
// Less than an hour, and more than a minute
else if (minDiff >= 1) {
const roundedMin = Math.round(minDiff);
if (roundedMin === 1) fbDate = 'about a minute ago';
else fbDate = `${roundedMin} minutes ago`;
}
// Less than a minute
else if (minDiff < 1) {
fbDate = 'less than a minute ago';
}
// Update this element
$(this).html(fbDate);
$(this).attr('title', fullDate);
} catch (e) {
// Do nothing
}
});
}
}
export default TimeUtils;
+184
View File
@@ -0,0 +1,184 @@
var uploadId="";
var uploadAttr="";
var popupUpload = null;
function showUploadDialog(id,msg,group,user,postUploadId,postUploadAttr,postUploadResultAttr,fileType){
var ts = Math.round((new Date()).getTime() / 1000);
uploadId = postUploadId;
uploadAttr = postUploadAttr;
uploadResultAttr = postUploadResultAttr;
var html='<div><iframe src="'+CLIENT_BASE_URL+'fileupload_page.php?id=_id_&msg=_msg_&file_group=_file_group_&file_type=_file_type_&user=_user_" frameborder="0" scrolling="no" width="300px" height="55px"></iframe></div>';
var html = html.replace(/_id_/g,id);
var html = html.replace(/_msg_/g,msg);
var html = html.replace(/_file_group_/g,group);
var html = html.replace(/_user_/g,user);
var html = html.replace(/_file_type_/g,fileType);
modJs.renderModel('upload',"Upload File",html);
$('#uploadModel').modal('show');
}
function closeUploadDialog(success,error,data){
var arr = data.split("|");
var file = arr[0];
var fileBaseName = arr[1];
var fileId = arr[2];
if(success == 1){
//popupUpload.close();
$('#uploadModel').modal('hide');
if(uploadResultAttr == "url"){
if(uploadAttr == "val"){
$('#'+uploadId).val(file);
}else if(uploadAttr == "html"){
$('#'+uploadId).html(file);
}else{
$('#'+uploadId).attr(uploadAttr,file);
}
}else if(uploadResultAttr == "name"){
if(uploadAttr == "val"){
$('#'+uploadId).val(fileBaseName);
}else if(uploadAttr == "html"){
$('#'+uploadId).html(fileBaseName);
$('#'+uploadId).attr("val",fileBaseName);
}else{
$('#'+uploadId).attr(uploadAttr,fileBaseName);
}
$('#'+uploadId).show();
$('#'+uploadId+"_download").show();
$('#'+uploadId+"_remove").show();
}else if(uploadResultAttr == "id"){
if(uploadAttr == "val"){
$('#'+uploadId).attr(uploadAttr,fileId);
}else if(uploadAttr == "html"){
$('#'+uploadId).html(fileBaseName);
$('#'+uploadId).attr("val",fileId);
}else{
$('#'+uploadId).attr(uploadAttr,fileId);
}
$('#'+uploadId).show();
$('#'+uploadId+"_download").show();
$('#'+uploadId+"_remove").show();
}
}else{
//popupUpload.close();
$('#uploadModel').modal('hide');
}
}
function download(name, closeCallback, closeCallbackData){
var successCallback = function(data){
var link;
var fileParts;
var viewableImages = ["png","jpg","gif","bmp","jpge"];
var viewableFiles = ["pdf","xml"];
$('.modal').modal('hide');
if(data['filename'].indexOf("https:") == 0 || data['filename'].indexOf("http:") == 0){
fileParts = data['filename'].split("?");
fileParts = fileParts[0].split(".");
if(jQuery.inArray(fileParts[fileParts.length - 1], viewableFiles ) >= 0) {
var win = window.open(data['filename'], '_blank');
win.focus();
}else{
link = '<a href="'+data['filename']+'" target="_blank">Download File <i class="icon-download-alt"></i> </a>';
if(jQuery.inArray(fileParts[fileParts.length - 1], viewableImages ) >= 0) {
link += '<br/><br/><img style="max-width:545px;max-height:350px;" src="'+data['filename']+'"/>';
}
modJs.showMessage("Download File Attachment",link,closeCallback,closeCallbackData);
}
}else{
fileParts = data['filename'].split(".");
link = '<a href="'+modJs.getCustomActionUrl("download",{'file':data['filename']})+'" target="_blank">Download File <i class="icon-download-alt"></i> </a>';
if(jQuery.inArray(fileParts[fileParts.length - 1], viewableImages ) >= 0) {
link += '<br/><br/><img style="max-width:545px;max-height:350px;" src="'+modJs.getClientDataUrl()+data['filename']+'"/>';
}
modJs.showMessage("Download File Attachment",link,closeCallback,closeCallbackData);
}
};
var failCallback = function(data){
modJs.showMessage("Error Downloading File","File not found");
};
modJs.sendCustomRequest("file",{'name':name},successCallback,failCallback);
}
function randomString(length){
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');
if (! length) {
length = Math.floor(Math.random() * chars.length);
}
var str = '';
for (var i = 0; i < length; i++) {
str += chars[Math.floor(Math.random() * chars.length)];
}
return str;
}
function verifyInstance(key){
var object = {};
object['a'] = "verifyInstance";
object['key'] = key;
$.post(this.baseUrl, object, function(data) {
if(data.status == "SUCCESS"){
$("#verifyModel").hide();
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
alert("Success: Instance Verified");
}else{
alert("Error: "+data.message);
}
},"json");
}
function nl2br(str, is_xhtml) {
// discuss at: http://phpjs.org/functions/nl2br/
// original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// improved by: Philip Peterson
// improved by: Onno Marsman
// improved by: Atli r
// improved by: Brett Zamir (http://brett-zamir.me)
// improved by: Maximusya
// bugfixed by: Onno Marsman
// bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// input by: Brett Zamir (http://brett-zamir.me)
// example 1: nl2br('Kevin\nvan\nZonneveld');
// returns 1: 'Kevin<br />\nvan<br />\nZonneveld'
// example 2: nl2br("\nOne\nTwo\n\nThree\n", false);
// returns 2: '<br>\nOne<br>\nTwo<br>\n<br>\nThree<br>\n'
// example 3: nl2br("\nOne\nTwo\n\nThree\n", true);
// returns 3: '<br />\nOne<br />\nTwo<br />\n<br />\nThree<br />\n'
var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br ' + '/>' : '<br>'; // Adjust comment to avoid issue on phpjs.org display
return (str + '')
.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
}
function updateLanguage(language) {
var object = {};
object['a'] = "updateLanguage";
object['language'] = language;
$.post(this.baseUrl, object, function(data) {
if(data.status == "SUCCESS"){
location.reload();
} else {
alert("Error occurred while changing language");
}
},"json");
}
@@ -0,0 +1,250 @@
/* Set the defaults for DataTables initialisation */
$.extend( true, $.fn.dataTable.defaults, {
"sDom":
"<'row'<'col-xs-6'l><'col-xs-6'f>r>"+
"t"+
"<'row'<'col-xs-6'i><'col-xs-6'p>>",
"oLanguage": {
"sLengthMenu": "_MENU_ records per page"
}
} );
/* Default class modification */
$.extend( $.fn.dataTableExt.oStdClasses, {
"sWrapper": "dataTables_wrapper form-inline",
"sFilterInput": "form-control input-sm",
"sLengthSelect": "form-control input-sm"
} );
// In 1.10 we use the pagination renderers to draw the Bootstrap paging,
// rather than custom plug-in
if ( $.fn.dataTable.Api ) {
$.fn.dataTable.defaults.renderer = 'bootstrap';
$.fn.dataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
var api = new $.fn.dataTable.Api( settings );
var classes = settings.oClasses;
var lang = settings.oLanguage.oPaginate;
var btnDisplay, btnClass;
var attach = function( container, buttons ) {
var i, ien, node, button;
var clickHandler = function ( e ) {
e.preventDefault();
if ( e.data.action !== 'ellipsis' ) {
api.page( e.data.action ).draw( false );
}
};
for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
button = buttons[i];
if ( $.isArray( button ) ) {
attach( container, button );
}
else {
btnDisplay = '';
btnClass = '';
switch ( button ) {
case 'ellipsis':
btnDisplay = '&hellip;';
btnClass = 'disabled';
break;
case 'first':
btnDisplay = lang.sFirst;
btnClass = button + (page > 0 ?
'' : ' disabled');
break;
case 'previous':
btnDisplay = lang.sPrevious;
btnClass = button + (page > 0 ?
'' : ' disabled');
break;
case 'next':
btnDisplay = lang.sNext;
btnClass = button + (page < pages-1 ?
'' : ' disabled');
break;
case 'last':
btnDisplay = lang.sLast;
btnClass = button + (page < pages-1 ?
'' : ' disabled');
break;
default:
btnDisplay = button + 1;
btnClass = page === button ?
'active' : '';
break;
}
if ( btnDisplay ) {
node = $('<li>', {
'class': classes.sPageButton+' '+btnClass,
'aria-controls': settings.sTableId,
'tabindex': settings.iTabIndex,
'id': idx === 0 && typeof button === 'string' ?
settings.sTableId +'_'+ button :
null
} )
.append( $('<a>', {
'href': '#'
} )
.html( btnDisplay )
)
.appendTo( container );
settings.oApi._fnBindAction(
node, {action: button}, clickHandler
);
}
}
}
};
attach(
$(host).empty().html('<ul class="pagination"/>').children('ul'),
buttons
);
}
}
else {
// Integration for 1.9-
$.fn.dataTable.defaults.sPaginationType = 'bootstrap';
/* API method to get paging information */
$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
{
return {
"iStart": oSettings._iDisplayStart,
"iEnd": oSettings.fnDisplayEnd(),
"iLength": oSettings._iDisplayLength,
"iTotal": oSettings.fnRecordsTotal(),
"iFilteredTotal": oSettings.fnRecordsDisplay(),
"iPage": oSettings._iDisplayLength === -1 ?
0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
"iTotalPages": oSettings._iDisplayLength === -1 ?
0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
};
};
/* Bootstrap style pagination control */
$.extend( $.fn.dataTableExt.oPagination, {
"bootstrap": {
"fnInit": function( oSettings, nPaging, fnDraw ) {
var oLang = oSettings.oLanguage.oPaginate;
var fnClickHandler = function ( e ) {
e.preventDefault();
if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) {
fnDraw( oSettings );
}
};
$(nPaging).append(
'<ul class="pagination">'+
'<li class="prev disabled"><a href="#">&larr; '+oLang.sPrevious+'</a></li>'+
'<li class="next disabled"><a href="#">'+oLang.sNext+' &rarr; </a></li>'+
'</ul>'
);
var els = $('a', nPaging);
$(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
$(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
},
"fnUpdate": function ( oSettings, fnDraw ) {
var iListLength = 5;
var oPaging = oSettings.oInstance.fnPagingInfo();
var an = oSettings.aanFeatures.p;
var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);
if ( oPaging.iTotalPages < iListLength) {
iStart = 1;
iEnd = oPaging.iTotalPages;
}
else if ( oPaging.iPage <= iHalf ) {
iStart = 1;
iEnd = iListLength;
} else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
iStart = oPaging.iTotalPages - iListLength + 1;
iEnd = oPaging.iTotalPages;
} else {
iStart = oPaging.iPage - iHalf + 1;
iEnd = iStart + iListLength - 1;
}
for ( i=0, ien=an.length ; i<ien ; i++ ) {
// Remove the middle elements
$('li:gt(0)', an[i]).filter(':not(:last)').remove();
// Add the new list items and their event handlers
for ( j=iStart ; j<=iEnd ; j++ ) {
sClass = (j==oPaging.iPage+1) ? 'class="active"' : '';
$('<li '+sClass+'><a href="#">'+j+'</a></li>')
.insertBefore( $('li:last', an[i])[0] )
.bind('click', function (e) {
e.preventDefault();
oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
fnDraw( oSettings );
} );
}
// Add / remove disabled classes from the static elements
if ( oPaging.iPage === 0 ) {
$('li:first', an[i]).addClass('disabled');
} else {
$('li:first', an[i]).removeClass('disabled');
}
if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {
$('li:last', an[i]).addClass('disabled');
} else {
$('li:last', an[i]).removeClass('disabled');
}
}
}
}
} );
}
/*
* TableTools Bootstrap compatibility
* Required TableTools 2.1+
*/
if ( $.fn.DataTable.TableTools ) {
// Set the classes that TableTools uses to something suitable for Bootstrap
$.extend( true, $.fn.DataTable.TableTools.classes, {
"container": "DTTT btn-group",
"buttons": {
"normal": "btn btn-default",
"disabled": "disabled"
},
"collection": {
"container": "DTTT_dropdown dropdown-menu",
"buttons": {
"normal": "",
"disabled": "disabled"
}
},
"print": {
"info": "DTTT_print_info modal"
},
"select": {
"row": "active"
}
} );
// Have the collection use a bootstrap compatible dropdown
$.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
"collection": {
"container": "ul",
"button": "li",
"liner": "a"
}
} );
}
File diff suppressed because it is too large Load Diff
+28
View File
@@ -0,0 +1,28 @@
/* global timeUtils */
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import NotificationManager from './Notifications';
import TimeUtils from './TimeUtils';
import RequestCache from './RequestCache';
const Aes = require('./Aes');
window.RequestCache = RequestCache;
window.setupTimeUtils = (diffHoursBetweenServerTimezoneWithGMT) => {
const timeUtils = new TimeUtils();
timeUtils.setServerGMToffset(diffHoursBetweenServerTimezoneWithGMT);
return timeUtils;
};
window.setupNotifications = (baseUrl) => {
const notificationManager = new NotificationManager();
notificationManager.setBaseUrl(baseUrl);
notificationManager.setTimeUtils(timeUtils);
return notificationManager;
};
+134
View File
@@ -0,0 +1,134 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/**
* ApproveAdminAdapter
*/
import LogViewAdapter from './LogViewAdapter';
class ApproveAdminAdapter extends LogViewAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
}
getStatusFieldPosition() {
const dm = this.getDataMapping();
return dm.length - 1;
}
openStatus(id, status) {
$(`#${this.itemNameLower}StatusModel`).modal('show');
$(`#${this.itemNameLower}_status`).html(this.getStatusOptions(status));
$(`#${this.itemNameLower}_status`).val(status);
this.statusChangeId = id;
}
closeDialog() {
$(`#${this.itemNameLower}StatusModel`).modal('hide');
}
changeStatus() {
const status = $(`#${this.itemNameLower}_status`).val();
const reason = $(`#${this.itemNameLower}_reason`).val();
if (status == undefined || status == null || status == '') {
this.showMessage('Error', `Please select ${this.itemNameLower} status`);
return;
}
const object = { id: this.statusChangeId, status, reason };
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'changeStatusSuccessCallBack';
callBackData.callBackFail = 'changeStatusFailCallBack';
this.customAction('changeStatus', `admin=${this.modulePathName}`, reqJson, callBackData);
this.closeDialog();
this.statusChangeId = null;
}
changeStatusSuccessCallBack(callBackData) {
this.showMessage('Successful', `${this.itemName} Request status changed successfully`);
this.get([]);
}
changeStatusFailCallBack(callBackData) {
this.showMessage('Error', `Error occurred while changing ${this.itemName} request status`);
}
getActionButtonsHtml(id, data) {
const editButton = '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img>';
const deleteButton = '<img class="tableActionButton" src="_BASE_images/delete.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Delete" onclick="modJs.deleteRow(_id_);return false;"></img>';
const statusChangeButton = '<img class="tableActionButton" src="_BASE_images/run.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Change Status" onclick="modJs.openStatus(_id_, \'_cstatus_\');return false;"></img>';
const viewLogsButton = '<img class="tableActionButton" src="_BASE_images/log.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="View Logs" onclick="modJs.getLogs(_id_);return false;"></img>';
let html = '<div style="width:120px;">_edit__delete__status__logs_</div>';
const optiondata = this.getStatusOptionsData(data[this.getStatusFieldPosition()]);
if (Object.keys(optiondata).length > 0) {
html = html.replace('_status_', statusChangeButton);
} else {
html = html.replace('_status_', '');
}
html = html.replace('_logs_', viewLogsButton);
if (this.showDelete) {
html = html.replace('_delete_', deleteButton);
} else {
html = html.replace('_delete_', '');
}
if (this.showEdit) {
html = html.replace('_edit_', editButton);
} else {
html = html.replace('_edit_', '');
}
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
html = html.replace(/_cstatus_/g, data[this.getStatusFieldPosition()]);
return html;
}
isSubProfileTable() {
if (this.user.user_level == 'Admin') {
return false;
}
return true;
}
getStatusOptionsData(currentStatus) {
const data = {};
if (currentStatus == 'Approved') {
} else if (currentStatus == 'Pending') {
data.Approved = 'Approved';
data.Rejected = 'Rejected';
} else if (currentStatus == 'Rejected') {
} else if (currentStatus == 'Cancelled') {
} else if (currentStatus == 'Processing') {
} else {
data['Cancellation Requested'] = 'Cancellation Requested';
data.Cancelled = 'Cancelled';
}
return data;
}
getStatusOptions(currentStatus) {
return this.generateOptions(this.getStatusOptionsData(currentStatus));
}
}
export default ApproveAdminAdapter;
+50
View File
@@ -0,0 +1,50 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/**
* ApproveApproverAdapter
*/
class ApproveApproverAdapter {
getActionButtonsHtml(id, data) {
const statusChangeButton = '<img class="tableActionButton" src="_BASE_images/run.png" style="cursor:pointer;" rel="tooltip" title="Change Status" onclick="modJs.openStatus(_id_, \'_cstatus_\');return false;"></img>';
const viewLogsButton = '<img class="tableActionButton" src="_BASE_images/log.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="View Logs" onclick="modJs.getLogs(_id_);return false;"></img>';
let html = '<div style="width:80px;">_status__logs_</div>';
html = html.replace('_logs_', viewLogsButton);
if (data[this.getStatusFieldPosition()] == 'Processing') {
html = html.replace('_status_', statusChangeButton);
} else {
html = html.replace('_status_', '');
}
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
html = html.replace(/_cstatus_/g, data[this.getStatusFieldPosition()]);
return html;
}
getStatusOptionsData(currentStatus) {
const data = {};
if (currentStatus != 'Processing') {
} else {
data.Approved = 'Approved';
data.Rejected = 'Rejected';
}
return data;
}
getStatusOptions(currentStatus) {
return this.generateOptions(this.getStatusOptionsData(currentStatus));
}
}
export default ApproveApproverAdapter;
+68
View File
@@ -0,0 +1,68 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import LogViewAdapter from './LogViewAdapter';
class ApproveModuleAdapter extends LogViewAdapter {
cancelRequest(id) {
const object = {};
object.id = id;
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'cancelSuccessCallBack';
callBackData.callBackFail = 'cancelFailCallBack';
this.customAction('cancel', `modules=${this.modulePathName}`, reqJson, callBackData);
}
// eslint-disable-next-line no-unused-vars
cancelSuccessCallBack(callBackData) {
this.showMessage('Successful', `${this.itemName} cancellation request sent`);
this.get([]);
}
cancelFailCallBack(callBackData) {
this.showMessage(`Error Occurred while cancelling ${this.itemName}`, callBackData);
}
getActionButtonsHtml(id, data) {
const editButton = '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img>';
const deleteButton = '<img class="tableActionButton" src="_BASE_images/delete.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Delete" onclick="modJs.deleteRow(_id_);return false;"></img>';
const requestCancellationButton = `<img class="tableActionButton" src="_BASE_images/delete.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="Cancel ${this.itemName}" onclick="modJs.cancelRequest(_id_);return false;"></img>`;
const viewLogsButton = '<img class="tableActionButton" src="_BASE_images/log.png" style="margin-left:15px;cursor:pointer;" rel="tooltip" title="View Logs" onclick="modJs.getLogs(_id_);return false;"></img>';
let html = '<div style="width:120px;">_edit__logs__delete_</div>';
html = html.replace('_logs_', viewLogsButton);
if (this.showDelete) {
if (data[7] === 'Approved') {
html = html.replace('_delete_', requestCancellationButton);
} else if (data[7] === 'Pending' || this.user.user_level === 'Admin') {
html = html.replace('_delete_', deleteButton);
} else {
html = html.replace('_delete_', '');
}
} else {
html = html.replace('_delete_', '');
}
if (this.showEdit) {
html = html.replace('_edit_', editButton);
} else {
html = html.replace('_edit_', '');
}
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
}
export default ApproveModuleAdapter;
+27
View File
@@ -0,0 +1,27 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from './AdapterBase';
class BaseGraphAdapter extends AdapterBase {
getDataMapping() {
return [];
}
getHeaders() {
return [];
}
getFormFields() {
return [];
}
// eslint-disable-next-line no-unused-vars
createTable(elementId) {
}
}
export default BaseGraphAdapter;
+102
View File
@@ -0,0 +1,102 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from './AdapterBase';
/*
* CustomFieldAdapter
*/
class CustomFieldAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.tableType = '';
}
getDataMapping() {
return [
'id',
'name',
'display',
'display_order',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Display Status' },
{ sTitle: 'Priority' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['display', { label: 'Display Status', type: 'select', source: [['Form', 'Show'], ['Hidden', 'Hidden']] }],
['field_type', { label: 'Field Type', type: 'select', source: [['text', 'Text Field'], ['textarea', 'Text Area'], ['select', 'Select'], ['select2', 'Select2'], ['select2multi', 'Multi Select'], ['fileupload', 'File Upload'], ['date', 'Date'], ['datetime', 'Date Time'], ['time', 'Time']] }],
['field_label', { label: 'Field Label', type: 'text', validation: '' }],
['field_validation', {
label: 'Validation', type: 'select2', validation: 'none', sort: 'none', 'null-label': 'Required', 'allow-null': true, source: [['none', 'None'], ['number', 'Number'], ['numberOrEmpty', 'Number or Empty'], ['float', 'Decimal'], ['email', 'Email'], ['emailOrEmpty', 'Email or Empty']],
}],
['field_options', {
label: 'Field Options',
type: 'datagroup',
form: [
['label', { label: 'Label', type: 'text', validation: '' }],
['value', { label: 'Value', type: 'text', validation: 'none' }],
],
html: '<div id="#_id_#" class="panel panel-default"><div class="panel-body">#_delete_##_edit_#<span style="color:#999;font-size:13px;font-weight:bold">#_label_#</span>:#_value_#</div></div>',
validation: 'none',
}],
['display_order', { label: 'Priority', type: 'text', validation: 'number' }],
['display_section', { label: 'Display Section', type: 'text', validation: 'none' }],
];
}
setTableType(type) {
this.tableType = type;
}
doCustomValidation(params) {
const validateName = function (str) {
const name = /^[a-z][a-z0-9._]+$/;
return str != null && name.test(str);
};
if (!validateName(params.name)) {
return 'Invalid name for custom field';
}
return null;
}
forceInjectValuesBeforeSave(params) {
const data = [params.name]; const options = []; let
optionsData;
data.push({});
data[1].label = params.field_label;
data[1].type = params.field_type;
data[1].validation = params.field_validation;
if (['select', 'select2', 'select2multi'].indexOf(params.field_type) >= 0) {
optionsData = (params.field_options === '' || params.field_options === undefined)
? [] : JSON.parse(params.field_options);
for (const index in optionsData) {
options.push([optionsData[index].value, optionsData[index].label]);
}
data[1].source = options;
}
if (params.field_validation == null || params.field_validation === undefined) {
params.field_validation = '';
}
params.data = JSON.stringify(data);
params.type = this.tableType;
return params;
}
}
export default CustomFieldAdapter;
+37
View File
@@ -0,0 +1,37 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from './AdapterBase';
/**
* IdNameAdapter
*/
class IdNameAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
}
getDataMapping() {
return [
'id',
'name',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
];
}
}
export default IdNameAdapter;
+58
View File
@@ -0,0 +1,58 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/* global timeUtils */
/**
* LogViewAdapter
*/
import AdapterBase from './AdapterBase';
class LogViewAdapter extends AdapterBase {
getLogs(id) {
const object = { id };
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getLogsSuccessCallBack';
callBackData.callBackFail = 'getLogsFailCallBack';
this.customAction('getLogs', `admin=${this.modulePathName}`, reqJson, callBackData);
}
getLogsSuccessCallBack(callBackData) {
let tableLog = '<table class="table table-condensed table-bordered table-striped" style="font-size:14px;"><thead><tr><th>Notes</th></tr></thead><tbody>_days_</tbody></table> ';
const rowLog = '<tr><td><span class="logTime label label-default">_date_</span>&nbsp;&nbsp;<b>_status_</b><br/>_note_</td></tr>';
const logs = callBackData.data;
let html = '';
let rowsLogs = '';
for (let i = 0; i < logs.length; i++) {
let trow = rowLog;
trow = trow.replace(/_date_/g, logs[i].time);
trow = trow.replace(/_status_/g, `${logs[i].status_from} -> ${logs[i].status_to}`);
trow = trow.replace(/_note_/g, logs[i].note);
rowsLogs += trow;
}
if (rowsLogs !== '') {
tableLog = tableLog.replace('_days_', rowsLogs);
html += tableLog;
}
this.showMessage('Logs', html);
timeUtils.convertToRelativeTime($('.logTime'));
}
// eslint-disable-next-line no-unused-vars
getLogsFailCallBack(callBackData) {
this.showMessage('Error', 'Error occured while getting data');
}
}
export default LogViewAdapter;
File diff suppressed because it is too large Load Diff
+216
View File
@@ -0,0 +1,216 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from './AdapterBase';
/**
* ObjectAdapter
*/
class ObjectAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.container = null;
this.loadMoreButton = null;
this.start = 0;
this.pageSize = 6;
this.currentPage = 1;
this.hasMoreData = true;
this.searchTerm = '';
this.searchInput = null;
}
getObjectHTML(object) {
const template = this.getCustomTemplate(this.getTemplateName());
let t = template;
for (const index in object) {
t = t.replace(new RegExp(`#_${index}_#`, 'g'), object[index]);
}
return t;
}
setPageSize(pageSize) {
this.pageSize = pageSize;
}
addDomEvents(object) {
}
getTemplateName() {
return '';
}
renderObject(object) {
const objDom = this.getObjectDom(object.id);
const html = this.getObjectHTML(object);
const domObj = $(html);
if (objDom !== undefined && objDom != null) {
objDom.replace(domObj);
} else {
this.container.append(domObj);
}
this.addDomEvents(domObj);
}
setContainer(container) {
this.container = container;
}
setLoadMoreButton(loadMoreButton) {
const that = this;
this.loadMoreButton = loadMoreButton;
this.loadMoreButton.off().on('click', () => {
that.loadMoreButton.attr('disabled', 'disabled');
that.loadMore([]);
});
}
showLoadError(msg) {
$(`#${this.getTableName()}_error`).html(msg);
$(`#${this.getTableName()}_error`).show();
}
hideLoadError() {
$(`#${this.getTableName()}_error`).hide();
}
setSearchBox(searchInput) {
const that = this;
this.searchInput = searchInput;
this.searchInput.off();
this.searchInput.keydown(function (event) {
const val = $(this).val();
if (event.which === 13) {
event.preventDefault();
that.search([]);
} else if ((event.which === 8 || event.which === 46) && val.length === 1 && that.searchTerm !== '') {
that.search([]);
}
});
}
getObjectDom(id) {
const obj = this.container.find(`#obj_${id}`);
if (obj.length) {
return obj;
}
return null;
}
loadMore(callBackData) {
if (!this.hasMoreData) {
return;
}
this.currentPage++;
this.get(callBackData, true);
}
get(callBackData, loadMore) {
const that = this;
this.hideLoadError();
if (!loadMore) {
this.currentPage = 1;
if (this.container != null) {
this.container.html('');
}
this.hasMoreData = true;
this.tableData = [];
}
this.start = (this.currentPage - 1) * this.pageSize;
this.container = $(`#${this.getTableName()}`).find('.objectList');
that.showLoader();
let url = `${this.getDataUrl(that.getDataMapping())
}&iDisplayStart=${this.start}&iDisplayLength=${this.pageSize}&objects=1`;
if (this.searchTerm !== '' && this.searchTerm !== undefined && this.searchTerm != null) {
url += `&sSearch=${this.searchTerm}`;
}
$.post(url, (data) => {
that.getSuccessCallBack(callBackData, data);
}, 'json').always(() => { that.hideLoader(); });
that.initFieldMasterData();
this.trackEvent('get', this.tab, this.table);
}
search(callBackData) {
const that = this;
this.searchTerm = $(`#${this.getTableName()}_search`).val();
this.get(callBackData);
}
getSuccessCallBack(callBackData, serverData) {
const data = [];
if (serverData.length === 0 && this.container.html() === '') {
this.showLoadError('No Results Found !!!');
return;
}
if (this.getFilters() == null) {
$(`#${this.getTableName()}_filterBtn`).hide();
$(`#${this.getTableName()}_resetFilters`).hide();
} else {
$(`#${this.getTableName()}_filterBtn`).show();
$(`#${this.getTableName()}_resetFilters`).show();
if (this.currentFilterString !== '' && this.currentFilterString != null) {
$(`#${this.getTableName()}_resetFilters`).html(`${this.currentFilterString}<i class="fa fa-times"></i>`);
} else {
$(`#${this.getTableName()}_resetFilters`).html('Reset Filters');
$(`#${this.getTableName()}_resetFilters`).hide();
}
}
$(`#${this.getTableName()}`).find('.search-controls').show();
if (serverData.length > this.pageSize) {
this.hasMoreData = true;
serverData.pop();
this.loadMoreButton.removeAttr('disabled');
this.loadMoreButton.show();
} else {
this.hasMoreData = false;
this.loadMoreButton.hide();
}
this.scrollToElementBottom(this.container);
for (let i = 0; i < serverData.length; i++) {
data.push(this.preProcessTableData(serverData[i]));
}
this.sourceData = serverData;
if (callBackData.callBack !== undefined && callBackData.callBack != null) {
if (callBackData.callBackData === undefined || callBackData.callBackData == null) {
callBackData.callBackData = [];
}
callBackData.callBackData.push(serverData);
callBackData.callBackData.push(data);
this.callFunction(callBackData.callBack, callBackData.callBackData);
}
this.tableData = data;
if (!(callBackData.noRender !== undefined && callBackData.noRender != null && callBackData.noRender === true)) {
for (let i = 0; i < data.length; i++) {
this.renderObject(data[i]);
}
}
}
}
export default ObjectAdapter;
+60
View File
@@ -0,0 +1,60 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from './AdapterBase';
/**
* @class SubAdapterBase
* @param endPoint
* @param tab
* @param filter
* @param orderBy
* @returns
*/
class SubAdapterBase extends AdapterBase {
deleteRow(id) {
this.deleteParams.id = id;
this.confirmDelete();
}
createTable(elementId) {
let item; let itemHtml; let itemDelete; let itemEdit;
const data = this.getTableData();
const deleteButton = `<button id="#_id_#_delete" onclick="modJs.subModJsList['tab${elementId}'].deleteRow('_id_');return false;" type="button" style="position: absolute;bottom: 5px;right: 5px;font-size: 13px;" tooltip="Delete"><li class="fa fa-times"></li></button>`;
const editButton = `<button id="#_id_#_edit" onclick="modJs.subModJsList['tab${elementId}'].edit('_id_');return false;" type="button" style="position: absolute;bottom: 5px;right: 35px;font-size: 13px;" tooltip="Edit"><li class="fa fa-edit"></li></button>`;
const table = $('<div class="list-group"></div>');
// add Header
const header = this.getSubHeader();
table.append(header);
if (data.length === 0) {
table.append(`<a href="#" class="list-group-item">${this.getNoDataMessage()}</a>`);
} else {
for (let i = 0; i < data.length; i++) {
item = data[i];
itemDelete = deleteButton.replace(/_id_/g, item[0]);
itemEdit = editButton.replace(/_id_/g, item[0]);
itemHtml = this.getSubItemHtml(item, itemDelete, itemEdit);
table.append(itemHtml);
}
}
$(`#${elementId}`).html('');
$(`#${elementId}`).append(table);
$('#plainMessageModel').modal('hide');
}
getNoDataMessage() {
return 'No data found';
}
getSubHeader() {
const header = $(`<a href="#" onclick="return false;" class="list-group-item" style="background:#eee;"><h4 class="list-group-item-heading">${this.getSubHeaderTitle()}</h4></a>`);
return header;
}
}
export default SubAdapterBase;
+297
View File
@@ -0,0 +1,297 @@
/* global modJs */
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import AdapterBase from './AdapterBase';
/**
* TableEditAdapter
*/
class TableEditAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.cellDataUpdates = {};
this.modulePath = '';
this.rowFieldName = '';
this.columnFieldName = '';
this.rowTable = '';
this.columnTable = '';
this.valueTable = '';
this.csvData = [];
this.columnIDMap = {};
}
setModulePath(path) {
this.modulePath = path;
}
setRowFieldName(name) {
this.rowFieldName = name;
}
setTables(rowTable, columnTable, valueTable) {
this.rowTable = rowTable;
this.columnTable = columnTable;
this.valueTable = valueTable;
}
setColumnFieldName(name) {
this.columnFieldName = name;
}
getDataMapping() {
return [
];
}
getFormFields() {
return [
];
}
get() {
this.getAllData();
}
getAllData(save) {
let req = {};
req.rowTable = this.rowTable;
req.columnTable = this.columnTable;
req.valueTable = this.valueTable;
req = this.addAdditionalRequestData('getAllData', req);
req.save = (save === undefined || save == null || save === false) ? 0 : 1;
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getAllDataSuccessCallBack';
callBackData.callBackFail = 'getAllDataFailCallBack';
this.customAction('getAllData', this.modulePath, reqJson, callBackData);
}
getDataItem(row, column, allData) {
const columnData = allData[1];
const rowData = allData[0];
const serverData = allData[2];
if (column === -1) {
return rowData[row].name;
}
return this.getDataItemByKeyValues(this.rowFieldName, rowData[row].id, this.columnFieldName, columnData[column].id, serverData);
}
getDataItemByKeyValues(rowKeyName, rowKeyVal, colKeyName, colKeyVal, data) {
for (let i = 0; i < data.length; i++) {
if (data[i][rowKeyName] === rowKeyVal && data[i][colKeyName] === colKeyVal) {
return (data[i].amount !== undefined && data[i].amount != null) ? data[i].amount : '';
}
}
return '';
}
getAllDataSuccessCallBack(allData) {
const serverData = allData[2];
const columnData = allData[1];
const rowData = allData[0];
const data = [];
for (let i = 0; i < rowData.length; i++) {
const row = [];
for (let j = -1; j < columnData.length; j++) {
row[j + 1] = this.getDataItem(i, j, allData);
}
data.push(this.preProcessTableData(row));
}
this.sourceData = serverData;
this.tableData = data;
this.setHeaders(columnData, rowData);
this.createTable(this.getTableName());
$(`#${this.getTableName()}Form`).hide();
$(`#${this.getTableName()}`).show();
this.csvData = [];
let tmpRow = [];
for (let i = 0; i < columnData.length; i++) {
tmpRow.push(columnData[i].name);
}
tmpRow = this.modifyCSVHeader(tmpRow);
this.csvData.push(tmpRow);
for (let i = 0; i < data.length; i++) {
this.csvData.push(data[i]);
}
}
modifyCSVHeader(header) {
return header;
}
getAllDataFailCallBack(callBackData, serverData) {
}
setHeaders(columns, rows) {
const headers = [];
headers.push({ sTitle: '', sWidth: '180px;' });
let sclass = '';
this.columnIDMap = {};
for (let i = 0; i < columns.length; i++) {
this.columnIDMap[columns[i].id] = i;
if (columns[i].editable === undefined || columns[i].editable == null || columns[i].editable === 'Yes') {
sclass = 'editcell';
} else {
sclass = '';
}
headers.push({
sTitle: columns[i].name,
sClass: sclass,
fnCreatedCell(nTd, sData, oData, iRow, iCol) {
$(nTd).data('colId', columns[iCol - 1].id);
$(nTd).data('rowId', rows[iRow].id);
},
});
}
this.headers = headers;
}
getHeaders() {
return this.headers;
}
createTable(elementId) {
const data = this.getTableData();
const headers = this.getHeaders();
if (this.showActionButtons()) {
headers.push({ sTitle: '', sClass: 'center' });
}
if (this.showActionButtons()) {
for (let i = 0; i < data.length; i++) {
data[i].push(this.getActionButtonsHtml(data[i][0], data[i]));
}
}
let html = '';
html = `${this.getTableTopButtonHtml()}<div class="box-body table-responsive"><table cellpadding="0" cellspacing="0" border="0" class="table table-bordered table-striped" id="grid"></table></div>`;
// Find current page
const activePage = $(`#${elementId} .dataTables_paginate .active a`).html();
let start = 0;
if (activePage !== undefined && activePage != null) {
start = parseInt(activePage, 10) * 15 - 15;
}
$(`#${elementId}`).html(html);
const dataTableParams = {
oLanguage: {
sLengthMenu: '_MENU_ records per page',
},
aaData: data,
aoColumns: headers,
bSort: false,
iDisplayLength: 15,
iDisplayStart: start,
};
const customTableParams = this.getCustomTableParams();
$.extend(dataTableParams, customTableParams);
$(`#${elementId} #grid`).dataTable(dataTableParams);
$('.dataTables_paginate ul').addClass('pagination');
$('.dataTables_length').hide();
$('.dataTables_filter input').addClass('form-control');
$('.dataTables_filter input').attr('placeholder', 'Search');
$('.dataTables_filter label').contents().filter(function () {
return (this.nodeType === 3);
}).remove();
// $('.tableActionButton').tooltip();
$(`#${elementId} #grid`).editableTableWidget();
$(`#${elementId} #grid .editcell`).on('validate', function (evt, newValue) {
return modJs.validateCellValue($(this), evt, newValue);
});
this.afterCreateTable(elementId);
}
afterCreateTable(elementId) {
}
addCellDataUpdate(colId, rowId, data) {
this.cellDataUpdates[`${colId}=${rowId}`] = [colId, rowId, data];
}
addAdditionalRequestData(type, req) {
return req;
}
sendCellDataUpdates() {
let req = this.cellDataUpdates;
req.rowTable = this.rowTable;
req.columnTable = this.columnTable;
req.valueTable = this.valueTable;
req = this.addAdditionalRequestData('updateData', req);
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'updateDataSuccessCallBack';
callBackData.callBackFail = 'updateDataFailCallBack';
this.showLoader();
this.customAction('updateData', this.modulePath, reqJson, callBackData);
}
updateDataSuccessCallBack(callBackData, serverData) {
this.hideLoader();
modJs.cellDataUpdates = {};
modJs.get();
}
updateDataFailCallBack(callBackData, serverData) {
this.hideLoader();
}
sendAllCellDataUpdates() {
let req = this.cellDataUpdates;
req.rowTable = this.rowTable;
req.columnTable = this.columnTable;
req.valueTable = this.valueTable;
req = this.addAdditionalRequestData('updateAllData', req);
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'updateDataAllSuccessCallBack';
callBackData.callBackFail = 'updateDataAllFailCallBack';
this.showLoader();
this.customAction('updateAllData', this.modulePath, reqJson, callBackData);
}
updateDataAllSuccessCallBack(callBackData, serverData) {
this.hideLoader();
modJs.cellDataUpdates = {};
modJs.getAllData(true);
}
updateDataAllFailCallBack(callBackData, serverData) {
this.hideLoader();
}
showActionButtons() {
return false;
}
}
export default TableEditAdapter;
-6
View File
@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icon-css-ae" width="640" height="480">
<path fill="#00732f" d="M0 0h640v160H0z"/>
<path fill="#fff" d="M0 160h640v160H0z"/>
<path d="M0 320h640v160H0z"/>
<path fill="red" d="M0 0h220v480H0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 257 B

@@ -0,0 +1,31 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="flag-icon-css-ar" width="640" height="480">
<path fill="#74acdf" d="M0 0h640v480H0z"/>
<path fill="#fff" d="M0 160h640v160H0z"/>
<g id="c" transform="translate(-64) scale(.96)">
<path id="a" fill="#f6b40e" stroke="#85340a" stroke-width="1.1" d="M396.8 251.3l28.5 62s.5 1.2 1.3.9c.8-.4.3-1.5.3-1.5l-23.7-64m-.7 24.1c-.4 9.4 5.4 14.6 4.7 23-.8 8.5 3.8 13.2 5 16.5 1 3.3-1.3 5.2-.3 5.7s3-2.1 2.4-6.8c-.7-4.6-4.2-6-3.4-16.3.8-10.3-4.2-12.7-3-22"/>
<use width="100%" height="100%" transform="rotate(22.5 400 250)" xlink:href="#a"/>
<use width="100%" height="100%" transform="rotate(45 400 250)" xlink:href="#a"/>
<use width="100%" height="100%" transform="rotate(67.5 400 250)" xlink:href="#a"/>
<path id="b" fill="#85340a" d="M404.3 274.4c.5 9 5.6 13 4.6 21.3 2.2-6.5-3.1-11.6-2.8-21.2m-7.7-23.8l19.5 42.6-16.3-43.9"/>
<use width="100%" height="100%" transform="rotate(22.5 400 250)" xlink:href="#b"/>
<use width="100%" height="100%" transform="rotate(45 400 250)" xlink:href="#b"/>
<use width="100%" height="100%" transform="rotate(67.5 400 250)" xlink:href="#b"/>
</g>
<use width="100%" height="100%" transform="rotate(90 320 240)" xlink:href="#c"/>
<use width="100%" height="100%" transform="rotate(180 320 240)" xlink:href="#c"/>
<use width="100%" height="100%" transform="rotate(-90 320 240)" xlink:href="#c"/>
<circle cx="320" cy="240" r="26.7" fill="#f6b40e" stroke="#85340a" stroke-width="1.4"/>
<path id="h" fill="#843511" d="M329.1 234.3c-1.8 0-3.6.8-4.6 2.4 2 1.9 6.6 2 9.7-.2a7 7 0 0 0-5.1-2.2zm0 .4c1.7 0 3.4.8 3.6 1.6-2 2.3-5.3 2-7.4.4a4.3 4.3 0 0 1 3.8-2z"/>
<use width="100%" height="100%" transform="matrix(-1 0 0 1 640.2 0)" xlink:href="#d"/>
<use width="100%" height="100%" transform="matrix(-1 0 0 1 640.2 0)" xlink:href="#e"/>
<use width="100%" height="100%" transform="translate(18.1)" xlink:href="#f"/>
<use width="100%" height="100%" transform="matrix(-1 0 0 1 640.2 0)" xlink:href="#g"/>
<path fill="#85340a" d="M316 243.7a1.9 1.9 0 1 0 1.8 2.9 4 4 0 0 0 2.2.6h.2a3.9 3.9 0 0 0 2.3-.6 1.9 1.9 0 1 0 1.8-3c.5.3.8.7.8 1.3 0 .6-.5 1.2-1.2 1.2a1.2 1.2 0 0 1-1.2-1.2 3 3 0 0 1-2.6 1.7 3 3 0 0 1-2.5-1.7 1.2 1.2 0 0 1-1.3 1.2c-.6 0-1.2-.6-1.2-1.2s.3-1 .8-1.2zm2 5.5c-2.1 0-3 1.8-4.8 3 1-.4 1.9-1.2 3.3-2s2.7.2 3.5.2c.8 0 2-1 3.5-.2 1.4.8 2.3 1.6 3.3 2-1.9-1.2-2.7-3-4.8-3a5.5 5.5 0 0 0-2 .6 5.5 5.5 0 0 0-2-.7z"/>
<path fill="#85340a" d="M317.2 251.6c-.8 0-1.8.2-3.4.6 3.7-.8 4.5.5 6.2.5 1.6 0 2.4-1.3 6.1-.5-4-1.2-4.9-.4-6.1-.4-.8 0-1.4-.3-2.8-.2z"/>
<path fill="#85340a" d="M314 252.2h-.8c4.3.5 2.3 3 6.8 3s2.5-2.5 6.8-3c-4.5-.4-3.1 2.3-6.8 2.3-3.5 0-2.4-2.3-6-2.3zm9.7 6.7a3.7 3.7 0 0 0-7.4 0 3.8 3.8 0 0 1 7.4 0z"/>
<path id="e" fill="#85340a" d="M303.4 234.3c4.7-4.1 10.7-4.8 14-1.7a8 8 0 0 1 1.5 3.5c.4 2.3-.3 4.8-2.1 7.4l.8.4a14.6 14.6 0 0 0 1.6-9.4 13.3 13.3 0 0 0-.6-2.3c-4.5-3.7-10.7-4-15.2 2z"/>
<path id="d" fill="#85340a" d="M310.8 233c2.7 0 3.3.7 4.5 1.7 1.2 1 1.9.8 2 1 .3.2 0 .8-.3.6-.5-.2-1.3-.6-2.5-1.6s-2.5-1-3.7-1c-3.7 0-5.7 3-6.2 2.8-.3-.2 2.1-3.5 6.2-3.5z"/>
<use width="100%" height="100%" transform="translate(-18.4)" xlink:href="#h"/>
<circle id="f" cx="310.9" cy="236.3" r="1.9" fill="#85340a"/>
<path id="g" fill="#85340a" d="M305.9 237.5c3.5 2.7 7 2.5 9 1.3 2-1.3 2-1.7 1.6-1.7-.4 0-.8.4-2.4 1.3-1.7.8-4.1.8-8.2-.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

+7
View File
@@ -0,0 +1,7 @@
input, button, select, textarea {
direction: rtl;
}
table {
direction: rtl;
}
+2
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

+8313
View File
File diff suppressed because one or more lines are too long
+34840
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More