Compare commits

...

27 Commits

Author SHA1 Message Date
dependabot[bot]
91f934ec51 Bump y18n from 3.2.1 to 3.2.2
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-30 12:28:55 +00:00
Gamonoid
92032cf1eb Update readme.md 2021-01-12 19:55:00 +01:00
Gamonoid
22cd81611d Add applity 2020-12-20 20:32:30 +01:00
Alan Cell
88962d4380 Merge branch 'release/v28.2.0.OS' 2020-11-13 02:46:51 +01:00
Alan Cell
b73e244865 Production build, release notes and version update for v28.2.0 2020-11-13 02:45:48 +01:00
Alan Cell
5f050282f0 Update readme and change delete label for employees 2020-11-13 02:43:40 +01:00
Alan Cell
f1dcc6b6a0 Merge branch 'release/v28.1.1.OS' 2020-11-07 12:52:02 +01:00
Alan Cell
e5eccf32a7 Merge tag 'v28.1.1.OS' into develop
v28.1.1.OS
2020-11-07 12:52:02 +01:00
Alan Cell
b6c0256b49 Update production build 2020-11-07 12:37:11 +01:00
Alan Cell
e31bf5a4b9 Fix api issues and production build 2020-11-07 12:25:12 +01:00
Alan Cell
06a3172a38 Merge branch 'release/v28.1.1.OS' 2020-11-07 11:46:23 +01:00
Alan Cell
e74ca00902 Merge tag 'v28.1.1.OS' into develop
v28.1.1.OS
2020-11-07 11:46:23 +01:00
Alan Cell
28aa16f35c Update version 2020-11-07 11:45:05 +01:00
Alan Cell
fb3b5b562e Merge branch 'release/v28.1.1.OS' 2020-11-07 11:41:24 +01:00
Alan Cell
8663a7aff1 Merge tag 'v28.1.1.OS' into develop
v28.1.1.OS
2020-11-07 11:41:24 +01:00
Alan Cell
e9baf45d7c Production build + fixing code style issues 2020-11-06 20:08:07 +01:00
Alan Cell
2abe52963f Imitate the REST api using url parameter based implementation
Reason for this implementation is some clients having trouble configuring the rest api either due to not having proper access to the webserver in a shared hosting environment or security restrictions. But still from icehrm frontend we need to consume the backend rest api.
2020-11-06 20:00:53 +01:00
Alan Cell
da55c7a2d2 Ability to delete files from S3 2020-11-06 19:41:56 +01:00
Alan Cell
5cd7963f6f Implement password change for employee profile 2020-11-06 19:38:48 +01:00
Alan Cell
d986a2b5bb Fix issue: employee not be selected when filtering employee documents 2020-11-06 19:32:52 +01:00
Alan Cell
1ee4fb4ba1 Update vagrant file 2020-11-06 19:23:05 +01:00
Alan Cell
b06780c466 Fix issue with time-sheets module nit being able to load projects 2020-11-06 18:51:46 +01:00
Alan Cell
5ec497e11d Upgrade vagrant config 2020-11-06 18:41:39 +01:00
Alan Cell
df3b6e968a Update vagrant 2020-11-06 09:46:20 +01:00
Thilina Pituwala
3ceb427479 Fix ci build 2020-11-01 10:17:04 +01:00
Thilina Pituwala
d3b4748cba Remove in lage in readme 2020-11-01 02:37:33 +01:00
Thilina Pituwala
2a9e65d8a8 Remove php5.6 from travis 2020-11-01 02:31:57 +01:00
43 changed files with 1329 additions and 31687 deletions

View File

@@ -14,7 +14,6 @@ install:
script: ant build-ci script: ant build-ci
language: php language: php
php: php:
- '5.6'
- '7.0' - '7.0'
- '7.1' - '7.1'
- '7.2' - '7.2'

16
Vagrantfile vendored
View File

@@ -3,8 +3,6 @@ Vagrant.configure("2") do |config|
config.vm.box_version = "1.0.0" config.vm.box_version = "1.0.0"
config.vm.network "private_network", ip: "192.168.10.12" config.vm.network "private_network", ip: "192.168.10.12"
config.vm.synced_folder ".", "/vagrant", type: "nfs" config.vm.synced_folder ".", "/vagrant", type: "nfs"
config.vm.synced_folder "./deployment/vagrant/sites-available", "/etc/nginx/sites-enabled", type: "nfs"
config.vm.synced_folder "./deployment/vagrant/ssl", "/etc/nginx/ssl", type: "nfs"
config.vm.provider "virtualbox" do |vb| config.vm.provider "virtualbox" do |vb|
vb.memory = "1024" vb.memory = "1024"
@@ -13,9 +11,17 @@ Vagrant.configure("2") do |config|
end end
config.vm.provision "shell", inline: <<-SHELL config.vm.provision "shell", inline: <<-SHELL
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config sudo rm /etc/nginx/ssl/icehrm.*
systemctl restart sshd.service sudo ln -s /vagrant/deployment/vagrant/ssl/icehrm.crt /etc/nginx/ssl/icehrm.crt
sudo service nginx restart sudo ln -s /vagrant/deployment/vagrant/ssl/icehrm.key /etc/nginx/ssl/icehrm.key
sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /vagrant/deployment/vagrant/sites-available/default /etc/nginx/sites-enabled/default
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
sudo service nginx restart
sudo chmod 755 -R /var/log
SHELL SHELL
config.vm.hostname = "icehrm.os" config.vm.hostname = "icehrm.os"

View File

@@ -1,3 +1,3 @@
<?php <?php
include ('config.php'); include ('config.php');
include (APP_BASE_PATH.'rest.php'); include (APP_BASE_PATH.'rest.php');

1
bin/export-plural-rules Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/gettext/languages/bin/export-plural-rules

1
bin/markdown Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/cebe/markdown/bin/markdown

1
bin/pdepend Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/pdepend/pdepend/src/bin/pdepend

1
bin/phpcb Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/mayflower/php-codebrowser/bin/phpcb

1
bin/phpcbf Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/squizlabs/php_codesniffer/scripts/phpcbf

1
bin/phpcpd Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/sebastian/phpcpd/composer/bin/phpcpd

1
bin/phpcs Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/squizlabs/php_codesniffer/scripts/phpcs

1
bin/phploc Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/phploc/phploc/phploc

1
bin/phpmd Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/phpmd/phpmd/src/bin/phpmd

1
bin/phpunit Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/phpunit/phpunit/phpunit

1
bin/release Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/consolidation/self-update/scripts/release

1
bin/robo Symbolic link
View File

@@ -0,0 +1 @@
../core/lib/composer/vendor/consolidation/robo/robo

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project name="icehrm" default="build"> <project name="icehrm" default="build">
<!-- By default, we assume all tools to be on the $PATH --> <!-- By default, we assume all tools to be on the $PATH -->
<property name="toolsdir" value="${basedir}/tools/"/> <property name="toolsdir" value="${basedir}/bin/"/>
<property name="destination" value="${basedir}/build/app"/> <property name="destination" value="${basedir}/build/app"/>
<property name="testdir" value="${basedir}/build/test"/> <property name="testdir" value="${basedir}/build/test"/>
<property name="origin" value="${basedir}"/> <property name="origin" value="${basedir}"/>

47
core/api-rest.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
define('CLIENT_PATH',dirname(__FILE__));
include ("config.base.php");
include ("include.common.php");
include("server.includes.inc.php");
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
if (defined('SYM_CLIENT')) {
define('REST_API_PATH', '/'.SYM_CLIENT.'/');
} else if (!defined('REST_API_PATH')){
define('REST_API_PATH', '/');
}
\Utils\LogManager::getInstance()->info("Request: " . $_REQUEST);
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
$echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () {
echo "Echo " . rand();
});
\Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute);
$moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers();
foreach ($moduleManagers as $moduleManagerObj) {
$moduleManagerObj->setupRestEndPoints();
}
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
\Utils\LogManager::getInstance()->debug('Api dispatch URI: '.$uri);
\Utils\LogManager::getInstance()->debug('Api dispatch method: '.$uri);
if (!defined('SYM_CLIENT')) {
//For hosted installations, dispatch will be done in app/index
\Classes\Macaw::dispatch();
}
}else{
echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true";
}

41
core/api-url-based.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
define('CLIENT_PATH',dirname(__FILE__));
include ("config.base.php");
include ("include.common.php");
include("server.includes.inc.php");
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
\Utils\LogManager::getInstance()->info("Request: " . $_REQUEST);
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
define('REST_API_PATH', '/');
$echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () {
echo "Echo " . rand();
});
\Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute);
$moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers();
foreach ($moduleManagers as $moduleManagerObj) {
$moduleManagerObj->setupRestEndPoints();
}
$method = $_SERVER['REQUEST_METHOD'];
if (strtoupper($method) === 'GET') {
\Classes\IceRoute::dispatch($_GET['url'], $method);
} else {
$method = strtoupper($_REQUEST['method']);
\Classes\IceRoute::dispatch($_REQUEST['url'], $method);
}
}else{
echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true";
}

View File

@@ -13,10 +13,10 @@ if(!defined('HOME_LINK_OTHERS')){
} }
//Version //Version
define('VERSION', '28.1.0.OS'); define('VERSION', '28.2.0.OS');
define('CACHE_VALUE', '28.1.0.OS.2020-10311445'); define('CACHE_VALUE', '28.2.0.OS.2020-11130243');
define('VERSION_NUMBER', '280100'); define('VERSION_NUMBER', '280200');
define('VERSION_DATE', '31/10/2020'); define('VERSION_DATE', '13/11/2020');
if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');} if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');}
if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');} if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');}

View File

