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
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
+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
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
+7
View File
@@ -0,0 +1,7 @@
import {
AttendanceAdapter,
EmployeeAttendanceSheetAdapter,
} from './lib';
window.AttendanceAdapter = AttendanceAdapter;
window.EmployeeAttendanceSheetAdapter = EmployeeAttendanceSheetAdapter;
+468
View File
@@ -0,0 +1,468 @@
/*
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 FormValidation from '../../../api/FormValidation';
class AttendanceAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.punch = null;
this.useServerTime = 0;
this.photoTaken = 0;
this.photoAttendance = 0;
}
updatePunchButton() {
this.getPunch('changePunchButtonSuccessCallBack');
}
setUseServerTime(val) {
this.useServerTime = val;
}
setPhotoAttendance(val) {
this.photoAttendance = parseInt(val, 10);
}
getDataMapping() {
return [
'id',
'in_time',
'out_time',
'note',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Time-In' },
{ sTitle: 'Time-Out' },
{ sTitle: 'Note' },
];
}
getFormFields() {
if (this.useServerTime === 0) {
return [
['id', { label: 'ID', type: 'hidden' }],
['time', { label: 'Time', type: 'datetime' }],
['note', { label: 'Note', type: 'textarea', validation: 'none' }],
];
}
return [
['id', { label: 'ID', type: 'hidden' }],
['note', { label: 'Note', type: 'textarea', validation: 'none' }],
];
}
getCustomTableParams() {
const that = this;
const dataTableParams = {
aoColumnDefs: [
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 1);
},
aTargets: [1],
},
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 2);
},
aTargets: [2],
},
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 3);
},
aTargets: [3],
},
{
fnRender: that.getActionButtons,
aTargets: [that.getDataMapping().length],
},
],
};
return dataTableParams;
}
preProcessRemoteTableData(data, cell, id) {
if (id === 1) {
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 === 2) {
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 === 3) {
if (cell !== undefined && cell !== null) {
if (cell.length > 20) {
return `${cell.substring(0, 20)}..`;
}
}
return cell;
}
return cell;
}
getActionButtonsHtml(id, data) {
return '';
}
getTableTopButtonHtml() {
if (this.punch === null || this.punch === undefined) {
return '<button id="punchButton" style="float:right;" onclick="modJs.showPunchDialog();return false;" class="btn btn-small">Punch-in <span class="icon-time"></span></button>';
}
return '<button id="punchButton" style="float:right;" onclick="modJs.showPunchDialog();return false;" class="btn btn-small">Punch-out <span class="icon-time"></span></button>';
}
save() {
const that = this;
const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' });
if (validator.checkValues()) {
const msg = this.doCustomValidation();
if (msg == null) {
let params = validator.getFormParameters();
params = this.forceInjectValuesBeforeSave(params);
params.cdate = this.getClientDate(new Date()).toISOString().slice(0, 19).replace('T', ' ');
const reqJson = JSON.stringify(params);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'saveSuccessCallback';
callBackData.callBackFail = 'getPunchFailCallBack';
this.customAction('savePunch', 'modules=attendance', reqJson, callBackData, true);
} else {
$(`#${this.getTableName()}Form .label`).html(msg);
$(`#${this.getTableName()}Form .label`).show();
}
}
}
saveSuccessCallback(callBackData) {
this.punch = callBackData;
this.getPunch('changePunchButtonSuccessCallBack');
$('#PunchModel').modal('hide');
this.get([]);
}
cancel() {
$('#PunchModel').modal('hide');
}
showPunchDialog() {
this.getPunch('showPunchDialogShowPunchSuccessCallBack');
}
getPunch(successCallBack) {
const that = this;
const object = {};
object.date = this.getClientDate(new Date()).toISOString().slice(0, 19).replace('T', ' ');
object.offset = this.getClientGMTOffset();
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = successCallBack;
callBackData.callBackFail = 'getPunchFailCallBack';
this.customAction('getPunch', 'modules=attendance', reqJson, callBackData);
}
showPunchDialogShowPunchSuccessCallBack(callBackData) {
this.punch = callBackData;
$('#PunchModel').modal('show');
if (this.punch === null) {
$('#PunchModel').find('h3').html('Punch Time-in');
modJs.renderForm();
} else {
$('#PunchModel').find('h3').html('Punch Time-out');
modJs.renderForm(this.punch);
}
$('#Attendance').show();
const picker = $('#time_datetime').data('datetimepicker');
picker.setLocalDate(new Date());
}
changePunchButtonSuccessCallBack(callBackData) {
this.punch = callBackData;
if (this.punch === null) {
$('#punchButton').html('Punch-in <span class="icon-time"></span>');
} else {
$('#punchButton').html('Punch-out <span class="icon-time"></span>');
}
}
getPunchFailCallBack(callBackData) {
this.showMessage('Error Occured while Time Punch', callBackData);
}
getClientDate(date) {
const offset = this.getClientGMTOffset();
const tzDate = date.addMinutes(offset * 60);
return tzDate;
}
getClientGMTOffset() {
const rightNow = new Date();
const jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
const temp = jan1.toGMTString();
const jan2 = new Date(temp.substring(0, temp.lastIndexOf(' ') - 1));
return (jan1 - jan2) / (1000 * 60 * 60);
}
doCustomValidation(params) {
if (this.photoAttendance === 1 && !this.photoTaken) {
return 'Please attach a photo before submitting';
}
return null;
}
forceInjectValuesBeforeSave(params) {
if (this.photoAttendance === 1) {
const canvas = document.getElementById('attendnaceCanvas');
params.image = canvas.toDataURL();
}
return params;
}
postRenderForm() {
if (this.photoAttendance === 1) {
$('.photoAttendance').show();
const video = document.getElementById('attendnaceVideo');
// Get access to the camera!
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
video.src = window.URL.createObjectURL(stream);
video.play();
});
}
this.photoTaken = false;
this.configureEvents();
} else {
$('.photoAttendance').remove();
}
}
configureEvents() {
const that = this;
const canvas = document.getElementById('attendnaceCanvas');
const context = canvas.getContext('2d');
const video = document.getElementById('attendnaceVideo');
$('.attendnaceSnap').click(() => {
context.drawImage(video, 0, 0, 208, 156);
that.photoTaken = true;
return false;
});
}
}
class EmployeeAttendanceSheetAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.currentTimesheetId = null;
this.currentTimesheet = null;
}
getDataMapping() {
return [
'id',
'date_start',
'date_end',
'total_time',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Start Date' },
{ sTitle: 'End Date' },
{ sTitle: 'Total Time' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['date_start', { label: 'TimeSheet Start Date', type: 'date', validation: '' }],
['date_end', { label: 'TimeSheet End Date', type: 'date', validation: '' }],
['details', { label: 'Reason', type: 'textarea', validation: 'none' }],
];
}
preProcessTableData(row) {
row[1] = Date.parse(row[1]).toString('MMM d, yyyy (dddd)');
row[2] = Date.parse(row[2]).toString('MMM d, yyyy (dddd)');
return row;
}
renderForm(object) {
const formHtml = this.templates.formTemplate;
const html = '';
$(`#${this.getTableName()}Form`).html(formHtml);
$(`#${this.getTableName()}Form`).show();
$(`#${this.getTableName()}`).hide();
$('#attendnacesheet_start').html(Date.parse(object.date_start).toString('MMM d, yyyy (dddd)'));
$('#attendnacesheet_end').html(Date.parse(object.date_end).toString('MMM d, yyyy (dddd)'));
this.currentTimesheet = object;
this.getTimeEntries();
}
getTimeEntries() {
const timesheetId = this.currentId;
const sourceMappingJson = JSON.stringify(modJsList.tabEmployeeTimeEntry.getSourceMapping());
const reqJson = JSON.stringify({ id: timesheetId, sm: sourceMappingJson });
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getTimeEntriesSuccessCallBack';
callBackData.callBackFail = 'getTimeEntriesFailCallBack';
this.customAction('getTimeEntries', 'modules=time_sheets', reqJson, callBackData);
}
getTimeEntriesSuccessCallBack(callBackData) {
const entries = callBackData;
let html = '';
const temp = '<tr><td><img class="tableActionButton" src="_BASE_images/delete.png" style="cursor:pointer;" rel="tooltip" title="Delete" onclick="modJsList[\'tabEmployeeTimeEntry\'].deleteRow(_id_);return false;"></img></td><td>_start_</td><td>_end_</td><td>_duration_</td><td>_project_</td><td>_details_</td>';
for (let i = 0; i < entries.length; i++) {
try {
let t = temp;
t = t.replace(/_start_/g, Date.parse(entries[i].date_start).toString('MMM d, yyyy [hh:mm tt]'));
t = t.replace(/_end_/g, Date.parse(entries[i].date_end).toString('MMM d, yyyy [hh:mm tt]'));
const mili = Date.parse(entries[i].date_end) - Date.parse(entries[i].date_start);
const minutes = Math.round(mili / 60000);
const hourMinutes = (minutes % 60);
const hours = (minutes - hourMinutes) / 60;
t = t.replace(/_duration_/g, `Hours (${hours}) - Min (${hourMinutes})`);
if (entries[i].project === 'null' || entries[i].project === null || entries[i].project === undefined) {
t = t.replace(/_project_/g, 'None');
} else {
t = t.replace(/_project_/g, entries[i].project);
}
t = t.replace(/_project_/g, entries[i].project);
t = t.replace(/_details_/g, entries[i].details);
t = t.replace(/_id_/g, entries[i].id);
t = t.replace(/_BASE_/g, this.baseUrl);
html += t;
} catch (e) {
// DN
}
}
$('.timesheet_entries_table_body').html(html);
if (modJs.getTableName() === 'SubEmployeeTimeSheetAll') {
$('#submit_sheet').hide();
$('#add_time_sheet_entry').hide();
} else if (this.currentElement.status === 'Approved') {
$('#submit_sheet').hide();
$('#add_time_sheet_entry').hide();
} else {
$('#submit_sheet').show();
$('#add_time_sheet_entry').show();
}
}
getTimeEntriesFailCallBack(callBackData) {
this.showMessage('Error', 'Error occured while getting timesheet entries');
}
createPreviousAttendnacesheet(id) {
const reqJson = JSON.stringify({ id });
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'createPreviousAttendnacesheetSuccessCallBack';
callBackData.callBackFail = 'createPreviousAttendnacesheetFailCallBack';
this.customAction('createPreviousAttendnaceSheet', 'modules=attendnace', reqJson, callBackData);
}
createPreviousAttendnacesheetSuccessCallBack(callBackData) {
$('.tooltip').css('display', 'none');
$('.tooltip').remove();
// this.showMessage("Success", "Previous Timesheet created");
this.get([]);
}
createPreviousAttendnacesheetFailCallBack(callBackData) {
this.showMessage('Error', callBackData);
}
getActionButtonsHtml(id, data) {
let html = '';
if (this.getTableName() === 'EmployeeTimeSheetAll') {
html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/view.png" style="cursor:pointer;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.edit(_id_);return false;"></img><img class="tableActionButton" src="_BASE_images/redo.png" style="cursor:pointer;margin-left:15px;" rel="tooltip" title="Create previous time sheet" onclick="modJs.createPreviousAttendnacesheet(_id_);return false;"></img></div>';
} else {
html = '<div style="width:80px;"><img class="tableActionButton" src="_BASE_images/view.png" style="cursor:pointer;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.edit(_id_);return false;"></img></div>';
}
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
getCustomTableParams() {
const that = this;
const dataTableParams = {
aoColumnDefs: [
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 1);
},
aTargets: [1],
},
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 2);
},
aTargets: [2],
},
{
fnRender: that.getActionButtons,
aTargets: [that.getDataMapping().length],
},
],
};
return dataTableParams;
}
preProcessRemoteTableData(data, cell, id) {
return Date.parse(cell).toString('MMM d, yyyy (dddd)');
}
}
module.exports = {
AttendanceAdapter,
EmployeeAttendanceSheetAdapter,
};
+3
View File
@@ -0,0 +1,3 @@
import { DashboardAdapter } from './lib';
window.DashboardAdapter = DashboardAdapter;
+99
View File
@@ -0,0 +1,99 @@
/*
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) {
}
getPunch() {
const that = this;
const object = {};
object.date = this.getClientDate(new Date()).toISOString().slice(0, 19).replace('T', ' ');
object.offset = this.getClientGMTOffset();
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getPunchSuccessCallBack';
callBackData.callBackFail = 'getPunchFailCallBack';
this.customAction('getPunch', 'modules=attendance', reqJson, callBackData);
}
getPunchSuccessCallBack(callBackData) {
const punch = callBackData;
if (punch == null) {
$('#lastPunchTime').html('Not');
$('#punchTimeText').html('Punched In');
} else {
$('#lastPunchTime').html(Date.parse(punch.in_time).toString('h:mm tt'));
$('#punchTimeText').html('Punched In');
}
}
getPunchFailCallBack(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', 'modules=dashboard', reqJson, callBackData);
}
getInitDataSuccessCallBack(data) {
$('#timeSheetHoursWorked').html(data.lastTimeSheetHours);
$('#numberOfProjects').html(data.activeProjects);
$('#pendingLeaveCount').html(data.pendingLeaves);
$('#numberOfEmployees').html(`${data.numberOfEmployees} Subordinates`);
$('#numberOfCandidates').html(`${data.numberOfCandidates} Candidates`);
$('#numberOfJobs').html(`${data.numberOfJobs} Active`);
$('#numberOfCourses').html(`${data.numberOfCourses} Active`);
}
getInitDataFailCallBack(callBackData) {
}
getClientDate(date) {
const offset = this.getClientGMTOffset();
const tzDate = date.addMinutes(offset * 60);
return tzDate;
}
getClientGMTOffset() {
const rightNow = new Date();
const jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
const temp = jan1.toGMTString();
const jan2 = new Date(temp.substring(0, temp.lastIndexOf(' ') - 1));
return (jan1 - jan2) / (1000 * 60 * 60);
}
}
module.exports = { DashboardAdapter };
+3
View File
@@ -0,0 +1,3 @@
import { EmployeeDependentAdapter } from './lib';
window.EmployeeDependentAdapter = EmployeeDependentAdapter;
+44
View File
@@ -0,0 +1,44 @@
/*
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';
/**
* EmployeeDependentAdapter
*/
class EmployeeDependentAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'relationship',
'dob',
'id_number',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Relationship' },
{ sTitle: 'Date of Birth' },
{ sTitle: 'Id Number' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['relationship', { label: 'Relationship', type: 'select', source: [['Child', 'Child'], ['Spouse', 'Spouse'], ['Parent', 'Parent'], ['Other', 'Other']] }],
['dob', { label: 'Date of Birth', type: 'date', validation: '' }],
['id_number', { label: 'Id Number', type: 'text', validation: 'none' }],
];
}
}
module.exports = { EmployeeDependentAdapter };
@@ -0,0 +1,3 @@
import { EmergencyContactAdapter } from './lib';
window.EmergencyContactAdapter = EmergencyContactAdapter;
+44
View File
@@ -0,0 +1,44 @@
/*
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 EmergencyContactAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'name',
'relationship',
'home_phone',
'work_phone',
'mobile_phone',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Relationship' },
{ sTitle: 'Home Phone' },
{ sTitle: 'Work Phone' },
{ sTitle: 'Mobile Phone' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['name', { label: 'Name', type: 'text', validation: '' }],
['relationship', { label: 'Relationship', type: 'text', validation: 'none' }],
['home_phone', { label: 'Home Phone', type: 'text', validation: 'none' }],
['work_phone', { label: 'Work Phone', type: 'text', validation: 'none' }],
['mobile_phone', { label: 'Mobile Phone', type: 'text', validation: 'none' }],
];
}
}
module.exports = { EmergencyContactAdapter };
+9
View File
@@ -0,0 +1,9 @@
import {
EmployeeAdapter,
CompanyGraphAdapter,
ApiAccessAdapter,
} from './lib';
window.EmployeeAdapter = EmployeeAdapter;
window.CompanyGraphAdapter = CompanyGraphAdapter;
window.ApiAccessAdapter = ApiAccessAdapter;
+724
View File
@@ -0,0 +1,724 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
/* eslint-disable camelcase,no-underscore-dangle */
/* global d3 */
import QRCode from 'qrcode';
import AdapterBase from '../../../api/AdapterBase';
class EmployeeAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.fieldNameMap = {};
this.hiddenFields = {};
this.tableFields = {};
this.formOnlyFields = {};
this.currentUserId = null;
}
setFieldNameMap(fields) {
let field;
for (let i = 0; i < fields.length; i++) {
field = fields[i];
this.fieldNameMap[field.name] = field;
if (field.display === 'Hidden') {
this.hiddenFields[field.name] = field;
} else if (field.display === 'Table and Form') {
this.tableFields[field.name] = field;
} else {
this.formOnlyFields[field.name] = field;
}
}
}
getDataMapping() {
return [
'id',
'employee_id',
'first_name',
'last_name',
'mobile_phone',
'department',
'gender',
'supervisor',
];
}
getHeaders() {
return [
{ sTitle: 'ID' },
{ sTitle: 'Employee Number' },
{ sTitle: 'First Name' },
{ sTitle: 'Last Name' },
{ sTitle: 'Mobile' },
{ sTitle: 'Department' },
{ sTitle: 'Gender' },
{ sTitle: 'Supervisor' },
];
}
getFormFields() {
const newFields = [];
let employee_id; let ssn_num; let employment_status; let job_title; let pay_grade; let joined_date; let department; let work_email; let
country;
if (this.checkPermission('Edit Employee Number') === 'Yes') {
employee_id = ['employee_id', { label: 'Employee Number', type: 'text', validation: '' }];
} else {
employee_id = ['employee_id', { label: 'Employee Number', type: 'placeholder', validation: '' }];
}
if (this.checkPermission('Edit EPF/CPF Number') === 'Yes') {
ssn_num = ['ssn_num', { label: 'EPF/CPF/SS No', type: 'text', validation: 'none' }];
} else {
ssn_num = ['ssn_num', { label: 'EPF/CPF/SS No', type: 'placeholder', validation: 'none' }];
}
if (this.checkPermission('Edit Employment Status') === 'Yes') {
employment_status = ['employment_status', { label: 'Employment Status', type: 'select2', 'remote-source': ['EmploymentStatus', 'id', 'name'] }];
} else {
employment_status = ['employment_status', { label: 'Employment Status', type: 'placeholder', 'remote-source': ['EmploymentStatus', 'id', 'name'] }];
}
if (this.checkPermission('Edit Job Title') === 'Yes') {
job_title = ['job_title', { label: 'Job Title', type: 'select2', 'remote-source': ['JobTitle', 'id', 'name'] }];
} else {
job_title = ['job_title', { label: 'Job Title', type: 'placeholder', 'remote-source': ['JobTitle', 'id', 'name'] }];
}
if (this.checkPermission('Edit Pay Grade') === 'Yes') {
pay_grade = ['pay_grade', {
label: 'Pay Grade', type: 'select2', 'allow-null': true, 'remote-source': ['PayGrade', 'id', 'name'],
}];
} else {
pay_grade = ['pay_grade', {
label: 'Pay Grade', type: 'placeholder', 'allow-null': true, 'remote-source': ['PayGrade', 'id', 'name'],
}];
}
if (this.checkPermission('Edit Joined Date') === 'Yes') {
joined_date = ['joined_date', { label: 'Joined Date', type: 'date', validation: '' }];
} else {
joined_date = ['joined_date', { label: 'Joined Date', type: 'placeholder', validation: '' }];
}
if (this.checkPermission('Edit Department') === 'Yes') {
department = ['department', { label: 'Department', type: 'select2', 'remote-source': ['CompanyStructure', 'id', 'title'] }];
} else {
department = ['department', { label: 'Department', type: 'placeholder', 'remote-source': ['CompanyStructure', 'id', 'title'] }];
}
if (this.checkPermission('Edit Work Email') === 'Yes') {
work_email = ['work_email', { label: 'Work Email', type: 'text', validation: 'email' }];
} else {
work_email = ['work_email', { label: 'Work Email', type: 'placeholder', validation: 'emailOrEmpty' }];
}
if (this.checkPermission('Edit Country') === 'Yes') {
country = ['country', { label: 'Country', type: 'select2', 'remote-source': ['Country', 'code', 'name'] }];
} else {
country = ['country', { label: 'Country', type: 'placeholder', 'remote-source': ['Country', 'code', 'name'] }];
}
const fields = [
['id', { label: 'ID', type: 'hidden', validation: '' }],
employee_id,
['first_name', { label: 'First Name', type: 'text', validation: '' }],
['middle_name', { label: 'Middle Name', type: 'text', validation: 'none' }],
['last_name', { label: 'Last Name', type: 'text', validation: '' }],
['nationality', { label: 'Nationality', type: 'select2', 'remote-source': ['Nationality', 'id', 'name'] }],
['birthday', { label: 'Date of Birth', type: 'date', validation: '' }],
['gender', { label: 'Gender', type: 'select', source: [['Male', 'Male'], ['Female', 'Female']] }],
['marital_status', { label: 'Marital Status', type: 'select', source: [['Married', 'Married'], ['Single', 'Single'], ['Divorced', 'Divorced'], ['Widowed', 'Widowed'], ['Other', 'Other']] }],
ssn_num,
['nic_num', { label: 'NIC', type: 'text', validation: 'none' }],
['other_id', { label: 'Other ID', type: 'text', validation: 'none' }],
['driving_license', { label: 'Driving License No', type: 'text', validation: 'none' }],
employment_status,
job_title,
pay_grade,
['work_station_id', { label: 'Work Station Id', type: 'text', validation: 'none' }],
['address1', { label: 'Address Line 1', type: 'text', validation: 'none' }],
['address2', { label: 'Address Line 2', type: 'text', validation: 'none' }],
['city', { label: 'City', type: 'text', validation: 'none' }],
country,
['province', {
label: 'Province', type: 'select2', 'allow-null': true, 'remote-source': ['Province', 'id', 'name'],
}],
['postal_code', { label: 'Postal/Zip Code', type: 'text', validation: 'none' }],
['home_phone', { label: 'Home Phone', type: 'text', validation: 'none' }],
['mobile_phone', { label: 'Mobile Phone', type: 'text', validation: 'none' }],
['work_phone', { label: 'Work Phone', type: 'text', validation: 'none' }],
work_email,
['private_email', { label: 'Private Email', type: 'text', validation: 'emailOrEmpty' }],
joined_date,
department,
];
for (let i = 0; i < this.customFields.length; i++) {
fields.push(this.customFields[i]);
}
for (let i = 0; i < fields.length; i++) {
const tempField = fields[i];
if (this.hiddenFields[tempField[0]] === undefined || this.hiddenFields[tempField[0]] === null) {
if (this.fieldNameMap[tempField[0]] !== undefined && this.fieldNameMap[tempField[0]] !== null) {
const title = this.fieldNameMap[tempField[0]].textMapped;
tempField[1].label = title;
}
newFields.push(tempField);
}
}
return newFields;
}
getSourceMapping() {
const k = this.sourceMapping;
k.supervisor = ['Employee', 'id', 'first_name+last_name'];
return k;
}
get() {
const sourceMappingJson = JSON.stringify(this.getSourceMapping());
const req = { map: sourceMappingJson };
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'modEmployeeGetSuccessCallBack';
callBackData.callBackFail = 'modEmployeeGetFailCallBack';
this.customAction('get', 'modules=employees', reqJson, callBackData);
}
deleteProfileImage(empId) {
const req = { id: empId };
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'modEmployeeDeleteProfileImageCallBack';
callBackData.callBackFail = 'modEmployeeDeleteProfileImageCallBack';
this.customAction('deleteProfileImage', 'modules=employees', reqJson, callBackData);
}
modEmployeeDeleteProfileImageCallBack(data) {
// eslint-disable-next-line no-restricted-globals
top.location.href = top.location.href;
}
modEmployeeGetSuccessCallBack(data) {
const fields = this.getFormFields();
const currentEmpId = data[1];
const userEmpId = data[2];
[data] = data;
let html = this.getCustomTemplate('myDetails.html');
for (let i = 0; i < fields.length; i++) {
if (this.fieldNameMap[fields[i][0]] !== undefined && this.fieldNameMap[fields[i][0]] !== null) {
const title = this.fieldNameMap[fields[i][0]].textMapped;
html = html.replace(`#_label_${fields[i][0]}_#`, this.gt(title));
}
}
html = html.replace(/#_.+_#/gi, '');
html = html.replace(/_id_/g, data.id);
$(`#${this.getTableName()}`).html(html);
for (let i = 0; i < fields.length; i++) {
$(`#${this.getTableName()} #${fields[i][0]}`).html(data[fields[i][0]]);
$(`#${this.getTableName()} #${fields[i][0]}_Name`).html(data[`${fields[i][0]}_Name`]);
}
$(`#${this.getTableName()} #supervisor_Name`).html(data.supervisor_Name);
let subordinates = '';
for (let i = 0; i < data.subordinates.length; i++) {
if (data.subordinates[i].first_name !== undefined && data.subordinates[i].first_name !== null) {
subordinates += `${data.subordinates[i].first_name} `;
}
if (data.subordinates[i].middle_name !== undefined && data.subordinates[i].middle_name !== null && data.subordinates[i].middle_name !== '') {
subordinates += `${data.subordinates[i].middle_name} `;
}
if (data.subordinates[i].last_name !== undefined && data.subordinates[i].last_name !== null && data.subordinates[i].last_name !== '') {
subordinates += data.subordinates[i].last_name;
}
subordinates += '<br/>';
}
// Add custom fields
if (data.customFields !== undefined && data.customFields !== null && Object.keys(data.customFields).length > 0) {
const ct = '<div class="col-xs-6 col-md-3" style="font-size:16px;"><label class="control-label col-xs-12" style="font-size:13px;">#_label_#</label><label class="control-label col-xs-12 iceLabel" style="font-size:13px;font-weight: bold;">#_value_#</label></div>';
const sectionTemplate = '<div class="panel panel-default" style="width:97.5%;"><div class="panel-heading"><h4>#_section.name_#</h4></div> <div class="panel-body" id="cont_#_section_#"> </div></div>';
let customFieldHtml;
for (const index in data.customFields) {
if (!data.customFields[index][1]) {
data.customFields[index][1] = this.gt('Other Details');
}
let sectionId = data.customFields[index][1].toLocaleLowerCase();
sectionId = sectionId.replace(' ', '_');
if ($(`#cont_${sectionId}`).length <= 0) {
// Add section
let sectionHtml = sectionTemplate;
sectionHtml = sectionHtml.replace('#_section_#', sectionId);
sectionHtml = sectionHtml.replace('#_section.name_#', data.customFields[index][1]);
$('#customFieldsCont').append($(sectionHtml));
}
customFieldHtml = ct;
customFieldHtml = customFieldHtml.replace('#_label_#', index);
if (data.customFields[index][2] === 'fileupload') {
customFieldHtml = customFieldHtml.replace(
'#_value_#',
`<button onclick="download('${data.customFields[index][0]}');return false;" class="btn btn-mini btn-inverse" type="button">View: ${index}</button>`,
);
} else {
customFieldHtml = customFieldHtml.replace('#_value_#', data.customFields[index][0]);
}
$(`#cont_${sectionId}`).append($(customFieldHtml));
}
} else {
$('#customFieldsCont').remove();
}
$(`#${this.getTableName()} #subordinates`).html(subordinates);
$(`#${this.getTableName()} #name`).html(`${data.first_name} ${data.last_name}`);
this.currentUserId = data.id;
$(`#${this.getTableName()} #profile_image_${data.id}`).attr('src', data.image);
if (this.checkPermission('Upload/Delete Profile Image') === 'No') {
$('#employeeUploadProfileImage').remove();
$('#employeeDeleteProfileImage').remove();
}
if (this.checkPermission('Edit Employee Details') === 'No') {
$('#employeeProfileEditInfo').remove();
}
if (currentEmpId !== userEmpId) {
$('#employeeUpdatePassword').remove();
}
this.cancel();
}
modEmployeeGetFailCallBack(data) {
}
editEmployee() {
this.edit(this.currentUserId);
}
changePassword() {
$('#adminUsersModel').modal('show');
$('#adminUsersChangePwd #newpwd').val('');
$('#adminUsersChangePwd #conpwd').val('');
}
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 = { pwd: conPassword };
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'changePasswordSuccessCallBack';
callBackData.callBackFail = 'changePasswordFailCallBack';
this.customAction('changePassword', 'modules=employees', 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);
}
}
/*
* Company Graph
*/
class CompanyStructureAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'title',
'address',
'type',
'country',
'parent',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Name' },
{ sTitle: 'Address' },
{ sTitle: 'Type' },
{ sTitle: 'Country', sClass: 'center' },
{ 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: 'select', 'remote-source': ['Country', 'code', 'name'] }],
['parent', {
label: 'Parent Structure', type: 'select', 'allow-null': true, 'remote-source': ['CompanyStructure', 'id', 'title'],
}],
];
}
}
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;
// eslint-disable-next-line prefer-destructuring
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')
// eslint-disable-next-line no-return-assign
.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)
// eslint-disable-next-line no-underscore-dangle
.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;
}
}
/*
* Api Access
*/
class ApiAccessAdapter extends AdapterBase {
getDataMapping() {
return [
];
}
getHeaders() {
return [
];
}
getFormFields() {
return [
];
}
setApiUrl(apiUrl) {
this.apiUrl = apiUrl;``
}
setToken(token) {
this.token = token;
}
get() {
const canvas = document.getElementById('apiQRcode');
QRCode.toCanvas(canvas, JSON.stringify({
key: 'IceHrm',
url: this.apiUrl,
token: this.token,
}), (error) => {
if (error) {
console.log(error);
}
});
}
}
module.exports = {
EmployeeAdapter,
CompanyGraphAdapter,
ApiAccessAdapter,
};
+5
View File
@@ -0,0 +1,5 @@
import {
EmployeeCompanyLoanAdapter,
} from './lib';
window.EmployeeCompanyLoanAdapter = EmployeeCompanyLoanAdapter;
+89
View File
@@ -0,0 +1,89 @@
/*
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 EmployeeCompanyLoanAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'loan',
'start_date',
'period_months',
'currency',
'amount',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Loan Type' },
{ sTitle: 'Loan Start Date' },
{ sTitle: 'Loan Period (Months)' },
{ sTitle: 'Currency' },
{ sTitle: 'Amount' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['loan', { label: 'Loan Type', type: 'placeholder', 'remote-source': ['CompanyLoan', 'id', 'name'] }],
['start_date', { label: 'Loan Start Date', type: 'placeholder', validation: '' }],
['last_installment_date', { label: 'Last Installment Date', type: 'placeholder', validation: 'none' }],
['period_months', { label: 'Loan Period (Months)', type: 'placeholder', validation: 'number' }],
['currency', { label: 'Currency', type: 'placeholder', 'remote-source': ['CurrencyType', 'id', 'name'] }],
['amount', { label: 'Loan Amount', type: 'placeholder', validation: 'float' }],
['monthly_installment', { label: 'Monthly Installment', type: 'placeholder', validation: 'float' }],
['status',
{
label: 'Status',
type: 'placeholder',
source: [['Approved', 'Approved'], ['Paid', 'Paid'], ['Suspended', 'Suspended']],
},
],
['details', { label: 'Details', type: 'placeholder', validation: 'none' }],
];
}
// eslint-disable-next-line no-unused-vars
getActionButtonsHtml(id, data) {
const editButton = '<img class="tableActionButton" '
+ 'src="_BASE_images/view.png" '
+ 'style="cursor:pointer;" '
+ 'rel="tooltip" title="View" '
+ '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>';
let html = '<div style="width:80px;">_edit__delete_</div>';
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;
}
}
module.exports = { EmployeeCompanyLoanAdapter };
+9
View File
@@ -0,0 +1,9 @@
import {
EmployeeOvertimeAdapter,
EmployeeOvertimeApproverAdapter,
SubordinateEmployeeOvertimeAdapter,
} from './lib';
window.EmployeeOvertimeAdapter = EmployeeOvertimeAdapter;
window.EmployeeOvertimeApproverAdapter = EmployeeOvertimeApproverAdapter;
window.SubordinateEmployeeOvertimeAdapter = SubordinateEmployeeOvertimeAdapter;
+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)
*/
import ApproveModuleAdapter from '../../../api/ApproveModuleAdapter';
import {
EmployeeOvertimeAdminAdapter,
} from '../../../admin/src/overtime/lib';
class EmployeeOvertimeAdapter extends ApproveModuleAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'Overtime';
this.itemNameLower = 'employeeovertime';
this.modulePathName = 'overtime';
}
getDataMapping() {
return [
'id',
'category',
'start_time',
'end_time',
'project',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Category' },
{ sTitle: 'Start Time' },
{ sTitle: 'End Time' },
{ sTitle: 'Project' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['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' }],
];
}
}
/*
EmployeeOvertimeApproverAdapter
*/
class EmployeeOvertimeApproverAdapter extends EmployeeOvertimeAdminAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'Overtime';
this.itemNameLower = 'employeeovertime';
this.modulePathName = 'overtime';
}
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') {
data.Approved = 'Approved';
data.Rejected = 'Rejected';
}
return data;
}
getStatusOptions(currentStatus) {
return this.generateOptions(this.getStatusOptionsData(currentStatus));
}
}
/*
EmployeeOvertimeAdapter
*/
class SubordinateEmployeeOvertimeAdapter extends EmployeeOvertimeAdminAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'Overtime';
this.itemNameLower = 'employeeovertime';
this.modulePathName = 'overtime';
}
}
module.exports = {
EmployeeOvertimeAdapter,
EmployeeOvertimeApproverAdapter,
SubordinateEmployeeOvertimeAdapter,
};
+5
View File
@@ -0,0 +1,5 @@
import {
EmployeeProjectAdapter,
} from './lib';
window.EmployeeProjectAdapter = EmployeeProjectAdapter;
+32
View File
@@ -0,0 +1,32 @@
/*
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 EmployeeProjectAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'project',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Project' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['project', { label: 'Project', type: 'select2', 'remote-source': ['Project', 'id', 'name'] }],
['details', { label: 'Details', type: 'textarea', validation: 'none' }],
];
}
}
module.exports = { EmployeeProjectAdapter };
+11
View File
@@ -0,0 +1,11 @@
import {
EmployeeSkillAdapter,
EmployeeEducationAdapter,
EmployeeCertificationAdapter,
EmployeeLanguageAdapter,
} from './lib';
window.EmployeeSkillAdapter = EmployeeSkillAdapter;
window.EmployeeEducationAdapter = EmployeeEducationAdapter;
window.EmployeeCertificationAdapter = EmployeeCertificationAdapter;
window.EmployeeLanguageAdapter = EmployeeLanguageAdapter;
+160
View File
@@ -0,0 +1,160 @@
import AdapterBase from '../../../api/AdapterBase';
class EmployeeSkillAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'skill_id',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Skill' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['skill_id', {
label: 'Skill', type: 'select2', 'allow-null': true, 'remote-source': ['Skill', 'id', 'name'],
}],
['details', { label: 'Details', type: 'textarea', validation: '' }],
];
}
}
/**
* EmployeeEducationAdapter
*/
class EmployeeEducationAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'education_id',
'institute',
'date_start',
'date_end',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Qualification' },
{ sTitle: 'Institute' },
{ sTitle: 'Start Date' },
{ sTitle: 'Completed On' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['education_id', {
label: 'Qualification', type: 'select2', 'allow-null': false, 'remote-source': ['Education', 'id', 'name'],
}],
['institute', { label: 'Institute', type: 'text', validation: '' }],
['date_start', { label: 'Start Date', type: 'date', validation: 'none' }],
['date_end', { label: 'Completed On', type: 'date', validation: 'none' }],
];
}
}
/**
* EmployeeCertificationAdapter
*/
class EmployeeCertificationAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'certification_id',
'institute',
'date_start',
'date_start',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Certification' },
{ sTitle: 'Institute' },
{ sTitle: 'Granted On' },
{ sTitle: 'Valid Thru' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['certification_id', {
label: 'Certification', type: 'select2', 'allow-null': false, 'remote-source': ['Certification', 'id', 'name'],
}],
['institute', { label: 'Institute', type: 'text', validation: '' }],
['date_start', { label: 'Granted On', type: 'date', validation: 'none' }],
['date_end', { label: 'Valid Thru', type: 'date', validation: 'none' }],
];
}
}
/**
* EmployeeLanguageAdapter
*/
class EmployeeLanguageAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'language_id',
'reading',
'speaking',
'writing',
'understanding',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Language' },
{ sTitle: 'Reading' },
{ sTitle: 'Speaking' },
{ sTitle: 'Writing' },
{ sTitle: 'Understanding' },
];
}
getFormFields() {
const compArray = [['Elementary Proficiency', 'Elementary Proficiency'],
['Limited Working Proficiency', 'Limited Working Proficiency'],
['Professional Working Proficiency', 'Professional Working Proficiency'],
['Full Professional Proficiency', 'Full Professional Proficiency'],
['Native or Bilingual Proficiency', 'Native or Bilingual Proficiency']];
return [
['id', { label: 'ID', type: 'hidden' }],
['language_id', {
label: 'Language', type: 'select2', 'allow-null': false, 'remote-source': ['Language', 'id', 'description'],
}],
['reading', { label: 'Reading', type: 'select', source: compArray }],
['speaking', { label: 'Speaking', type: 'select', source: compArray }],
['writing', { label: 'Writing', type: 'select', source: compArray }],
['understanding', { label: 'Understanding', type: 'select', source: compArray }],
];
}
}
module.exports = {
EmployeeSkillAdapter,
EmployeeEducationAdapter,
EmployeeCertificationAdapter,
EmployeeLanguageAdapter,
};
+5
View File
@@ -0,0 +1,5 @@
import {
UserReportAdapter,
} from './lib';
window.UserReportAdapter = UserReportAdapter;
+32
View File
@@ -0,0 +1,32 @@
/*
Copyright (c) 2018 [Glacies UG, Berlin, Germany] (http://glacies.de)
Developer: Thilina Hasantha (http://lk.linkedin.com/in/thilinah | https://github.com/thilinah)
*/
import {
ReportAdapter,
} from '../../../admin/src/reports/lib';
/**
* UserReportAdapter
*/
class UserReportAdapter extends ReportAdapter {
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;
}
}
module.exports = { UserReportAdapter };
+5
View File
@@ -0,0 +1,5 @@
import {
EmployeeSalaryAdapter,
} from './lib';
window.EmployeeSalaryAdapter = EmployeeSalaryAdapter;
+36
View File
@@ -0,0 +1,36 @@
/*
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 EmployeeSalaryAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'component',
'amount',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Salary Component' },
{ sTitle: 'Amount' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['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' }],
];
}
}
module.exports = { EmployeeSalaryAdapter };
+11
View File
@@ -0,0 +1,11 @@
import {
EmployeeTimeSheetAdapter,
SubEmployeeTimeSheetAdapter,
EmployeeTimeEntryAdapter,
QtsheetAdapter,
} from './lib';
window.EmployeeTimeSheetAdapter = EmployeeTimeSheetAdapter;
window.SubEmployeeTimeSheetAdapter = SubEmployeeTimeSheetAdapter;
window.EmployeeTimeEntryAdapter = EmployeeTimeEntryAdapter;
window.QtsheetAdapter = QtsheetAdapter;
+948
View File
@@ -0,0 +1,948 @@
/*
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, moment */
import AdapterBase from '../../../api/AdapterBase';
import FormValidation from '../../../api/FormValidation';
import TableEditAdapter from '../../../api/TableEditAdapter';
const ValidationRules = FormValidation.getValidationRules();
class EmployeeTimeSheetAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.currentTimesheetId = null;
this.currentTimesheet = null;
this.needStartEndTime = false;
}
getDataMapping() {
return [
'id',
'date_start',
'date_end',
'total_time',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Start Date' },
{ sTitle: 'End Date' },
{ sTitle: 'Total Time' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['date_start', { label: 'TimeSheet Start Date', type: 'date', validation: '' }],
['date_end', { label: 'TimeSheet End Date', type: 'date', validation: '' }],
['details', { label: 'Reason', type: 'textarea', validation: 'none' }],
];
}
preProcessTableData(_row) {
const row = _row;
row[1] = Date.parse(row[1]).toString('MMM d, yyyy (dddd)');
row[2] = Date.parse(row[2]).toString('MMM d, yyyy (dddd)');
return row;
}
setNeedStartEndTime(status) {
this.needStartEndTime = status;
}
renderForm(object) {
const formHtml = this.templates.formTemplate;
$('#EmployeeTimesheetBlock').remove();
$(`#${this.getTableName()}Form`).html(formHtml);
$(`#${this.getTableName()}Form`).show();
$(`#${this.getTableName()}`).hide();
$('.timesheet_start').html(Date.parse(object.date_start).toString('MMM d, yyyy (dddd)'));
$('.timesheet_end').html(Date.parse(object.date_end).toString('MMM d, yyyy (dddd)'));
this.currentTimesheet = object;
this.getTimeEntries();
const st = Date.parse(object.date_start);
$('#EmployeeTimesheetBlock').fullCalendar({
header: {
// left: 'prev,next today',
left: false,
// center: 'title',
center: false,
// right: 'month,agendaWeek,agendaDay'
right: false,
},
year: st.toString('yyyy'),
month: st.toString('M'),
date: st.toString('d'),
defaultView: 'basicWeek',
height: 200,
editable: false,
events: modJs.getScheduleJsonUrl(this.currentTimesheet.employee),
loading(bool) {
if (bool) $('#loadingBlock').show();
else $('#loadingBlock').hide();
},
// eslint-disable-next-line no-unused-vars
dayClick(date, jsEvent, view, resourceObj) {
modJs.renderFormByDate(date.format());
},
// eslint-disable-next-line no-unused-vars
eventClick(calEvent, jsEvent, view) {
modJs.renderFormTimeEntryCalender(calEvent.id);
},
eventRender(event, element) {
element.find('.fc-time').remove();
},
});
$('#EmployeeTimesheetBlock').fullCalendar('gotoDate', st);
$('.fc-toolbar').hide();
}
quickEdit(id, status, sdate, edate) {
$('#Qtsheet').data('lastActiveTab', modJs.tab);
// eslint-disable-next-line no-global-assign
modJs = modJsList.tabQtsheet;
modJs.setCurrentTimeSheetId(id);
$('.timesheet_start').html(sdate);
$('.timesheet_end').html(edate);
$('#timesheetTabs').find('.active').find('.reviewBlock.reviewBlockTable').hide();
$('#QtsheetHeader').show();
$('#Qtsheet').show();
$('#QtsheetDataButtons').show();
if (status === 'Submitted' || status === 'Approved') {
$('.completeBtnTable').hide();
$('.saveBtnTable').hide();
} else {
$('.completeBtnTable').show();
$('.saveBtnTable').show();
}
modJs.get([]);
}
getScheduleJsonUrl(employeeId) {
const url = `${this.moduleRelativeURL}?a=ca&sa=getEmployeeTimeEntries&t=${this.table}&mod=modules%3Dtime_sheets&e=${employeeId}`;
return url;
}
renderFormByDate(_date) {
let date = _date;
if (date.indexOf('T') < 0) {
const s1 = moment();
date = `${date} ${s1.format('HH:mm:ss')}`;
}
const start = date.replace('T', ' ');
const m1 = moment(start);
m1.add(1, 'h');
const end = m1.format('YYYY-MM-DD HH:mm:ss');
const obj = {};
obj.date = _date;
obj.date_start = start;
obj.date_end = end;
this.renderFormTimeEntryCalender(obj);
}
renderFormTimeEntryCalender(object) {
if (`${this.needStartEndTime}` === '0') {
return;
}
this.openTimeEntryDialog(object);
if (object.id !== undefined && object.id != null) {
const cid = object.id;
$('.deleteBtnWorkSchedule').show();
$('.deleteBtnWorkSchedule').off().on('click', () => {
modJs.deleteRow(cid);
return false;
});
} else {
$('.deleteBtnWorkSchedule').remove();
}
}
openTimeEntryDialog(object) {
this.currentTimesheetId = this.currentId;
const obj = modJsList.tabEmployeeTimeEntry;
$('#TimeEntryModel').modal({
backdrop: 'static',
keyboard: false,
});
obj.currentTimesheet = this.currentTimesheet;
obj.renderForm(object);
obj.timesheetId = this.currentId;
}
closeTimeEntryDialog() {
$('#TimeEntryModel').modal('hide');
}
getTimeEntries() {
const timesheetId = this.currentId;
const sourceMappingJson = JSON.stringify(modJsList.tabEmployeeTimeEntry.getSourceMapping());
const object = { id: timesheetId, sm: sourceMappingJson };
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'getTimeEntriesSuccessCallBack';
callBackData.callBackFail = 'getTimeEntriesFailCallBack';
this.customAction('getTimeEntries', 'modules=time_sheets', reqJson, callBackData);
}
getTimeEntriesSuccessCallBack(callBackData) {
const entries = callBackData;
let html = '';
const temp = '<tr><td><img class="tableActionButton" src="_BASE_images/delete.png" style="cursor:pointer;" rel="tooltip" title="Delete" onclick="modJsList[\'tabEmployeeTimeEntry\'].deleteRow(_id_);return false;"></img></td><td>_start_</td><td>_end_</td><td>_duration_</td><td>_project_</td><td>_details_</td>';
for (let i = 0; i < entries.length; i++) {
try {
let t = temp;
t = t.replace(/_start_/g, Date.parse(entries[i].date_start).toString('MMM d, yyyy [hh:mm tt]'));
t = t.replace(/_end_/g, Date.parse(entries[i].date_end).toString('MMM d, yyyy [hh:mm tt]'));
const mili = Date.parse(entries[i].date_end) - Date.parse(entries[i].date_start);
const minutes = Math.round(mili / 60000);
const hourMinutes = (minutes % 60);
const hours = (minutes - hourMinutes) / 60;
t = t.replace(/_duration_/g, `Hours (${hours}) - Min (${hourMinutes})`);
if (entries[i].project === 'null' || entries[i].project == null || entries[i].project === undefined) {
t = t.replace(/_project_/g, 'None');
} else {
t = t.replace(/_project_/g, entries[i].project);
}
t = t.replace(/_project_/g, entries[i].project);
t = t.replace(/_details_/g, entries[i].details);
t = t.replace(/_id_/g, entries[i].id);
t = t.replace(/_BASE_/g, this.baseUrl);
html += t;
} catch (e) {
// Do nothing
}
}
$('.timesheet_entries_table_body').html(html);
if (modJs.getTableName() === 'SubEmployeeTimeSheetAll' || `${this.needStartEndTime}` === '0') {
$('.submit_sheet').hide();
$('.add_time_sheet_entry').hide();
} else if (this.currentElement.status === 'Approved') {
$('.submit_sheet').hide();
$('.add_time_sheet_entry').hide();
} else {
$('.submit_sheet').show();
$('.add_time_sheet_entry').show();
}
$('#EmployeeTimesheetBlock').fullCalendar('refetchEvents');
}
// eslint-disable-next-line no-unused-vars
getTimeEntriesFailCallBack(callBackData) {
this.showMessage('Error', 'Error occured while getting timesheet entries');
}
createPreviousTimesheet(id) {
const object = { id };
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'createPreviousTimesheetSuccessCallBack';
callBackData.callBackFail = 'createPreviousTimesheetFailCallBack';
this.customAction('createPreviousTimesheet', 'modules=time_sheets', reqJson, callBackData);
}
// eslint-disable-next-line no-unused-vars
createPreviousTimesheetSuccessCallBack(callBackData) {
$('.tooltip').css('display', 'none');
$('.tooltip').remove();
// this.showMessage("Success", "Previous Timesheet created");
this.get([]);
}
createPreviousTimesheetFailCallBack(callBackData) {
this.showMessage('Error', callBackData);
}
changeTimeSheetStatusWithId(id, status) {
if (status === '' || status == null || status === undefined) {
this.showMessage('Status Error', 'Please select a status');
return;
}
const object = { id, status };
const reqJson = JSON.stringify(object);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'changeTimeSheetStatusSuccessCallBack';
callBackData.callBackFail = 'changeTimeSheetStatusFailCallBack';
this.customAction('changeTimeSheetStatus', 'modules=time_sheets', reqJson, callBackData);
}
// eslint-disable-next-line no-unused-vars
changeTimeSheetStatusSuccessCallBack(callBackData) {
this.showMessage('Successful', 'Timesheet status changed successfully');
this.get([]);
}
// eslint-disable-next-line no-unused-vars
changeTimeSheetStatusFailCallBack(callBackData) {
this.showMessage('Error', 'Error occured while changing Timesheet status');
}
getActionButtonsHtml(id, data) {
let html = '';
if (`${this.needStartEndTime}` === '0') {
html = '<div style="width:100px;">'
+ '<img class="tableActionButton" src="_BASE_images/view.png" style="cursor:pointer;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.edit(_id_);return false;"></img>'
+ '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;margin-left:15px;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.quickEdit(_id_,\'_status_\',\'_sdate_\',\'_edate_\');return false;"></img>'
+ '_redoBtn_'
+ '</div>';
} else {
html = '<div style="width:80px;">'
+ '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.edit(_id_);return false;"></img>'
+ '_redoBtn_'
+ '</div>';
}
if (this.getTableName() === 'EmployeeTimeSheetAll') {
const redoBtn = '<img class="tableActionButton" src="_BASE_images/redo.png" style="cursor:pointer;margin-left:15px;" rel="tooltip" title="Create previous time sheet" onclick="modJs.createPreviousTimesheet(_id_);return false;"></img>';
html = html.replace(/_redoBtn_/g, redoBtn);
} else {
html = html.replace(/_redoBtn_/g, '');
}
html = html.replace(/_id_/g, id);
html = html.replace(/_sdate_/g, data[1]);
html = html.replace(/_edate_/g, data[2]);
html = html.replace(/_status_/g, data[4]);
html = html.replace(/_BASE_/g, this.baseUrl);
return html;
}
getCustomTableParams() {
const that = this;
const dataTableParams = {
aoColumnDefs: [
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 1);
},
aTargets: [1],
},
{
fnRender(data, cell) {
return that.preProcessRemoteTableData(data, cell, 2);
},
aTargets: [2],
},
{
fnRender: that.getActionButtons,
aTargets: [that.getDataMapping().length],
},
],
};
return dataTableParams;
}
// eslint-disable-next-line no-unused-vars
preProcessRemoteTableData(data, cell, id) {
return Date.parse(cell).toString('MMM d, yyyy (dddd)');
}
}
/*
* Subordinate TimeSheets
*/
class SubEmployeeTimeSheetAdapter extends EmployeeTimeSheetAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.timeSheetStatusChangeId = null;
}
getDataMapping() {
return [
'id',
'employee',
'date_start',
'date_end',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Employee', bSearchable: true },
{ sTitle: 'Start Date', bSearchable: true },
{ sTitle: 'End Date', bSearchable: true },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['employee', {
label: 'Employee', type: 'select', 'allow-null': false, 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
['date_start', { label: 'TimeSheet Start Date', type: 'date', validation: '' }],
['date_end', { label: 'TimeSheet Start Date', type: 'date', validation: '' }],
['details', { label: 'Reason', type: 'textarea', validation: 'none' }],
];
}
isSubProfileTable() {
return true;
}
getCustomSuccessCallBack(serverData) {
const data = [];
const mapping = this.getDataMapping();
for (let i = 0; i < serverData.length; i++) {
const row = [];
for (let j = 0; j < mapping.length; j++) {
row[j] = serverData[i][mapping[j]];
}
data.push(this.preProcessTableData(row));
}
this.tableData = data;
this.createTable(this.getTableName());
$(`#${this.getTableName()}Form`).hide();
$(`#${this.getTableName()}`).show();
}
preProcessTableData(_row) {
const row = _row;
row[2] = Date.parse(row[2]).toString('MMM d, yyyy (dddd)');
row[3] = Date.parse(row[3]).toString('MMM d, yyyy (dddd)');
return row;
}
openTimeSheetStatus(timeSheetId, status) {
this.currentTimesheetId = timeSheetId;
$('#TimeSheetStatusModel').modal('show');
$('#timesheet_status').val(status);
this.timeSheetStatusChangeId = timeSheetId;
}
closeTimeSheetStatus() {
$('#TimeSheetStatusModel').modal('hide');
}
changeTimeSheetStatus() {
const timeSheetStatus = $('#timesheet_status').val();
this.changeTimeSheetStatusWithId(this.timeSheetStatusChangeId, timeSheetStatus);
this.closeTimeSheetStatus();
this.timeSheetStatusChangeId = null;
}
getActionButtonsHtml(id, data) {
let html;
if (`${this.needStartEndTime}` === '0') {
html = '<div style="width:100px;">'
+ '<img class="tableActionButton" src="_BASE_images/view.png" style="cursor:pointer;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.edit(_id_);return false;"></img>'
+ '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;margin-left:15px;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.quickEdit(_id_,\'_status_\',\'_sdate_\',\'_edate_\');return false;"></img>'
+ '<img class="tableActionButton" src="_BASE_images/run.png" style="cursor:pointer;margin-left:15px;" rel="tooltip" title="Change TimeSheet Status" onclick="modJs.openTimeSheetStatus(_id_,\'_status_\');return false;"></img>'
+ '</div>';
} else {
html = '<div style="width:80px;">'
+ '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit Timesheet Entries" onclick="modJs.edit(_id_);return false;"></img>'
+ '<img class="tableActionButton" src="_BASE_images/run.png" style="cursor:pointer;margin-left:15px;" rel="tooltip" title="Change TimeSheet Status" onclick="modJs.openTimeSheetStatus(_id_,\'_status_\');return false;"></img>'
+ '</div>';
}
html = html.replace(/_id_/g, id);
html = html.replace(/_BASE_/g, this.baseUrl);
html = html.replace(/_sdate_/g, data[1]);
html = html.replace(/_edate_/g, data[2]);
html = html.replace(/_status_/g, data[4]);
return html;
}
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: that.getActionButtons,
aTargets: [that.getDataMapping().length],
},
],
};
return dataTableParams;
}
getFilters() {
return [
['employee', {
label: 'Employee', type: 'select2', 'allow-null': true, 'null-label': 'All Employees', 'remote-source': ['Employee', 'id', 'first_name+last_name'],
}],
['status', {
label: 'Status', type: 'select', 'allow-null': true, 'null-label': 'All', source: [['Submitted', 'Submitted'], ['Pending', 'Pending'], ['Approved', 'Approved'], ['Rejected', 'Rejected']],
}],
];
}
}
/**
* EmployeeTimeEntryAdapter
*/
class EmployeeTimeEntryAdapter extends AdapterBase {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.timesheetId = null;
this.currentTimesheet = null;
this.allProjectsAllowed = 1;
this.employeeProjects = [];
}
getDataMapping() {
return [
'id',
'project',
'date_start',
'time_start',
'date_end',
'time_end',
'details',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Project' },
{ sTitle: 'Start Date' },
{ sTitle: 'Start Time' },
{ sTitle: 'End Date' },
{ sTitle: 'End Time' },
{ sTitle: 'Details' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['project', {
label: 'Project', type: 'select2', 'allow-null': false, 'remote-source': ['Project', 'id', 'name', 'getEmployeeProjects'],
}],
['date_select', { label: 'Date', type: 'select', source: [] }],
['date_start', { label: 'Start Time', type: 'time', validation: '' }],
['date_end', { label: 'End Time', type: 'time', validation: '' }],
['details', { label: 'Details', type: 'textarea', validation: '' }],
];
}
getDates(startDate, stopDate) {
const dateArray = [];
let currentDate = startDate;
while (currentDate <= stopDate) {
dateArray.push(new Date(currentDate));
currentDate = currentDate.add({ days: 1 });
}
return dateArray;
}
renderForm(object) {
let formHtml = this.getCustomTemplate('time_entry_form.html');
formHtml = formHtml.replace(/modJs/g, "modJsList['tabEmployeeTimeEntry']");
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]);
}
}
}
// append dates
// var dateStart = new Date(this.currentTimesheet.date_start);
// var dateStop = new Date(this.currentTimesheet.date_end);
// var datesArray = this.getDates(dateStart, dateStop);
let optionList = '';
for (let i = 0; i < this.currentTimesheet.days.length; i++) {
const k = this.currentTimesheet.days[i];
// optionList += '<option value="'+timeUtils.getMySQLFormatDate(k)+'">'+k.toUTCString().slice(0, -13)+'</option>';
optionList += `<option value="${k[0]}">${k[1]}</option>`;
}
formHtml = formHtml.replace(/_id_/g, `${this.getTableName()}_submit`);
formHtml = formHtml.replace(/_fields_/g, html);
$(`#${this.getTableName()}Form`).html(formHtml);
$(`#${this.getTableName()}Form`).show();
$(`#${this.getTableName()}`).hide();
$(`#${this.getTableName()}Form .datefield`).datepicker({ viewMode: 2 });
$(`#${this.getTableName()}Form .datetimefield`).datetimepicker({
language: 'en',
});
$(`#${this.getTableName()}Form .timefield`).datetimepicker({
language: 'en',
pickDate: false,
});
$(`#${this.getTableName()}Form .select2Field`).select2();
$('#date_select').html(optionList);
if (object !== undefined && object != null) {
this.fillForm(object);
}
}
// eslint-disable-next-line no-unused-vars
fillForm(object, _formId, fields) {
let formId = _formId;
if (formId == null || formId === undefined || formId === '') {
formId = `#${this.getTableName()}Form`;
}
if (object.id != null && object.id !== undefined) {
$(`${formId} #id`).val(object.id);
}
if (object.project != null && object.project !== undefined) {
$(`${formId} #project`).select2('val', object.project);
}
if (object.date != null && object.date !== undefined) {
$(`${formId} #date_select`).val(object.date);
}
}
cancel() {
$('#TimeEntryModel').modal('hide');
}
setAllProjectsAllowed(allProjectsAllowed) {
this.allProjectsAllowed = allProjectsAllowed;
}
setEmployeeProjects(employeeProjects) {
this.employeeProjects = employeeProjects;
}
save() {
const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' });
if (validator.checkValues()) {
const params = validator.getFormParameters();
params.timesheet = this.timesheetId;
params.time_start = params.date_start;
params.time_end = params.date_end;
params.date_start = `${params.date_select} ${params.date_start}`;
params.date_end = `${params.date_select} ${params.date_end}`;
const msg = this.doCustomValidation(params);
if (msg == null) {
const id = $(`#${this.getTableName()}_submit #id`).val();
if (id != null && id !== undefined && id !== '') {
params.id = id;
}
this.add(params, []);
this.cancel();
} else {
$(`#${this.getTableName()}Form .label`).html(msg);
$(`#${this.getTableName()}Form .label`).show();
}
}
}
doCustomValidation(params) {
const st = Date.parse(params.date_start);
const et = Date.parse(params.date_end);
if (st.compareTo(et) !== -1) {
return 'Start time should be less than End time';
}
/*
var sd = Date.parse(this.currentTimesheet.date_start);
var ed = Date.parse(this.currentTimesheet.date_end).addDays(1);
if(sd.compareTo(et) != -1 || sd.compareTo(st) > 0 || st.compareTo(ed) != -1 || et.compareTo(ed) != -1){
return "Start time and end time shoud be with in " + sd.toString('MMM d, yyyy (dddd)') + " and " + ed.toString('MMM d, yyyy (dddd)');
}
*/
return null;
}
// eslint-disable-next-line no-unused-vars
addSuccessCallBack(callBackData, serverData) {
this.get(callBackData);
modJs.getTimeEntries();
}
deleteRow(id) {
this.deleteObj(id, []);
}
// eslint-disable-next-line no-unused-vars
deleteSuccessCallBack(callBackData, serverData) {
modJs.getTimeEntries();
}
}
/**
* QtsheetAdapter
*/
class QtsheetAdapter extends TableEditAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.cellDataUpdates = {};
this.currentId = null;
}
validateCellValue(element, evt, newValue) {
if (!ValidationRules.float(newValue)) {
return false;
}
const val = parseFloat(newValue);
if (val < 0 || val > 24) {
return false;
}
// Update total
// Find current column number
// Adding 2 because nth child is based on 1 and we are adding a virtual column for row names
const coldNum = this.columnIDMap[element.data('colId')] + 2;
let columnTotal = 0;
let columnTotalWithoutCurrent = 0;
$(`#${this.getTableName()} tr td:nth-child(${coldNum})`).each(function () {
const rowId = $(this).data('rowId');
let tval = '';
if (element.data('rowId') === rowId) {
tval = newValue;
} else {
tval = $(this).html();
}
if (rowId !== -1) {
if (ValidationRules.float(tval)) {
columnTotal += parseFloat(tval);
if (element.data('rowId') !== rowId) {
columnTotalWithoutCurrent += parseFloat(tval);
}
}
} else if (columnTotal > 24) {
$(this).html(columnTotalWithoutCurrent);
} else {
$(this).html(columnTotal);
}
});
if (columnTotal > 24) {
return false;
}
modJs.addCellDataUpdate(element.data('colId'), element.data('rowId'), newValue);
return true;
}
setCurrentTimeSheetId(val) {
this.currentId = val;
this.cellDataUpdates = {};
}
addAdditionalRequestData(type, req) {
if (type === 'updateData') {
req.currentId = this.currentId;
} else if (type === 'updateAllData') {
req.currentId = this.currentId;
} else if (type === 'getAllData') {
req.currentId = this.currentId;
}
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;
}
downloadTimesheet() {
const element = document.createElement('a');
element.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(this.getCSVData())}`);
element.setAttribute('download', `timesheet_${this.currentId}.csv`);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
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) * 100 - 100;
}
$(`#${elementId}`).html(html);
const dataTableParams = {
oLanguage: {
sLengthMenu: '_MENU_ records per page',
},
aaData: data,
aoColumns: headers,
bSort: false,
iDisplayLength: 100,
iDisplayStart: start,
};
const customTableParams = this.getCustomTableParams();
$.extend(dataTableParams, customTableParams);
$(`#${elementId} #grid`).dataTable(dataTableParams);
$(`#${elementId} #grid tr:last`).find('td').removeClass('editcell');
$('.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);
});
}
}
module.exports = {
EmployeeTimeSheetAdapter,
SubEmployeeTimeSheetAdapter,
EmployeeTimeEntryAdapter,
QtsheetAdapter,
};
+11
View File
@@ -0,0 +1,11 @@
import {
EmployeeImmigrationAdapter,
EmployeeTravelRecordAdapter,
EmployeeTravelRecordApproverAdapter,
SubordinateEmployeeTravelRecordAdapter,
} from './lib';
window.EmployeeImmigrationAdapter = EmployeeImmigrationAdapter;
window.EmployeeTravelRecordAdapter = EmployeeTravelRecordAdapter;
window.EmployeeTravelRecordApproverAdapter = EmployeeTravelRecordApproverAdapter;
window.SubordinateEmployeeTravelRecordAdapter = SubordinateEmployeeTravelRecordAdapter;
+181
View File
@@ -0,0 +1,181 @@
/*
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 ApproveModuleAdapter from '../../../api/ApproveModuleAdapter';
import {
EmployeeTravelRecordAdminAdapter,
} from '../../../admin/src/travel/lib';
class EmployeeImmigrationAdapter extends AdapterBase {
getDataMapping() {
return [
'id',
'document',
'documentname',
'valid_until',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Document' },
{ sTitle: 'Document Id' },
{ sTitle: 'Valid Until' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return [
['id', { label: 'ID', type: 'hidden' }],
['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' }],
];
}
}
class EmployeeTravelRecordAdapter extends ApproveModuleAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'Travel';
this.itemNameLower = 'employeetravelrecord';
this.modulePathName = 'travel';
}
getDataMapping() {
return [
'id',
'type',
'purpose',
'travel_from',
'travel_to',
'travel_date',
'return_date',
'status',
];
}
getHeaders() {
return [
{ sTitle: 'ID', bVisible: false },
{ sTitle: 'Travel Type' },
{ sTitle: 'Purpose' },
{ sTitle: 'From' },
{ sTitle: 'To' },
{ sTitle: 'Travel Date' },
{ sTitle: 'Return Date' },
{ sTitle: 'Status' },
];
}
getFormFields() {
return this.addCustomFields([
['id', { label: 'ID', type: 'hidden' }],
['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' }],
]);
}
}
/*
EmployeeTravelRecordApproverAdapter
*/
class EmployeeTravelRecordApproverAdapter extends EmployeeTravelRecordAdminAdapter {
constructor(endPoint, tab, filter, orderBy) {
super(endPoint, tab, filter, orderBy);
this.itemName = 'Travel';
this.itemNameLower = 'employeetravelrecord';
this.modulePathName = 'travel';
}
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') {
data.Approved = 'Approved';
data.Rejected = 'Rejected';
}
return data;
}
getStatusOptions(currentStatus) {
return this.generateOptions(this.getStatusOptionsData(currentStatus));
}
}
/*
SubordinateExpenseModuleAdapter
*/
class SubordinateEmployeeTravelRecordAdapter extends EmployeeTravelRecordAdminAdapter {
}
module.exports = {
EmployeeImmigrationAdapter,
EmployeeTravelRecordAdapter,
EmployeeTravelRecordApproverAdapter,
SubordinateEmployeeTravelRecordAdapter,
};