@@ -277,7 +277,7 @@ $csrfToken = sha1(rand(4500, 100000) . time(). CLIENT_BASE_URL);
<div class="col-lg-6 col-md-8 col-xs-10"> <div class="col-lg-6 col-md-8 col-xs-10">
<div class="bg-white-2 h-100 px-11 pt-11 pb-7"> <div class="bg-white-2 h-100 px-11 pt-11 pb-7">
<div class="row d-flex justify-content-center"> <div class="row d-flex justify-content-center">
<img src="<?=$logoFileUrl?>"/> <img src="<?=$logoFileUrl?>" style="max-width:100%;max-height:280px;"/>
</div> </div>
<hr/> <hr/>
<?php if ($gsuiteEnabled) {?> <?php if ($gsuiteEnabled) {?>

View File

@@ -3,49 +3,8 @@ header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: DELETE, POST, GET, OPTIONS'); header('Access-Control-Allow-Methods: DELETE, POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With'); header('Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
header('Content-Type: application/json'); header('Content-Type: application/json');
define('CLIENT_PATH',dirname(__FILE__)); if (isset($_REQUEST['method']) && isset($_REQUEST['url'])) {
include ("config.base.php"); include(APP_BASE_PATH . 'api-url-based.php');
include ("include.common.php"); } else {
include("server.includes.inc.php"); include(APP_BASE_PATH . 'api-rest.php');
if(\Classes\SettingsManager::getInstance()->getSetting('Api: REST Api Enabled') == '1') {
if (defined('SYM_CLIENT')) {
define('REST_API_PATH', '/'.SYM_CLIENT.'/');
} else if (!defined('REST_API_PATH')){
define('REST_API_PATH', '/');
}
\Utils\LogManager::getInstance()->info("Request: " . $_REQUEST);
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit();
}
$echoRoute = \Classes\Macaw::get(REST_API_PATH . 'echo', function () {
echo "Echo " . rand();
});
\Utils\LogManager::getInstance()->debug('Api registered URI: '.$echoRoute);
$moduleManagers = \Classes\BaseService::getInstance()->getModuleManagers();
foreach ($moduleManagers as $moduleManagerObj) {
$moduleManagerObj->setupRestEndPoints();
}
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
\Utils\LogManager::getInstance()->debug('Api dispatch URI: '.$uri);
\Utils\LogManager::getInstance()->debug('Api dispatch method: '.$uri);
if (!defined('SYM_CLIENT')) {
//For hosted installations, dispatch will be done in app/index
\Classes\Macaw::dispatch();
}
}else{
echo "REST Api is not enabled. Please set 'Api: REST Api Enabled' setting to true";
} }

View File

@@ -292,8 +292,8 @@ class BaseService
$childCompaniesIds = array(); $childCompaniesIds = array();
if (\Classes\SettingsManager::getInstance()->getSetting( if (\Classes\SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled' 'System: Child Company Structure Managers Enabled'
) == '1' ) == '1'
) { ) {
$childCompaniesResp = \Company\Common\Model\CompanyStructure::getAllChildCompanyStructures( $childCompaniesResp = \Company\Common\Model\CompanyStructure::getAllChildCompanyStructures(
$cempObj->department $cempObj->department
@@ -486,8 +486,8 @@ class BaseService
$childCompaniesIds = array(); $childCompaniesIds = array();
if (SettingsManager::getInstance()->getSetting( if (SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled' 'System: Child Company Structure Managers Enabled'
) == '1' ) == '1'
) { ) {
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department); $childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
$childCompanies = $childCompaniesResp->getObject(); $childCompanies = $childCompaniesResp->getObject();
@@ -567,8 +567,8 @@ class BaseService
$childCompaniesIds = array(); $childCompaniesIds = array();
if (SettingsManager::getInstance()->getSetting( if (SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled' 'System: Child Company Structure Managers Enabled'
) == '1' ) == '1'
) { ) {
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department); $childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
$childCompanies = $childCompaniesResp->getObject(); $childCompanies = $childCompaniesResp->getObject();
@@ -1783,8 +1783,8 @@ END;
) { ) {
$departmentHeadFound = true; $departmentHeadFound = true;
} elseif (SettingsManager::getInstance()->getSetting( } elseif (SettingsManager::getInstance()->getSetting(
'System: Child Company Structure Managers Enabled' 'System: Child Company Structure Managers Enabled'
) == '1' ) == '1'
) { ) {
$companyStructure = new CompanyStructure(); $companyStructure = new CompanyStructure();
$companyStructure->Load('id = ?', array($subordinate->department)); $companyStructure->Load('id = ?', array($subordinate->department));

View File

@@ -94,6 +94,8 @@ class FileService
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret); $s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$result = $s3FileSys->putObject($s3Bucket, $uploadname, $localFile, 'authenticated-read'); $result = $s3FileSys->putObject($s3Bucket, $uploadname, $localFile, 'authenticated-read');
$file->size = filesize($localFile);
unlink("/tmp/".$file->filename); unlink("/tmp/".$file->filename);
unlink("/tmp/".$file->filename."_orig"); unlink("/tmp/".$file->filename."_orig");
@@ -101,7 +103,6 @@ class FileService
$file->employee = $profileImage->employee; $file->employee = $profileImage->employee;
$file->file_group = 'profile_image_small'; $file->file_group = 'profile_image_small';
$file->size = filesize(CLIENT_BASE_PATH.'data/'.$file->filename);
$file->size_text = $this->getReadableSize($file->size); $file->size_text = $this->getReadableSize($file->size);
if (!empty($result)) { if (!empty($result)) {
@@ -293,8 +294,7 @@ class FileService
if ($file->employee == $profileId) { if ($file->employee == $profileId) {
$ok = $file->Delete(); $ok = $file->Delete();
if ($ok) { if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename); $this->deleteFileFromDisk($file);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else { } else {
return false; return false;
} }
@@ -306,8 +306,7 @@ class FileService
if ($file->employee == $profileId) { if ($file->employee == $profileId) {
$ok = $file->Delete(); $ok = $file->Delete();
if ($ok) { if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename); $this->deleteFileFromDisk($file);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else { } else {
return false; return false;
} }
@@ -317,6 +316,30 @@ class FileService
return true; return true;
} }
public function deleteFileFromDisk($file)
{
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload"
);
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
$uploadname = CLIENT_NAME."/".$file->filename;
LogManager::getInstance()->info("Delete from S3:".$uploadname);
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3FileSys->deleteObject($s3Bucket, $uploadname);
} else {
LogManager::getInstance()->info("Delete:".CLIENT_BASE_PATH.'data/'.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
}
}
public function deleteFileByField($value, $field) public function deleteFileByField($value, $field)
{ {
LogManager::getInstance()->info("Delete file by field: $field / value: $value"); LogManager::getInstance()->info("Delete file by field: $field / value: $value");

177
core/src/Classes/IceRoute.php Executable file
View File

@@ -0,0 +1,177 @@
<?php
namespace Classes;
/**
* @method static IceRoute get(string $route, Callable $callback)
* @method static IceRoute post(string $route, Callable $callback)
* @method static IceRoute put(string $route, Callable $callback)
* @method static IceRoute delete(string $route, Callable $callback)
* @method static IceRoute options(string $route, Callable $callback)
* @method static IceRoute head(string $route, Callable $callback)
*/
class IceRoute
{
public static $halts = false;
public static $routes = array();
public static $methods = array();
public static $callbacks = array();
public static $patterns = array(
':any' => '[^/]+',
':num' => '[0-9]+',
':all' => '.*'
);
public static $error_callback;
/**
* Defines a route w/ callback and method
*/
public static function __callstatic($method, $params)
{
$uri = $params[0][0];
$callback = $params[0][1];
array_push(self::$routes, $uri);
array_push(self::$methods, strtoupper($method));
array_push(self::$callbacks, $callback);
return $uri;
}
/**
* Defines callback if route is not found
*/
public static function error($callback)
{
self::$error_callback = $callback;
}
public static function haltOnMatch($flag = true)
{
self::$halts = $flag;
}
/**
* Runs the callback for the given request
*/
public static function dispatch($uri, $method)
{
$searches = array_keys(static::$patterns);
$replaces = array_values(static::$patterns);
$found_route = false;
self::$routes = str_replace('//', '/', self::$routes);
// check if route is defined without regex
if (in_array($uri, self::$routes)) {
$route_pos = array_keys(self::$routes, $uri);
foreach ($route_pos as $route) {
//using an ANY option to match both GET and POST requests
if (self::$methods[$route] == $method || self::$methods[$route] == 'ANY') {
$found_route = true;
//if route is not an object
if (!is_object(self::$callbacks[$route])) {
//grab all parts based on a / separator
$parts = explode('/', self::$callbacks[$route]);
//collect the last index of the array
$last = end($parts);
//grab the controller name and method call
$segments = explode('@', $last);
//instanitate controller
$controller = new $segments[0]();
//call method
$controller->$segments[1]();
if (self::$halts) {
return;
}
} else {
//call closure
call_user_func(self::$callbacks[$route]);
if (self::$halts) {
return;
}
}
}
}
} else {
// check if defined with regex
$pos = 0;
foreach (self::$routes as $route) {
if (strpos($route, ':') !== false) {
$route = str_replace($searches, $replaces, $route);
}
if (preg_match('#^' . $route . '$#', $uri, $matched)) {
if (self::$methods[$pos] == $method) {
$found_route = true;
array_shift($matched); //remove $matched[0] as [1] is the first parameter.
if (!is_object(self::$callbacks[$pos])) {
//grab all parts based on a / separator
$parts = explode('/', self::$callbacks[$pos]);
//collect the last index of the array
$last = end($parts);
//grab the controller name and method call
$segments = explode('@', $last);
//instanitate controller
$controller = new $segments[0]();
//fix multi parameters
if (!method_exists($controller, $segments[1])) {
echo "controller and action not found";
} else {
call_user_func_array(array($controller, $segments[1]), $matched);
}
//call method and pass any extra parameters to the method
// $controller->$segments[1](implode(",", $matched));
if (self::$halts) {
return;
}
} else {
call_user_func_array(self::$callbacks[$pos], $matched);
if (self::$halts) {
return;
}
}
}
}
$pos++;
}
}
// run the error callback if the route was not found
if ($found_route == false) {
if (!self::$error_callback) {
self::$error_callback = function () {
header($_SERVER['SERVER_PROTOCOL']." 404 Not Found");
echo '404';
};
}
call_user_func(self::$error_callback);
}
}
}

View File

@@ -42,6 +42,8 @@ class Macaw
array_push(self::$methods, strtoupper($method)); array_push(self::$methods, strtoupper($method));
array_push(self::$callbacks, $callback); array_push(self::$callbacks, $callback);
call_user_func('\Classes\IceRoute::'.$method, $params);
return $uri; return $uri;
} }

View File

@@ -420,6 +420,8 @@ class RestEndPoint
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
$token = $matches[1]; $token = $matches[1];
} }
} else {
$token = $_GET['token'];
} }
if (strlen($token) > 32) { if (strlen($token) > 32) {

View File

@@ -147,6 +147,10 @@ class EmployeesActionManager extends SubActionManager
return new IceResponse(IceResponse::ERROR, "Error occurred while changing password"); return new IceResponse(IceResponse::ERROR, "Error occurred while changing password");
} }
if (!PasswordManager::verifyPassword($req->current, $user->password)) {
return new IceResponse(IceResponse::ERROR, "Current password is incorrect");
}
$passwordStrengthResponse = PasswordManager::isQualifiedPassword($req->pwd); $passwordStrengthResponse = PasswordManager::isQualifiedPassword($req->pwd);
if ($passwordStrengthResponse->getStatus() === IceResponse::ERROR) { if ($passwordStrengthResponse->getStatus() === IceResponse::ERROR) {
return $passwordStrengthResponse; return $passwordStrengthResponse;
@@ -158,6 +162,6 @@ class EmployeesActionManager extends SubActionManager
return new IceResponse(IceResponse::ERROR, $user->ErrorMsg()); return new IceResponse(IceResponse::ERROR, $user->ErrorMsg());
} }
return new IceResponse(IceResponse::SUCCESS, $user); return new IceResponse(IceResponse::SUCCESS, []);
} }
} }

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

18
package-lock.json generated
View File

@@ -3824,7 +3824,7 @@
}, },
"doctrine": { "doctrine": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -5515,9 +5515,9 @@
} }
}, },
"y18n": { "y18n": {
"version": "3.2.1", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==",
"dev": true "dev": true
}, },
"yargs": { "yargs": {
@@ -6988,7 +6988,7 @@
}, },
"is-accessor-descriptor": { "is-accessor-descriptor": {
"version": "0.1.6", "version": "0.1.6",
"resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
"integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -7034,7 +7034,7 @@
}, },
"is-data-descriptor": { "is-data-descriptor": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
"integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -11340,9 +11340,9 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
}, },
"y18n": { "y18n": {
"version": "4.0.0", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ=="
}, },
"yargs": { "yargs": {
"version": "13.3.2", "version": "13.3.2",

View File

@@ -1,5 +1,3 @@
<img src="web/images/logo-sq.png" align="right" />
IceHrm IceHrm
=========== ===========
[![Build Status](https://travis-ci.org/gamonoid/icehrm.svg?branch=master)](https://travis-ci.org/gamonoid/icehrm) [![Build Status](https://travis-ci.org/gamonoid/icehrm.svg?branch=master)](https://travis-ci.org/gamonoid/icehrm)

View File

@@ -1,3 +1,19 @@
# Release Notes IceHrm Open Source
## Release note v28.2.0.OS
### New features
* 🦠 💉 Custom extensions [https://icehrm.gitbook.io/icehrm/developer-guide/creating-first-extension](https://icehrm.gitbook.io/icehrm/developer-guide/creating-first-extension)
## Release note v28.1.1.OS
### 🐛 Bug fixes
* Fixing inability to filter employee documents
* Fixed the issue with selecting projects when adding timesheets details
* Fix issues occurred due to incorrectly configured API
## Release note v28.1.0.OS ## Release note v28.1.0.OS
### 🧲 New features ### 🧲 New features
@@ -16,441 +32,477 @@
* New REST endpoints for employee qualifications * New REST endpoints for employee qualifications
### 🐛 Bug fixes ### 🐛 Bug fixes
* Fixed, issue with managers being able to create performance reviews for employees who are not their direct reports * Fixed, issue with managers being able to create performance reviews for employees who are not their direct reports
* Fixed, issues related to using full profile image instead of using smaller version of profile image * Fixed, issues related to using full profile image instead of using smaller version of profile image
* Changing third gender to other * Changing third gender to other
* Improvements and fixes for internal frontend data caching * Improvements and fixes for internal frontend data caching
## Release note v27.0.2.OS
This fixes some major issues found in v27.0.1.OS
### 🐛 Bug fixes
* Filtering across whole application was broken and now it's fixed
* Fixed the issue related to photo not being shown to the admin when photo attendance is enabled
### 🧑🏻‍💻 For developers
* We have added support for vagrant development environment based on Debian 10 / PHP 7.3 \(with Xdebug\) / Nginx / MySQL
## Release note v27.0.0.OS ## Release note v27.0.0.OS
### New features ### New features
* Employee document management is now available for open-source version * Employee document management is now available for open-source version
* UI/UX improvements (new fonts / better spacing) * UI/UX improvements \(new fonts / better spacing\)
* Payroll module improvements * Payroll module improvements
* Security improvements to password policy * Security improvements to password policy
* Albanian language is now available * Albanian language is now available
* Ability to deploy using docker * Ability to deploy using docker
### For developers ### For developers
* Developer environment based on docker [https://www.youtube.com/watch?v=sz8OV_ON6S8](https://www.youtube.com/watch?v=sz8OV_ON6S8)
* Developer environment based on docker [https://www.youtube.com/watch?v=sz8OV\_ON6S8](https://www.youtube.com/watch?v=sz8OV_ON6S8)
* [Developer guide](https://icehrm.gitbook.io/icehrm/developer-guide/create-new-module) * [Developer guide](https://icehrm.gitbook.io/icehrm/developer-guide/create-new-module)
* Fully supports all php versions >= 5.6 upto v7.3 (php 5.6 support is deprecated and not recommended) * Fully supports all php versions &gt;= 5.6 upto v7.3 \(php 5.6 support is deprecated and not recommended\)
### Bug fixes ### Bug fixes
* Fixes to newly found vulnerabilities (https://github.com/gamonoid/icehrm/issues/213): credits to: [Talos](https://talosintelligence.com/)
* Fixes to newly found vulnerabilities \([https://github.com/gamonoid/icehrm/issues/213](https://github.com/gamonoid/icehrm/issues/213)\): credits to: [Talos](https://talosintelligence.com/)
* Fixed the travel request approval for managers * Fixed the travel request approval for managers
* Fixed the issue with attendance source IP display * Fixed the issue with attendance source IP display
* Fixing Api issues in PHP 7.3 * Fixing Api issues in PHP 7.3
## Release note v26.6.0.OS
Release note v26.6.0.OS
------------------------
### Features ### Features
* Some Improvements to UI such as updating Icons and upgrading font-awesome to its latest version
* Tracking IP and location of the employee when marking attendance, this is done when updating attendance via mobile * Some Improvements to UI such as updating Icons and upgrading font-awesome to its latest version
* Ability to control location tracking via mobile using server side settings * Tracking IP and location of the employee when marking attendance, this is done when updating attendance via mobile
* Improvements to translations * Ability to control location tracking via mobile using server side settings
* Compatible with location tracking with icehrm mobile app * Improvements to translations
### Mobile App ### Mobile App
* This release is coupled with mobile application release on AppStore (https://apple.co/2Yrtxoy) and Google Play (http://bit.ly/2OkMmKe)
* This release is coupled with mobile application release on AppStore \([https://apple.co/2Yrtxoy](https://apple.co/2Yrtxoy)\) and Google Play \([http://bit.ly/2OkMmKe](http://bit.ly/2OkMmKe)\)
### Fixes ### Fixes
* Order projects by name on Timesheet project listing (This is to make it easier to edit timesheets with many projects)
* Link home page user profile to employee profile update page * Order projects by name on Timesheet project listing \(This is to make it easier to edit timesheets with many projects\)
* Fix issues related to configuring Api with mobile app * Link home page user profile to employee profile update page
* Fix issues related to configuring Api with mobile app
### Security Improvements ### Security Improvements
* Upgrade npm missing dependencies
* Upgrade npm missing dependencies
Release note v26.2.0.OS
------------------------ ## Release note v26.2.0.OS
### Features ### Features
* Add staff directory module
* Update client-side js to ES6
* Compatible with IceHrm Mobile App
* Use npm libraries when possible
* Add gulp build for frontend assets
* Allow generating QR code with rest api key (https://github.com/gamonoid/icehrm/issues/169)
* Updated readme for development setup with vagrant
* Add staff directory module
* Update client-side js to ES6
* Compatible with IceHrm Mobile App
* Use npm libraries when possible
* Add gulp build for frontend assets
* Allow generating QR code with rest api key \([https://github.com/gamonoid/icehrm/issues/169](https://github.com/gamonoid/icehrm/issues/169)\)
* Updated readme for development setup with vagrant
### Fixes ### Fixes
* Add missing employee details report
* Fix: Labels of 'Employee Custom Fields' not displayed (https://github.com/gamonoid/icehrm/issues/146)
* Fix: Work week for all counties can not be edited
* Fix: Custom fields are not shown under employee profile (https://github.com/gamonoid/icehrm/issues/159)
* Fix: Additional buttons shown below timesheet list (https://github.com/gamonoid/icehrm/issues/171)
* Updates to Italian translations (https://github.com/gamonoid/icehrm/pull/166) by https://github.com/nightwatch75
* Add missing employee details report
Release note v24.0.0.OS * Fix: Labels of 'Employee Custom Fields' not displayed \([https://github.com/gamonoid/icehrm/issues/146](https://github.com/gamonoid/icehrm/issues/146)\)
------------------------ * Fix: Work week for all counties can not be edited
* Fix: Custom fields are not shown under employee profile \([https://github.com/gamonoid/icehrm/issues/159](https://github.com/gamonoid/icehrm/issues/159)\)
* Fix: Additional buttons shown below timesheet list \([https://github.com/gamonoid/icehrm/issues/171](https://github.com/gamonoid/icehrm/issues/171)\)
* Updates to Italian translations \([https://github.com/gamonoid/icehrm/pull/166](https://github.com/gamonoid/icehrm/pull/166)\) by [https://github.com/nightwatch75](https://github.com/nightwatch75)
## Release note v24.0.0.OS
### Features ### Features
* Allow passing additional parameters to payroll predefined methods
* Pass leave type name in function field to get leave count for a given type * Allow passing additional parameters to payroll predefined methods
* Add employee name to payroll report * Pass leave type name in function field to get leave count for a given type
* Show supervisor name on employee profile * Add employee name to payroll report
* Add custom fields to employee report * Show supervisor name on employee profile
* Add filter by status feature to subordinate time sheets * Add custom fields to employee report
* Add filter by status feature to subordinate time sheets
### Security Fixes ### Security Fixes
* Fix missing login form CSRF token
* Fix risky usage of hashed password in request * Fix missing login form CSRF token
* Fixing permission issues on module access for each user level * Fix risky usage of hashed password in request
* Prevent manager from accessing sensitive user records * Fixing permission issues on module access for each user level
* Prevent manager from accessing sensitive user records
### Other Fixes ### Other Fixes
* Hide employee salary from managers
* Prevent manager from accessing audit, cron and notifications * Hide employee salary from managers
* Prevent managers from deleting employees * Prevent manager from accessing audit, cron and notifications
* Validate overtime start and end times * Prevent managers from deleting employees
* Fix issue: employee can download draft payroll * Validate overtime start and end times
* Fix issue: employee can download draft payroll
Release note v23.0.1.OS
------------------------ ## Release note v23.0.1.OS
This release include some very critical security fixes. We recommend upgrading your installation to latest release. This release include some very critical security fixes. We recommend upgrading your installation to latest release.
### Fixes ### Fixes
* Fix missing login form CSRF token
* Fix risky usage of hashed password in request
Release note v23.0.0.OS
------------------------
### Features
* Loading last used module when revisiting application
* Finnish language support (Beta)
* Improvements to German, Italian and Chinese language translations
* Allow quickly switching languages
* Improvements to security for preventing possible LFI attacks
* Allow manual date inputs
* Custom fields for travel requests
* Allow importing approved overtime hours into payroll
* Add date and time masks
### Fixes
* Fix logout cookie issue, by clearing remember me cookie when logging out
* Improve privacy for GDPR
* Improvements to file upload field
* Fix issue: attendance rest end point not working on php 5.6
Release note v22.0.0.OS * Fix missing login form CSRF token
------------------------ * Fix risky usage of hashed password in request
### Features
* Improvements to module naming
### Fixes
* Fix issue: filter dialog default values are not selected
* Fix issue: department head can be an employee outside the department
* Fix issue: department head or supervisor (who has manager leave access) can't use switch employee feature
* Fix issue: employee name is not visible on report if middle name is empty
Release note v21.1.0.OS ## Release note v23.0.0.OS
------------------------
### Features
* UI improvements (help button and error messages)
* Allow adding placeholders to text fields
* Improvements to German Translations
### Fixes
* Fixing notification issues
Release note v21.0.0.OS
------------------------
### Features
* Fully compatible with php 7.1
* Add Net_SMTP via composer (no pear installation needed)
### Fixes
* Fixes for web servers not supporting JSON in GET request
Release note v21.0.0.OS
------------------------
### Features
* Fully compatible with php 7.1
* Add Net_SMTP via composer (no pear installation needed)
### Fixes
* Fixes for web servers not supporting JSON in GET request
Release note v20.3.0.PRO
------------------------
### Features
* Employee and Attendance REST Api Released
* Import/Export for Payroll Configurations
* Ability to import employee approved time sheet hours to payroll
* Swift Mailer based SMTP support (no need to install Net_SMTP anymore)
* Add direct Edit button on employee list
### Fixes
* Fix DB connection issues due to special characters in password
* Fixes for custom field saving issues in mysql v5.7.x
Release note v20.2
------------------
### Fixes
* Fix for resetting modules
Release note v20.1
------------------
### Features
* Compatible with MySQL 5.7 Strict Mode
* PSR-2 compatible code
* Employee History Module
* Staff Directory
### Fixes
* Fix: password reset not working
* Fix: limiting selectable countries via Settings
* Fix for resetting modules
Release note v20.0
------------------
### Features
* Payroll Module
* Compatible with MySQL 5.7 Strict Mode
* Namespaced Classes
* LDAP Module
### Fixes
* Fix: limiting selectable countries via Settings
Release note v19.0
------------------
### Features
* Development environment
* Overtime module
* Department heads who can manage all employees attached to a company structure
Release note v18.0
------------------
### Features
* Translations (beta) for German, French, Polish, Italian, Sinhala, Chinese, Japanese, Hindi and Spanish
* PDF Reports
* Ability to specify department heads
* Add advanced custom fields to employees via UI
* Allow indirect admins to approve travel requests
* Adding more languages to Language meta data table
* Improvements to report module
* Ability to select sections for placing custom fields on employee detail view screen
* Introducing clone button
* Unlimited custom fields for employees
* PDF report for monitoring time employee spent on projects
* Report files module - Allow downloading all previously generated reports
### Fixes
* Fix: subordinates are not showing beyond first page issue.
Release note v16.1
------------------
### Fixes
* Fix LDAP user login issue
* Allow creating users with username having dot and dash
Release note v16.0
------------------
### Features
* Advanced Employee Management Module is now included in IceHrm Open Source Edition
* LDAP Module which was only available in IceHrm Enterprise is now included in open source also
* Initial implementation of icehrm REST Api for reading employee details
* Improvements to data filtering
* Multiple tabs for settings module
* Overtime reports - now its possible to calculate overtime for employees.compatible with US overtime rules
* Logout the user if tried accessing an unauthorized module
* Setting for updating module names
### Fixes
* Fix issue: classes should be loaded even the module is disabled
* Deleting the only Admin user is not allowed
* Fixes for handling non UTF-8
* Fix for non-mandatory select boxes are shown as mandatory
Release note v15.2
------------------
### Features ### Features
* Overtime Reports
* Overtime calculation for california
### Fixes
* Fix issue: uncaught error when placeholder value is empty
* Log email sending success status
* Fix broken longer company name issue
* Make the application accessible when client on an intranet with no internet connection
* Fix issue: when a module is disabled other modules depend on it stops working
* Loading last used module when revisiting application
Release note v15.0 * Finnish language support \(Beta\)
------------------ * Improvements to German, Italian and Chinese language translations
* Allow quickly switching languages
### Features * Improvements to security for preventing possible LFI attacks
* Clear HTML5 local storage when logging in and switching users * Allow manual date inputs
* Showing a loading message while getting data from server * Custom fields for travel requests
* Adding a new field to show total time of each time sheet * Allow importing approved overtime hours into payroll
* New report added for listing Employee Time Sheets * Add date and time masks
* Company logo uploaded via settings will be used for all email headers
### Fixes
* Fix issue: default module URL is incorrect for Employees
* Fix date parsing issue in time sheets
* AWS phar is included only when required
Release note v14.1
------------------
### Features
* Add Quick access menu
### Fixes ### Fixes
* Fix issue: salary module not loading
* Add travel report
Release note v14.0 * Fix logout cookie issue, by clearing remember me cookie when logging out
------------------ * Improve privacy for GDPR
* Improvements to file upload field
* Fix issue: attendance rest end point not working on php 5.6
## Release note v22.0.0.OS
### Features ### Features
* IceHrm is now fully compatible with PHP 7
* Improvements to travel management module to change the process of applying for travel requests
* New report add for getting travel requests
* Improvements to user interface
* Bunch of UI improvements including changing menu order and font sizes
* Add a setting to use server time for time zone defined on department that a user is attached to create new attendance records
* Improvements to admin/manager and user dashboard
* Managers allowed to view/add/edit employee documents
* New reports added for employee expenses and travel
### Fixes
* Fix unavailable help links
* Improvements to module naming
Release note v13.4
-----------------
### Features
### Fixes
* Fix employee leave report leave type field
Release note v13.0
-----------------
### Features
* Recruitment module
* Allow managers to edit attendance of direct report employees
### Fixes
* Employee switching issue fixed
* Fix terminated employee labels
* Fix issue with punch-in
Release note v12.6
-----------------
### Features
* Charts module
* Code level security improvements
### Fixes
* Employee switching issue fixed
Release note v11.1
-----------------
### Features
* Add/Edit or remove employee fields
Release note v11.0
-----------------
### Features
* Employee data archiving
* Leave cancellation requests
* Adding view employee feature
### Fixes ### Fixes
* Improvements to date time pickers
* Fix issue: filter dialog default values are not selected
* Fix issue: department head can be an employee outside the department
* Fix issue: department head or supervisor \(who has manager leave access\) can't use switch employee feature
* Fix issue: employee name is not visible on report if middle name is empty
Release note v10.1 ## Release note v21.1.0.OS
-----------------
### Features ### Features
* Integration with ice-framework (http://githun.com/thilinah/ice-framework)
* Option for only allow users to add an entry to a timesheet only if they have marked atteandance for the selected period
* Restricting availability of leave types to employees using leave groups
* Admins and add notes to employees
Release note v9.1 * UI improvements \(help button and error messages\)
----------------- * Allow adding placeholders to text fields
* Improvements to German Translations
### Fixes ### Fixes
* Add missing S3FileSystem class
* Fix issue: passing result of a method call directly into empty method is not supported in php v5.3
* Fixing notification issues
Release note v9.0 ## Release note v21.0.0.OS
-----------------
### Features ### Features
* New user interface
* Decimal leave counts supported
Update icehrm v8.4 to v9.0
--------------------------
* Make a backup of your icehrm db * Fully compatible with php 7.1
* Run db script "icehrmdb_update_v8.4_to_v9.0.sql" which can be found inside script folder of icehrm_v9.0 * Add Net\_SMTP via composer \(no pear installation needed\)
* remove all folders except app folder in icehrm root folder
* copy all folders except app folder from new installation to icehrm root folder
Release note v8.4
-----------------
### Fixes ### Fixes
* Fix leave carry forward rounding issues
* Fix issue: select2 default value not getting set for select2
* Fix issue: email not sent when admin changing leave status
Release note v8.3 * Fixes for web servers not supporting JSON in GET request
-----------------
### Fixes ## Release note v21.0.0.OS
* Fix user table issue on windows, this will resolve errors such as: (Note that this fix has no effect on unix based installations)
* Admin not able to view user uploaded documents
* Admin not able to upload documants for users
* Admin can not view employee attendance records
* Employee projects can not be added
Release note v8.2
-----------------
### Features ### Features
* Fully compatible with php 7.1
* Add Net\_SMTP via composer \(no pear installation needed\)
### Fixes
* Fixes for web servers not supporting JSON in GET request
## Release note v20.3.0.PRO
### Features
* Employee and Attendance REST Api Released
* Import/Export for Payroll Configurations
* Ability to import employee approved time sheet hours to payroll
* Swift Mailer based SMTP support \(no need to install Net\_SMTP anymore\)
* Add direct Edit button on employee list
### Fixes
* Fix DB connection issues due to special characters in password
* Fixes for custom field saving issues in mysql v5.7.x
## Release note v20.2
### Fixes
* Fix for resetting modules
## Release note v20.1
### Features
* Compatible with MySQL 5.7 Strict Mode
* PSR-2 compatible code
* Employee History Module
* Staff Directory
### Fixes
* Fix: password reset not working
* Fix: limiting selectable countries via Settings
* Fix for resetting modules
## Release note v20.0
### Features
* Payroll Module
* Compatible with MySQL 5.7 Strict Mode
* Namespaced Classes
* LDAP Module
### Fixes
* Fix: limiting selectable countries via Settings
## Release note v19.0
### Features
* Development environment
* Overtime module
* Department heads who can manage all employees attached to a company structure
## Release note v18.0
### Features
* Translations \(beta\) for German, French, Polish, Italian, Sinhala, Chinese, Japanese, Hindi and Spanish
* PDF Reports
* Ability to specify department heads
* Add advanced custom fields to employees via UI
* Allow indirect admins to approve travel requests
* Adding more languages to Language meta data table
* Improvements to report module
* Ability to select sections for placing custom fields on employee detail view screen
* Introducing clone button
* Unlimited custom fields for employees
* PDF report for monitoring time employee spent on projects
* Report files module - Allow downloading all previously generated reports
### Fixes
* Fix: subordinates are not showing beyond first page issue.
## Release note v16.1
### Fixes
* Fix LDAP user login issue
* Allow creating users with username having dot and dash
## Release note v16.0
### Features
* Advanced Employee Management Module is now included in IceHrm Open Source Edition
* LDAP Module which was only available in IceHrm Enterprise is now included in open source also
* Initial implementation of icehrm REST Api for reading employee details
* Improvements to data filtering
* Multiple tabs for settings module
* Overtime reports - now its possible to calculate overtime for employees.compatible with US overtime rules
* Logout the user if tried accessing an unauthorized module
* Setting for updating module names
### Fixes
* Fix issue: classes should be loaded even the module is disabled
* Deleting the only Admin user is not allowed
* Fixes for handling non UTF-8
* Fix for non-mandatory select boxes are shown as mandatory
## Release note v15.2
### Features
* Overtime Reports
* Overtime calculation for california
### Fixes
* Fix issue: uncaught error when placeholder value is empty
* Log email sending success status
* Fix broken longer company name issue
* Make the application accessible when client on an intranet with no internet connection
* Fix issue: when a module is disabled other modules depend on it stops working
## Release note v15.0
### Features
* Clear HTML5 local storage when logging in and switching users
* Showing a loading message while getting data from server
* Adding a new field to show total time of each time sheet
* New report added for listing Employee Time Sheets
* Company logo uploaded via settings will be used for all email headers
### Fixes
* Fix issue: default module URL is incorrect for Employees
* Fix date parsing issue in time sheets
* AWS phar is included only when required
## Release note v14.1
### Features
* Add Quick access menu
### Fixes
* Fix issue: salary module not loading
* Add travel report
## Release note v14.0
### Features
* IceHrm is now fully compatible with PHP 7
* Improvements to travel management module to change the process of applying for travel requests
* New report add for getting travel requests
* Improvements to user interface
* Bunch of UI improvements including changing menu order and font sizes
* Add a setting to use server time for time zone defined on department that a user is attached to create new attendance records
* Improvements to admin/manager and user dashboard
* Managers allowed to view/add/edit employee documents
* New reports added for employee expenses and travel
### Fixes
* Fix unavailable help links
## Release note v13.4
### Features
### Fixes
* Fix employee leave report leave type field
## Release note v13.0
### Features
* Recruitment module
* Allow managers to edit attendance of direct report employees
### Fixes
* Employee switching issue fixed
* Fix terminated employee labels
* Fix issue with punch-in
## Release note v12.6
### Features
* Charts module
* Code level security improvements
### Fixes
* Employee switching issue fixed
## Release note v11.1
### Features
* Add/Edit or remove employee fields
## Release note v11.0
### Features
* Employee data archiving
* Leave cancellation requests
* Adding view employee feature
### Fixes
* Improvements to date time pickers
## Release note v10.1
### Features
* Integration with ice-framework \([http://githun.com/thilinah/ice-framework](http://githun.com/thilinah/ice-framework)\)
* Option for only allow users to add an entry to a timesheet only if they have marked atteandance for the selected period
* Restricting availability of leave types to employees using leave groups
* Admins and add notes to employees
## Release note v9.1
### Fixes
* Add missing S3FileSystem class
* Fix issue: passing result of a method call directly into empty method is not supported in php v5.3
## Release note v9.0
### Features
* New user interface
* Decimal leave counts supported
## Update icehrm v8.4 to v9.0
* Make a backup of your icehrm db
* Run db script "icehrmdb\_update\_v8.4\_to\_v9.0.sql" which can be found inside script folder of icehrm\_v9.0
* remove all folders except app folder in icehrm root folder
* copy all folders except app folder from new installation to icehrm root folder
## Release note v8.4
### Fixes
* Fix leave carry forward rounding issues
* Fix issue: select2 default value not getting set for select2
* Fix issue: email not sent when admin changing leave status
## Release note v8.3
### Fixes
* Fix user table issue on windows, this will resolve errors such as: \(Note that this fix has no effect on unix based installations\)
* Admin not able to view user uploaded documents
* Admin not able to upload documants for users
* Admin can not view employee attendance records
* Employee projects can not be added
## Release note v8.2
### Features
* Instance verification added * Instance verification added
Release note v8.1 ## Release note v8.1
-----------------
### Fixes ### Fixes
* Fixed bug that caused a fatal error in php v5.4 * Fixed bug that caused a fatal error in php v5.4
* aws2.7.11 phar file replaced by a aws2.7.11 extracted files * aws2.7.11 phar file replaced by a aws2.7.11 extracted files
* old aws sdk removed * old aws sdk removed
Release note v8.0 ## Release note v8.0
-----------------
### Features ### Features
* Admin dashbord module * Admin dashbord module
* If the employee joined in current leave period, his leave entitlement is calculated proportional to joined date * If the employee joined in current leave period, his leave entitlement is calculated proportional to joined date
* Improvements to reporting module * Improvements to reporting module
@@ -462,22 +514,22 @@ Release note v8.0
* Upgrade aws sdk to v2.7.11 * Upgrade aws sdk to v2.7.11
* Allow employees to change password * Allow employees to change password
* Use only the email address defined under user for sending mails * Use only the email address defined under user for sending mails
* Making work_email and private_email fields optional * Making work\_email and private\_email fields optional
### Fixes ### Fixes
* Upload dialog close button issue fixed * Upload dialog close button issue fixed
Release note v7.2 ## Release note v7.2
-----------------
### Fixes ### Fixes
* Some critical vulnerabilities are fixed as recommend by http://zeroscience.mk/en/
Release note v7.1 * Some critical vulnerabilities are fixed as recommend by [http://zeroscience.mk/en/](http://zeroscience.mk/en/)
-----------------
## Release note v7.1
### Features ### Features
* Improved company structure graph * Improved company structure graph
* Leave notes implementation <20> Supervisor can add a note when approving or rejecting leaves * Leave notes implementation <20> Supervisor can add a note when approving or rejecting leaves
* Filtering support * Filtering support
@@ -486,20 +538,20 @@ Release note v7.1
* Add ability to disable employee information editing * Add ability to disable employee information editing
### Fixes ### Fixes
* Make loans editable only by admin * Make loans editable only by admin
* Fix: permissions not getting applied to employee documents * Fix: permissions not getting applied to employee documents
* Fix error adding employee documents when no user assigned to the admin * Fix error adding employee documents when no user assigned to the admin
### Code Quality ### Code Quality
* Moving all module related code and data into module folders * Moving all module related code and data into module folders
Release note v6.1 ## Release note v6.1
-----------------
Leave carry forwared related isue fixed Leave carry forwared related isue fixed
Release note v6.0 ## Release note v6.0
-----------------
* Features * Features
* Notifications for leaves and timesheets * Notifications for leaves and timesheets
@@ -513,21 +565,18 @@ Release note v6.0
* Admin can make all projects available to employees or just the set of prjects assigned to them using Setting "Projects: Make All Projects Available to Employees" * Admin can make all projects available to employees or just the set of prjects assigned to them using Setting "Projects: Make All Projects Available to Employees"
* Employee document, date added field can not be changed by the employee anymore * Employee document, date added field can not be changed by the employee anymore
* About dialog added for admins * About dialog added for admins
* Fixes * Fixes
* Fix default employee delete issue (when the default employee is deleted the admin user attached to it also get deleted) * Fix default employee delete issue \(when the default employee is deleted the admin user attached to it also get deleted\)
* Fix user duplicate email issue * Fix user duplicate email issue
* Fix manager can not logout from switched employee * Fix manager can not logout from switched employee
* Remove admin guide from non admin users * Remove admin guide from non admin users
Release note v5.3 ## Release note v5.3
-----------------
* Fixes * Fixes
* Fix missing employee name in employee details report * Fix missing employee name in employee details report
Release note v5.2 ## Release note v5.2
-----------------
* Fixes * Fixes
* Remove unwanted error logs * Remove unwanted error logs
@@ -536,38 +585,33 @@ Release note v5.2
* Remove add new button from subordinates module * Remove add new button from subordinates module
* Adding administrators' guide * Adding administrators' guide
Release note v5.1 ## Release note v5.1
-----------------
* Fixes * Fixes
* Fixing for non updating null fields * Fixing for non updating null fields
* https://bitbucket.org/thilina/icehrm-opensource/commits/df57308b53484a2e43ef5c72967ed1cd0dc756cc * [https://bitbucket.org/thilina/icehrm-opensource/commits/df57308b53484a2e43ef5c72967ed1cd0dc756cc](https://bitbucket.org/thilina/icehrm-opensource/commits/df57308b53484a2e43ef5c72967ed1cd0dc756cc)
Release note v5.0 ## Release note v5.0
-----------------
* Features * Features
* New user permission implementation * New user permission implementation
* Adding new user level - Manager * Adding new user level - Manager
* Fixes * Fixes
* Fixing remote table loading issue * Fixing remote table loading issue
Release note v4.2 ## Release note v4.2
-----------------
### Fixes ### Fixes
* https://bitbucket.org/thilina/icehrm-opensource/issue/23/subordinate-leaves-pagination-not-working
* https://bitbucket.org/thilina/icehrm-opensource/issue/20/error-occured-while-time-punch
* [https://bitbucket.org/thilina/icehrm-opensource/issue/23/subordinate-leaves-pagination-not-working](https://bitbucket.org/thilina/icehrm-opensource/issue/23/subordinate-leaves-pagination-not-working)
* [https://bitbucket.org/thilina/icehrm-opensource/issue/20/error-occured-while-time-punch](https://bitbucket.org/thilina/icehrm-opensource/issue/20/error-occured-while-time-punch)
Release note v4.1 ## Release note v4.1
-----------------
### Features ### Features
* Better email format for notifications * Better email format for notifications
* Convert upload dialog to a bootstrp model * Convert upload dialog to a bootstrp model
* Fixes * Fixes
* Fix error sending emails with amazon SES * Fix error sending emails with amazon SES
* Fix errors related to XAMPP and WAMPP servers * Fix errors related to XAMPP and WAMPP servers
@@ -576,3 +620,4 @@ Release note v4.1
* Allow icehrm client to work without an internet connection * Allow icehrm client to work without an internet connection
* Fix installer incorrect base url issue * Fix installer incorrect base url issue
* Fix empty user creation issue * Fix empty user creation issue

View File

@@ -154,7 +154,7 @@ class EmployeeDocumentAdapter extends AdapterBase {
getFilters() { getFilters() {
return [ return [
['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name'] }], ['employee', { label: 'Employee', type: 'select2', 'remote-source': ['Employee', 'id', 'first_name+last_name', 'getActiveSubordinateEmployees'] }],
]; ];
} }

View File

@@ -426,7 +426,7 @@ class EmployeeAdapter extends ReactModalAdapterBase {
&& ( && (
<Tag color="volcano" onClick={() => modJs.terminateEmployee(record.id)} style={{ cursor: 'pointer' }}> <Tag color="volcano" onClick={() => modJs.terminateEmployee(record.id)} style={{ cursor: 'pointer' }}>
<DeleteOutlined /> <DeleteOutlined />
{` ${adapter.gt('Delete')}`} {` ${adapter.gt('Deactivate')}`}
</Tag> </Tag>
)} )}
{adapter.hasAccess('save') {adapter.hasAccess('save')

View File

@@ -55,7 +55,7 @@ class AdapterBase extends ModuleBase {
} }
setupApiClient(token) { setupApiClient(token) {
this.apiClient = new IceApiClient(this.apiUrl, token); this.apiClient = new IceApiClient(this.apiUrl, token, window.CLIENT_BASE_URL, true);
} }
setApiUrl(apiUrl) { setApiUrl(apiUrl) {

26
web/api/CustomAction.js Normal file
View File

@@ -0,0 +1,26 @@
const axios = require('axios');
class CustomAction {
constructor(adapter) {
this.adapter = adapter;
}
execute(subAction, module, request, isPost) {
if (!isPost) {
return axios.get(
this.adapter.moduleRelativeURL,
{
params: {
t: this.adapter.table, a: 'ca', sa: subAction, mod: module, req: request,
},
},
);
}
return axios.post(this.moduleRelativeURL, {
t: this.adapter.table, a: 'ca', sa: subAction, mod: module, req: request,
});
}
}
export default CustomAction;

View File

@@ -1,12 +1,19 @@
const axios = require('axios'); const axios = require('axios');
class IceApiClient { class IceApiClient {
constructor(baseUrl, token) { constructor(baseUrl, token, clientBaseUrl, legacyApiWrapper = true) {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.token = token; this.token = token;
this.clientBaseUrl = clientBaseUrl;
this.legacyApiWrapper = legacyApiWrapper;
} }
get(endpoint) { get(endpoint) {
if (this.legacyApiWrapper) {
const url = `${this.clientBaseUrl}api/index.php?token=${this.token}&method=get&url=/${endpoint}`;
return axios.get(url);
}
return axios.get(this.baseUrl + endpoint, { return axios.get(this.baseUrl + endpoint, {
headers: { headers: {
Authorization: `Bearer ${this.token}`, Authorization: `Bearer ${this.token}`,

View File

@@ -61,10 +61,10 @@ class ModuleBase {
} }
/** /**
* Some browsers do not support sending JSON in get parameters. Set this to true to avoid sending JSON * Some browsers do not support sending JSON in get parameters. Set this to true to avoid sending JSON
* @method setNoJSONRequests * @method setNoJSONRequests
* @param val {Boolean} * @param val {Boolean}
*/ */
setNoJSONRequests(val) { setNoJSONRequests(val) {
this.noJSONRequests = val; this.noJSONRequests = val;
} }
@@ -79,12 +79,12 @@ class ModuleBase {
} }
/** /**
* Check if the current user has a permission * Check if the current user has a permission
* @method checkPermission * @method checkPermission
* @param permission {String} * @param permission {String}
* @example * @example
* this.checkPermission("Upload/Delete Profile Image") * this.checkPermission("Upload/Delete Profile Image")
*/ */
checkPermission(permission) { checkPermission(permission) {
if (this.permissions[permission] === undefined || this.permissions[permission] == null || this.permissions[permission] === 'Yes') { if (this.permissions[permission] === undefined || this.permissions[permission] == null || this.permissions[permission] === 'Yes') {
return 'Yes'; return 'Yes';
@@ -168,15 +168,15 @@ class ModuleBase {
} }
/** /**
* If this method returned false the action buttons in data table for modules will not be displayed. * If this method returned false the action buttons in data table for modules will not be displayed.
* Override this method in module lib.js to hide action buttons * Override this method in module lib.js to hide action buttons
* @method showActionButtons * @method showActionButtons
* @param permission {String} * @param permission {String}
* @example * @example
* EmployeeLeaveEntitlementAdapter.method('showActionButtons() { * EmployeeLeaveEntitlementAdapter.method('showActionButtons() {
* return false; * return false;
* } * }
*/ */
showActionButtons() { showActionButtons() {
return true; return true;
} }
@@ -201,30 +201,30 @@ class ModuleBase {
} }
/** /**
* Get the current profile * Get the current profile
* @method getCurrentProfile * @method getCurrentProfile
* @returns Profile of the current user if the profile is not switched if not switched profile * @returns Profile of the current user if the profile is not switched if not switched profile
*/ */
getCurrentProfile() { getCurrentProfile() {
return this.currentProfile; return this.currentProfile;
} }
/** /**
* Retrive data required to create select boxes for add new /edit forms for a given module. This is called when loading the module * Retrive data required to create select boxes for add new /edit forms for a given module. This is called when loading the module
* @method initFieldMasterData * @method initFieldMasterData
* @param callback {Function} call this once loading completed * @param callback {Function} call this once loading completed
* @param callback {Function} call this once all field loading completed. This indicate that the form can be displayed saftly * @param callback {Function} call this once all field loading completed. This indicate that the form can be displayed saftly
* @example * @example
* ReportAdapter.method('renderForm(object) { * ReportAdapter.method('renderForm(object) {
* var that = this; * var that = this;
* this.processFormFieldsWithObject(object); * this.processFormFieldsWithObject(object);
* var cb = function(){ * var cb = function(){
* that.super.renderForm(object); * that.super.renderForm(object);
* }; * };
* this.initFieldMasterData(cb); * this.initFieldMasterData(cb);
* } * }
*/ */
initFieldMasterData(callback, loadAllCallback, loadAllCallbackData) { initFieldMasterData(callback, loadAllCallback, loadAllCallbackData) {
this.fieldMasterData = {}; this.fieldMasterData = {};
this.fieldMasterDataKeys = {}; this.fieldMasterDataKeys = {};
@@ -236,10 +236,11 @@ class ModuleBase {
for (let i = 0; i < remoteSourceFields.length; i++) { for (let i = 0; i < remoteSourceFields.length; i++) {
const fieldRemote = remoteSourceFields[i]; const fieldRemote = remoteSourceFields[i];
if (fieldRemote[1]['remote-source'] !== undefined && fieldRemote[1]['remote-source'] != null) { if (fieldRemote[1]['remote-source'] !== undefined && fieldRemote[1]['remote-source'] != null) {
let key = `${fieldRemote[1]['remote-source'][0]}_${fieldRemote[1]['remote-source'][1]}_${fieldRemote[1]['remote-source'][2]}`; // let key = `${fieldRemote[1]['remote-source'][0]}_${fieldRemote[1]['remote-source'][1]}_${fieldRemote[1]['remote-source'][2]}`;
if (fieldRemote[1]['remote-source'].length === 4) { // if (fieldRemote[1]['remote-source'].length === 4) {
key = `${key}_${fieldRemote[1]['remote-source'][3]}`; // key = `${key}_${fieldRemote[1]['remote-source'][3]}`;
} // }
const key = this.getRemoteSourceKey(fieldRemote);
this.fieldMasterDataKeys[key] = false; this.fieldMasterDataKeys[key] = false;
const callBackData = {}; const callBackData = {};
@@ -320,26 +321,26 @@ class ModuleBase {
} }
/** /**
* Pass true to this method after creating module JS object to open new/edit entry form for the module on a popup. * Pass true to this method after creating module JS object to open new/edit entry form for the module on a popup.
* @method setShowFormOnPopup * @method setShowFormOnPopup
* @param val {Boolean} * @param val {Boolean}
* @example * @example
* modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id} * modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id}
* modJs.subModJsList['tabCandidateApplication'].setShowFormOnPopup(true); * modJs.subModJsList['tabCandidateApplication'].setShowFormOnPopup(true);
*/ */
setShowFormOnPopup(val) { setShowFormOnPopup(val) {
this.showFormOnPopup = val; this.showFormOnPopup = val;
} }
/** /**
* Set this to true to if you need the datatable to load data page by page instead of loading all data at once. * Set this to true to if you need the datatable to load data page by page instead of loading all data at once.
* @method setRemoteTable * @method setRemoteTable
* @param val {Boolean} * @param val {Boolean}
* @example * @example
* modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id} * modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id}
* modJs.subModJsList['tabCandidateApplication'].setRemoteTable(true); * modJs.subModJsList['tabCandidateApplication'].setRemoteTable(true);
*/ */
setRemoteTable(val) { setRemoteTable(val) {
this.createRemoteTable = val; this.createRemoteTable = val;
@@ -372,14 +373,14 @@ class ModuleBase {
} }
if (this.fieldMasterDataCallback !== null if (this.fieldMasterDataCallback !== null
&& this.fieldMasterDataCallback !== undefined && this.fieldMasterDataCallback !== undefined
&& this.isAllLoaded(this.fieldMasterDataKeys) && this.isAllLoaded(this.fieldMasterDataKeys)
&& (this.fieldMasterDataCallbackData !== null && this.fieldMasterDataCallbackData !== undefined) && (this.fieldMasterDataCallbackData !== null && this.fieldMasterDataCallbackData !== undefined)
) { ) {
this.fieldMasterDataCallback(this.fieldMasterDataCallbackData); this.fieldMasterDataCallback(this.fieldMasterDataCallbackData);
} else if (this.fieldMasterDataCallback !== null } else if (this.fieldMasterDataCallback !== null
&& this.fieldMasterDataCallback !== undefined && this.fieldMasterDataCallback !== undefined
&& this.isAllLoaded(this.fieldMasterDataKeys) && this.isAllLoaded(this.fieldMasterDataKeys)
) { ) {
this.fieldMasterDataCallback(); this.fieldMasterDataCallback();
} }
@@ -597,10 +598,10 @@ class ModuleBase {
} }
/** /**
* Create the data table on provided element id * Create the data table on provided element id
* @method createTable * @method createTable
* @param val {Boolean} * @param val {Boolean}
*/ */
createTable(elementId) { createTable(elementId) {
const that = this; const that = this;
@@ -678,10 +679,10 @@ class ModuleBase {
} }
/** /**
* Create a data table on provided element id which loads data page by page * Create a data table on provided element id which loads data page by page
* @method createTableServer * @method createTableServer
* @param val {Boolean} * @param val {Boolean}
*/ */
createTableServer(elementId) { createTableServer(elementId) {
const that = this; const that = this;
@@ -748,10 +749,10 @@ class ModuleBase {
} }
/** /**
* This should be overridden in module lib.js classes to return module headers which are used to create the data table. * This should be overridden in module lib.js classes to return module headers which are used to create the data table.
* @method getHeaders * @method getHeaders
* @example * @example
SettingAdapter.method('getHeaders() { SettingAdapter.method('getHeaders() {
return [ return [
{ "sTitle": "ID" ,"bVisible":false}, { "sTitle": "ID" ,"bVisible":false},
{ "sTitle": "Name" }, { "sTitle": "Name" },
@@ -759,17 +760,17 @@ class ModuleBase {
{ "sTitle": "Details"} { "sTitle": "Details"}
]; ];
} }
*/ */
getHeaders() { getHeaders() {
} }
/** /**
* This should be overridden in module lib.js classes to return module field values which are used to create the data table. * This should be overridden in module lib.js classes to return module field values which are used to create the data table.
* @method getDataMapping * @method getDataMapping
* @example * @example
SettingAdapter.method('getDataMapping() { SettingAdapter.method('getDataMapping() {
return [ return [
"id", "id",
"name", "name",
@@ -777,23 +778,23 @@ class ModuleBase {
"description" "description"
]; ];
} }
*/ */
getDataMapping() { getDataMapping() {
} }
/** /**
* This should be overridden in module lib.js classes to return module from fields which are used to create the add/edit form and also used for initializing select box values in form. * This should be overridden in module lib.js classes to return module from fields which are used to create the add/edit form and also used for initializing select box values in form.
* @method getFormFields * @method getFormFields
* @example * @example
SettingAdapter.method('getFormFields() { SettingAdapter.method('getFormFields() {
return [ return [
[ "id", {"label":"ID","type":"hidden"}], [ "id", {"label":"ID","type":"hidden"}],
[ "value", {"label":"Value","type":"text","validation":"none"}] [ "value", {"label":"Value","type":"text","validation":"none"}]
]; ];
} }
*/ */
getFormFields() { getFormFields() {
} }
@@ -807,26 +808,26 @@ class ModuleBase {
} }
/** /**
* This can be overridden in module lib.js classes inorder to show a filter form * This can be overridden in module lib.js classes inorder to show a filter form
* @method getFilters * @method getFilters
* @example * @example
EmployeeAdapter.method('getFilters() { EmployeeAdapter.method('getFilters() {
return [ return [
[ "job_title", {"label":"Job Title","type":"select2","allow-null":true,"null-label":"All Job Titles","remote-source":["JobTitle","id","name"]}], [ "job_title", {"label":"Job Title","type":"select2","allow-null":true,"null-label":"All Job Titles","remote-source":["JobTitle","id","name"]}],
[ "department", {"label":"Department","type":"select2","allow-null":true,"null-label":"All Departments","remote-source":["CompanyStructure","id","title"]}], [ "department", {"label":"Department","type":"select2","allow-null":true,"null-label":"All Departments","remote-source":["CompanyStructure","id","title"]}],
[ "supervisor", {"label":"Supervisor","type":"select2","allow-null":true,"null-label":"Anyone","remote-source":["Employee","id","first_name+last_name"]}] [ "supervisor", {"label":"Supervisor","type":"select2","allow-null":true,"null-label":"Anyone","remote-source":["Employee","id","first_name+last_name"]}]
]; ];
} }
*/ */
getFilters() { getFilters() {
return null; return null;
} }
/** /**
* Show the edit form for an item * Show the edit form for an item
* @method edit * @method edit
* @param id {int} id of the item to edit * @param id {int} id of the item to edit
*/ */
edit(id) { edit(id) {
this.currentId = id; this.currentId = id;
this.getElement(id, []); this.getElement(id, []);
@@ -890,10 +891,10 @@ class ModuleBase {
} }
/** /**
* Delete an item * Delete an item
* @method deleteRow * @method deleteRow
* @param id {int} id of the item to edit * @param id {int} id of the item to edit
*/ */
deleteRow(id) { deleteRow(id) {
this.deleteParams.id = id; this.deleteParams.id = id;
@@ -902,17 +903,17 @@ class ModuleBase {
} }
/** /**
* Show a popup with message * Show a popup with message
* @method showMessage * @method showMessage
* @param title {String} title of the message box * @param title {String} title of the message box
* @param message {String} message * @param message {String} message
* @param closeCallback {Function} this will be called once the dialog is closed (optional) * @param closeCallback {Function} this will be called once the dialog is closed (optional)
* @param closeCallback {Function} data to pass to close callback (optional) * @param closeCallback {Function} data to pass to close callback (optional)
* @param closeCallbackData * @param closeCallbackData
* @param isPlain {Boolean} if true buttons are not shown (optional / default = true) * @param isPlain {Boolean} if true buttons are not shown (optional / default = true)
* @example * @example
* this.showMessage("Error Occured while Applying Leave", callBackData); * this.showMessage("Error Occured while Applying Leave", callBackData);
*/ */
showMessage(title, message, closeCallback = null, closeCallbackData = null, isPlain = false) { showMessage(title, message, closeCallback = null, closeCallbackData = null, isPlain = false) {
const that = this; const that = this;
let modelId = ''; let modelId = '';
@@ -1005,11 +1006,11 @@ class ModuleBase {
/** /**
* Create or edit an element * Create or edit an element
* @method save * @method save
* @param getFunctionCallBackData {Array} once a success is returned call get() function for this module with these parameters * @param getFunctionCallBackData {Array} once a success is returned call get() function for this module with these parameters
* @param successCallback {Function} this will get called after success response * @param successCallback {Function} this will get called after success response
*/ */
save(callGetFunction, successCallback) { save(callGetFunction, successCallback) {
const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' }); const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' });
@@ -1040,7 +1041,7 @@ class ModuleBase {
const fields = this.getFormFields(); const fields = this.getFormFields();
fields.forEach((field) => { fields.forEach((field) => {
if ((field[1].type === 'date' || field[1].type === 'datetime') if ((field[1].type === 'date' || field[1].type === 'datetime')
&& (params[field[0]] === '' || params[field[0]] === '0000-00-00' || params[field[0]] === '0000-00-00 00:00:00')) { && (params[field[0]] === '' || params[field[0]] === '0000-00-00' || params[field[0]] === '0000-00-00 00:00:00')) {
if (field[1].validation === 'none') { if (field[1].validation === 'none') {
params[field[0]] = 'NULL'; params[field[0]] = 'NULL';
} else { } else {
@@ -1084,23 +1085,23 @@ class ModuleBase {
} }
/** /**
* Override this method to inject attitional parameters or modify existing parameters retrived from * Override this method to inject attitional parameters or modify existing parameters retrived from
* add/edit form before sending to the server * add/edit form before sending to the server
* @method forceInjectValuesBeforeSave * @method forceInjectValuesBeforeSave
* @param params {Array} keys and values in form * @param params {Array} keys and values in form
* @returns {Array} modified parameters * @returns {Array} modified parameters
*/ */
forceInjectValuesBeforeSave(params) { forceInjectValuesBeforeSave(params) {
return params; return params;
} }
/** /**
* Override this method to do custom validations at client side * Override this method to do custom validations at client side
* @method doCustomValidation * @method doCustomValidation
* @param params {Array} keys and values in form * @param params {Array} keys and values in form
* @returns {Null or String} return null if validation success, returns error message if unsuccessful * @returns {Null or String} return null if validation success, returns error message if unsuccessful
* @example * @example
EmployeeLeaveAdapter.method('doCustomValidation(params) { EmployeeLeaveAdapter.method('doCustomValidation(params) {
try{ try{
if(params['date_start'] != params['date_end']){ if(params['date_start'] != params['date_end']){
var ds = new Date(params['date_start']); var ds = new Date(params['date_start']);
@@ -1114,7 +1115,7 @@ class ModuleBase {
} }
return null; return null;
} }
*/ */
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
doCustomValidation(params) { doCustomValidation(params) {
return null; return null;
@@ -1177,7 +1178,12 @@ class ModuleBase {
value = 'Not Selected'; value = 'Not Selected';
} }
} else { } else {
value = this.fieldMasterData[`${rmf[0]}_${rmf[1]}_${rmf[2]}`][filters[prop]]; let key = `${rmf[0]}_${rmf[1]}_${rmf[2]}`;
if (rmf.length > 3) {
key = `${key}_${rmf[3]}`;
}
//value = this.fieldMasterData[`${rmf[0]}_${rmf[1]}_${rmf[2]}`][filters[prop]];
value = this.fieldMasterData[key][filters[prop]];
valueOrig = value; valueOrig = value;
} }
} else { } else {
@@ -1231,20 +1237,20 @@ class ModuleBase {
} }
/** /**
* Override this method to do custom validations at client side for values selected in filters * Override this method to do custom validations at client side for values selected in filters
* @method doCustomFilterValidation * @method doCustomFilterValidation
* @param params {Array} keys and values in form * @param params {Array} keys and values in form
* @returns {Null or String} return null if validation success, returns error message if unsuccessful * @returns {Null or String} return null if validation success, returns error message if unsuccessful
*/ */
doCustomFilterValidation(params) { doCustomFilterValidation(params) {
return true; return true;
} }
/** /**
* Reset selected filters * Reset selected filters
* @method resetFilters * @method resetFilters
*/ */
resetFilters() { resetFilters() {
this.filter = this.origFilter; this.filter = this.origFilter;
@@ -1332,7 +1338,8 @@ class ModuleBase {
try { try {
modJs.filterQuery(); modJs.filterQuery();
} catch (err) { } catch (err) {
// Do Nothing console.log(err);
console.log(err.message);
} }
return false; return false;
}); });
@@ -1344,20 +1351,20 @@ class ModuleBase {
/** /**
* Override this method in your module class to make changes to data fo the form before showing the form * Override this method in your module class to make changes to data fo the form before showing the form
* @method preRenderForm * @method preRenderForm
* @param object {Array} keys value list for populating form * @param object {Array} keys value list for populating form
*/ */
preRenderForm(object) { preRenderForm(object) {
} }
/** /**
* Create the form * Create the form
* @method renderForm * @method renderForm
* @param object {Array} keys value list for populating form * @param object {Array} keys value list for populating form
*/ */
renderForm(object) { renderForm(object) {
const signatureIds = []; const signatureIds = [];
@@ -1581,28 +1588,28 @@ class ModuleBase {
} }
/** /**
* Override this method in your module class to make changes to data fo the form after showing it * Override this method in your module class to make changes to data fo the form after showing it
* @method postRenderForm * @method postRenderForm
* @param object {Array} keys value list for populating form * @param object {Array} keys value list for populating form
* @param $tempDomObj {DOM} a DOM element for the form * @param $tempDomObj {DOM} a DOM element for the form
* @example * @example
* UserAdapter.method('postRenderForm(object, $tempDomObj) { * UserAdapter.method('postRenderForm(object, $tempDomObj) {
if(object == null || object == undefined){ if(object == null || object == undefined){
$tempDomObj.find("#changePasswordBtn").remove(); $tempDomObj.find("#changePasswordBtn").remove();
} }
} }
*/ */
postRenderForm(object, $tempDomObj) { postRenderForm(object, $tempDomObj) {
} }
/** /**
* Convert data group field to HTML * Convert data group field to HTML
* @method dataGroupToHtml * @method dataGroupToHtml
* @param val {String} value in the field * @param val {String} value in the field
* @param field {Array} field meta data * @param field {Array} field meta data
*/ */
dataGroupToHtml(val, field) { dataGroupToHtml(val, field) {
const data = JSON.parse(val); const data = JSON.parse(val);
@@ -1657,10 +1664,10 @@ class ModuleBase {
} }
/** /**
* Reset the DataGroup for a given field * Reset the DataGroup for a given field
* @method resetDataGroup * @method resetDataGroup
* @param field {Array} field meta data * @param field {Array} field meta data
*/ */
resetDataGroup(field) { resetDataGroup(field) {
$(`#${field[0]}`).val(''); $(`#${field[0]}`).val('');
$(`#${field[0]}_div`).html(''); $(`#${field[0]}_div`).html('');
@@ -2054,12 +2061,12 @@ class ModuleBase {
/** /**
* Fill a form with required values after showing it * Fill a form with required values after showing it
* @method fillForm * @method fillForm
* @param object {Array} form data * @param object {Array} form data
* @param formId {String} id of the form * @param formId {String} id of the form
* @param formId {Array} field meta data * @param formId {Array} field meta data
*/ */
fillForm(object, formId, fields) { fillForm(object, formId, fields) {
let placeHolderVal; let placeHolderVal;
@@ -2094,7 +2101,8 @@ class ModuleBase {
$(`${formId} #${fields[i][0]}`).html(object[fields[i][0]]); $(`${formId} #${fields[i][0]}`).html(object[fields[i][0]]);
} else if (fields[i][1].type === 'placeholder') { } else if (fields[i][1].type === 'placeholder') {
if (fields[i][1]['remote-source'] !== undefined && fields[i][1]['remote-source'] != null) { if (fields[i][1]['remote-source'] !== undefined && fields[i][1]['remote-source'] != null) {
const key = `${fields[i][1]['remote-source'][0]}_${fields[i][1]['remote-source'][1]}_${fields[i][1]['remote-source'][2]}`; //const key = `${fields[i][1]['remote-source'][0]}_${fields[i][1]['remote-source'][1]}_${fields[i][1]['remote-source'][2]}`;
const key = this.getRemoteSourceKey(fields[i]);
placeHolderVal = this.fieldMasterData[key][object[fields[i][0]]]; placeHolderVal = this.fieldMasterData[key][object[fields[i][0]]];
} else { } else {
placeHolderVal = object[fields[i][0]]; placeHolderVal = object[fields[i][0]];
@@ -2172,7 +2180,7 @@ class ModuleBase {
} }
} else if (fields[i][1].type === 'signature') { } else if (fields[i][1].type === 'signature') {
if (object[fields[i][0]] !== '' || object[fields[i][0]] !== undefined if (object[fields[i][0]] !== '' || object[fields[i][0]] !== undefined
|| object[fields[i][0]] != null) { || object[fields[i][0]] != null) {
$(`${formId} #${fields[i][0]}`).data('signaturePad').fromDataURL(object[fields[i][0]]); $(`${formId} #${fields[i][0]}`).data('signaturePad').fromDataURL(object[fields[i][0]]);
} }
} else if (fields[i][1].type === 'simplemde') { } else if (fields[i][1].type === 'simplemde') {
@@ -2189,9 +2197,9 @@ class ModuleBase {
} }
/** /**
* Cancel edit or add new on modules * Cancel edit or add new on modules
* @method cancel * @method cancel
*/ */
cancel() { cancel() {
$(`#${this.getTableName()}Form`).hide(); $(`#${this.getTableName()}Form`).hide();
@@ -2218,10 +2226,11 @@ class ModuleBase {
if (field[1].source !== undefined && field[1].source != null) { if (field[1].source !== undefined && field[1].source != null) {
t = t.replace('_options_', this.renderFormSelectOptions(field[1].source, field)); t = t.replace('_options_', this.renderFormSelectOptions(field[1].source, field));
} else if (field[1]['remote-source'] !== undefined && field[1]['remote-source'] != null) { } else if (field[1]['remote-source'] !== undefined && field[1]['remote-source'] != null) {
let key = `${field[1]['remote-source'][0]}_${field[1]['remote-source'][1]}_${field[1]['remote-source'][2]}`; // let key = `${field[1]['remote-source'][0]}_${field[1]['remote-source'][1]}_${field[1]['remote-source'][2]}`;
if (field[1]['remote-source'].length === 4) { // if (field[1]['remote-source'].length === 4) {
key = `${key}_${field[1]['remote-source'][3]}`; // key = `${key}_${field[1]['remote-source'][3]}`;
} // }
const key = this.getRemoteSourceKey(field);
t = t.replace('_options_', this.renderFormSelectOptionsRemote(this.fieldMasterData[key], field)); t = t.replace('_options_', this.renderFormSelectOptionsRemote(this.fieldMasterData[key], field));
} }
} else if (field[1].type === 'colorpick') { } else if (field[1].type === 'colorpick') {
@@ -2413,49 +2422,49 @@ class ModuleBase {
} }
/** /**
* Override this method to change add new button label * Override this method to change add new button label
* @method getAddNewLabel * @method getAddNewLabel
*/ */
getAddNewLabel() { getAddNewLabel() {
return 'Add New'; return 'Add New';
} }
/** /**
* Used to set whether to show the add new button for a module * Used to set whether to show the add new button for a module
* @method setShowAddNew * @method setShowAddNew
* @param showAddNew {Boolean} value * @param showAddNew {Boolean} value
*/ */
setShowAddNew(showAddNew) { setShowAddNew(showAddNew) {
this.showAddNew = showAddNew; this.showAddNew = showAddNew;
} }
/** /**
* Used to set whether to show delete button for each entry in module * Used to set whether to show delete button for each entry in module
* @method setShowDelete * @method setShowDelete
* @param val {Boolean} value * @param val {Boolean} value
*/ */
setShowDelete(val) { setShowDelete(val) {
this.showDelete = val; this.showDelete = val;
} }
/** /**
* Used to set whether to show edit button for each entry in module * Used to set whether to show edit button for each entry in module
* @method setShowEdit * @method setShowEdit
* @param val {Boolean} value * @param val {Boolean} value
*/ */
setShowEdit(val) { setShowEdit(val) {
this.showEdit = val; this.showEdit = val;
} }
/** /**
* Used to set whether to show save button in form * Used to set whether to show save button in form
* @method setShowSave * @method setShowSave
* @param val {Boolean} value * @param val {Boolean} value
*/ */
setShowSave(val) { setShowSave(val) {
@@ -2464,20 +2473,20 @@ class ModuleBase {
/** /**
* Used to set whether to show cancel button in form * Used to set whether to show cancel button in form
* @method setShowCancel * @method setShowCancel
* @param val {Boolean} value * @param val {Boolean} value
*/ */
setShowCancel(val) { setShowCancel(val) {
this.showCancel = val; this.showCancel = val;
} }
/** /**
* Datatable option array will be extended with associative array provided here * Datatable option array will be extended with associative array provided here
* @method getCustomTableParams * @method getCustomTableParams
* @param val {Boolean} value * @param val {Boolean} value
*/ */
getCustomTableParams() { getCustomTableParams() {
@@ -2490,12 +2499,12 @@ class ModuleBase {
/** /**
* This return html for action buttons in each row. Override this method if you need to make changes to action buttons. * This return html for action buttons in each row. Override this method if you need to make changes to action buttons.
* @method getActionButtonsHtml * @method getActionButtonsHtml
* @param id {int} id of the row * @param id {int} id of the row
* @param data {Array} data for the row * @param data {Array} data for the row
* @returns {String} html for action buttons * @returns {String} html for action buttons
*/ */
getActionButtonsHtml(id, data) { 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 editButton = '<img class="tableActionButton" src="_BASE_images/edit.png" style="cursor:pointer;" rel="tooltip" title="Edit" onclick="modJs.edit(_id_);return false;"></img>';
@@ -2528,11 +2537,11 @@ class ModuleBase {
/** /**
* Generates a random string * Generates a random string
* @method generateRandom * @method generateRandom
* @param length {int} required length of the string * @param length {int} required length of the string
* @returns {String} random string * @returns {String} random string
*/ */
generateRandom(length) { generateRandom(length) {
const d = new Date(); const d = new Date();
@@ -2593,10 +2602,10 @@ class ModuleBase {
} }
/** /**
* Override this method in a module to provide the help link for the module. Help link of the module on frontend will get updated with this. * Override this method in a module to provide the help link for the module. Help link of the module on frontend will get updated with this.
* @method getHelpLink * @method getHelpLink
* @returns {String} help link * @returns {String} help link
*/ */
getHelpLink() { getHelpLink() {
return null; return null;

View File

@@ -0,0 +1,232 @@
import React, {Component} from 'react';
import {
Form,
Modal,
Input,
Button,
message,
} from 'antd';
import CustomAction from '../api/CustomAction';
class UpdatePasswordModal extends React.Component {
state = {
loading: false,
passwordHasError: false,
passwordState: { hasFeedback: false, validateStatus:'', help:'Password must include at least one number, one lowercase letter, one uppercase letter and a symbol' },
confirmationHasError: false,
confirmationState: { hasFeedback: false, validateStatus:'', help:'' },
};
constructor(props) {
super(props);
this.formRef = React.createRef();
this.customAction = new CustomAction(this.props.adapter);
}
componentDidMount() {
message.config({
top: 40,
});
}
clearConfirmFeedback = () => {
this.setState({confirmationHasError: false});
this.setState({
confirmationState: {
hasFeedback : false,
validateStatus:'',
help:'',
}
});
}
updatePasswordState(value) {
const passwordValidationResult = this.validatePassword(value);
if (passwordValidationResult !== null) {
this.setState({passwordHasError: true});
this.setState({
passwordState: {
hasFeedback : true,
validateStatus:'error',
help:passwordValidationResult,
}
});
return false;
} else {
this.setState({passwordHasError: false});
this.setState({
passwordState: {
hasFeedback : true,
validateStatus:'success',
help:'',
}
});
}
return true;
}
updateConfirmPasswordState(values) {
if (values.confirm !== values.new) {
this.setState({confirmationHasError: true});
this.setState({
confirmationState: {
hasFeedback : true,
validateStatus:'error',
help:'Passwords don\'t match',
}
});
return false;
} else {
this.setState({confirmationHasError: false});
this.setState({
confirmationState: {
hasFeedback : false,
validateStatus:'',
help:'',
}
});
}
return true;
}
handleOk = () => {
const from = this.formRef.current;
from
.validateFields()
.then((values) => {
if (this.updatePasswordState(values.new) && this.updateConfirmPasswordState(values)) {
this.updatePassword(values.current, values.new)
.then((response) => {
const data = response.data;
console.log(data);
if (data.status === 'SUCCESS') {
this.handleCancel();
message.success(this.props.adapter.gt('Password updated'));
} else {
message.error(
`${this.props.adapter.gt('Error updating password')}: ${this.props.adapter.gt(data.data)}`
);
}
}).catch((error) => {
message.error(
`${this.props.adapter.gt('Error updating password')}`
);
console.log(error.message);
});
}
})
.catch((info) => {
this.setState({ loading: false });
});
}
handleCancel = () => {
if (this.formRef.current) {
this.formRef.current.resetFields();
}
this.props.closeModal();
}
updatePassword = (oldPassword, newPassword) => {
const req = { current: oldPassword ? oldPassword : '', pwd: newPassword };
const reqJson = JSON.stringify(req);
const callBackData = [];
callBackData.callBackData = [];
callBackData.callBackSuccess = 'changePasswordSuccessCallBack';
callBackData.callBackFail = 'changePasswordFailCallBack';
return this.customAction.execute('changePassword', 'modules=employees', reqJson);
}
validatePassword = (password) => {
if (password.length < 8) {
return this.props.adapter.gt('Password too short');
}
if (password.length > 20) {
return this.props.adapter.gt('Password too long');
}
const numberTester = /.*[0-9]+.*$/;
if (!password.match(numberTester)) {
return this.props.adapter.gt('Password must include at least one number');
}
const lowerTester = /.*[a-z]+.*$/;
if (!password.match(lowerTester)) {
return this.props.adapter.gt('Password must include at least one lowercase letter');
}
const upperTester = /.*[A-Z]+.*$/;
if (!password.match(upperTester)) {
return this.props.adapter.gt('Password must include at least one uppercase letter');
}
const symbolTester = /.*[\W]+.*$/;
if (!password.match(symbolTester)) {
return this.props.adapter.gt('Password must include at least one symbol');
}
return null;
}
render() {
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
return (
<Modal
visible={this.props.visible}
title="Update Password"
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={[
<Button key="back" onClick={this.handleCancel}>
{this.props.adapter.gt('Cancel')}
</Button>,
<Button key="submit" type="primary" loading={this.state.loading} onClick={this.handleOk}>
{this.props.adapter.gt('Update')}
</Button>,
]}
>
<Form {...layout} ref={this.formRef}>
<Form.Item label="Current Password" key="current" name="current" >
<Input.Password placeholder="current password"/>
</Form.Item>
{ this.state.passwordHasError &&
<Form.Item label="New Password" key="new" name="new" {...this.state.passwordState}>
<Input.Password placeholder="new password" onChange={(event) => this.updatePasswordState(event.target.value)}/>
</Form.Item>
}
{ !this.state.passwordHasError &&
<Form.Item label="New Password" key="new" name="new" {...this.state.passwordState}>
<Input.Password placeholder="new password" onChange={(event) => this.updatePasswordState(event.target.value)}/>
</Form.Item>
}
{ this.state.confirmationHasError &&
<Form.Item label="Confirm Password" key="confirm" name="confirm" {...this.state.confirmationState}>
<Input.Password placeholder="confirm password" onChange={(event) => this.clearConfirmFeedback()}/>
</Form.Item>
}
{ !this.state.confirmationHasError &&
<Form.Item label="Confirm Password" key="confirm" name="confirm" >
<Input.Password placeholder="confirm password" onChange={(event) => this.clearConfirmFeedback()}/>
</Form.Item>
}
</Form>
</Modal>
)
}
}
export default UpdatePasswordModal;

30987
web/dist/admin-bundle.js vendored

File diff suppressed because one or more lines are too long

4
web/dist/common.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,37 +1,32 @@
import React, {Component} from 'react'; import React from 'react';
import { import {
Col, Col,
Card, Card,
Badge,
Avatar, Avatar,
Input,
Row, Row,
Descriptions, Descriptions,
Typography, Typography,
Table,
Space, Space,
Button,
Tag, Tag,
message,
Tabs, Tabs,
Spin,
Skeleton Skeleton
} from 'antd'; } from 'antd';
import { import {
FilterOutlined,
EditOutlined, EditOutlined,
PhoneTwoTone, PhoneTwoTone,
MailTwoTone, MailTwoTone,
SyncOutlined, SyncOutlined,
LockOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import TagList from "../../../../components/TagList"; import TagList from "../../../../components/TagList";
const { Search } = Input; import UpdatePasswordModal from "../../../../components/UpdatePasswordModal";
const { Title, Text } = Typography; const { Title, Text } = Typography;
const { TabPane } = Tabs; const { TabPane } = Tabs;
class EmployeeProfile extends React.Component { class EmployeeProfile extends React.Component {
state = { state = {
loading: true, loading: true,
showPasswordResetModal: false,
}; };
constructor(props) { constructor(props) {
@@ -42,6 +37,10 @@ class EmployeeProfile extends React.Component {
this.setState({ loading: value }); this.setState({ loading: value });
} }
setShowPasswordUpdate(value) {
this.setState({ showPasswordResetModal: value });
}
updateProfileImage() { updateProfileImage() {
showUploadDialog( showUploadDialog(
`profile_image_${this.props.element.id}_${(new Date()).getTime()}`, `profile_image_${this.props.element.id}_${(new Date()).getTime()}`,
@@ -71,6 +70,33 @@ class EmployeeProfile extends React.Component {
</>); </>);
} }
getEditButtonJsxWithPassword() {
return (<>
{this.state.loading &&
<Tag icon={<SyncOutlined spin/>} color="processing">
{this.props.adapter.gt('Edit')}
</Tag>
}
{!this.state.loading &&
<Tag icon={<EditOutlined/>} color="processing"
onClick={() => modJs.edit(this.props.element.id)}>
{this.props.adapter.gt('Edit')}
</Tag>
}
<Tag icon={<LockOutlined/>} color="volcano" onClick={() => this.setShowPasswordUpdate(true)}>
{this.props.adapter.gt('Update Password')}
</Tag>
</>);
}
getUpdatePasswordButtonJsx() {
return (<>
<Tag icon={<SyncOutlined spin/>} color="processing">
{this.props.adapter.gt('Update Password')}
</Tag>
</>);
}
getTabViewEmployeeFilterButtonJsx(tab) { getTabViewEmployeeFilterButtonJsx(tab) {
return ( return (
<Tag icon={<EditOutlined/>} color="processing" <Tag icon={<EditOutlined/>} color="processing"
@@ -86,10 +112,15 @@ class EmployeeProfile extends React.Component {
} }
return ( return (
<> <>
<UpdatePasswordModal
visible={this.state.showPasswordResetModal}
closeModal={() => {this.setState({ showPasswordResetModal: false })}}
adapter={this.props.adapter}
/>
<Row direction="vertical" style={{width: '100%', padding: '10px'}} gutter={24}> <Row direction="vertical" style={{width: '100%', padding: '10px'}} gutter={24}>
<Col span={24}> <Col span={24}>
<Card title={this.props.adapter.gt('Employee Profile')} <Card title={this.props.adapter.gt('Employee Profile')}
extra={this.getEditButtonJsx()} extra={this.getEditButtonJsxWithPassword()}
style={{ width: '100%' }} style={{ width: '100%' }}
> >
<Space size={'large'}> <Space size={'large'}>

View File

@@ -613,8 +613,15 @@ class EmployeeTimeEntryAdapter extends AdapterBase {
return dateArray; return dateArray;
} }
renderForm(object) { renderForm(object) {
this.initMasterDataReader();
this.masterDataReader.updateAllMasterData()
.then(() => {
this._renderForm(object);
});
}
_renderForm(object) {
let formHtml = this.getCustomTemplate('time_entry_form.html'); let formHtml = this.getCustomTemplate('time_entry_form.html');
formHtml = formHtml.replace(/modJs/g, "modJsList['tabEmployeeTimeEntry']"); formHtml = formHtml.replace(/modJs/g, "modJsList['tabEmployeeTimeEntry']");
let html = ''; let html = '';