Compare commits
24 Commits
v28.1.0.OS
...
extension-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5df15d39c1 | ||
|
|
143bcac1f9 | ||
|
|
84548c4f63 | ||
|
|
e5eccf32a7 | ||
|
|
f1dcc6b6a0 | ||
|
|
b6c0256b49 | ||
|
|
e31bf5a4b9 | ||
|
|
06a3172a38 | ||
|
|
e74ca00902 | ||
|
|
28aa16f35c | ||
|
|
fb3b5b562e | ||
|
|
8663a7aff1 | ||
|
|
e9baf45d7c | ||
|
|
2abe52963f | ||
|
|
da55c7a2d2 | ||
|
|
5cd7963f6f | ||
|
|
d986a2b5bb | ||
|
|
1ee4fb4ba1 | ||
|
|
b06780c466 | ||
|
|
5ec497e11d | ||
|
|
df3b6e968a | ||
|
|
3ceb427479 | ||
|
|
d3b4748cba | ||
|
|
2a9e65d8a8 |
@@ -14,7 +14,6 @@ install:
|
||||
script: ant build-ci
|
||||
language: php
|
||||
php:
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
|
||||
16
Vagrantfile
vendored
16
Vagrantfile
vendored
@@ -3,8 +3,6 @@ Vagrant.configure("2") do |config|
|
||||
config.vm.box_version = "1.0.0"
|
||||
config.vm.network "private_network", ip: "192.168.10.12"
|
||||
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|
|
||||
vb.memory = "1024"
|
||||
@@ -13,9 +11,17 @@ Vagrant.configure("2") do |config|
|
||||
end
|
||||
|
||||
config.vm.provision "shell", inline: <<-SHELL
|
||||
sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
|
||||
systemctl restart sshd.service
|
||||
sudo service nginx restart
|
||||
sudo rm /etc/nginx/ssl/icehrm.*
|
||||
sudo ln -s /vagrant/deployment/vagrant/ssl/icehrm.crt /etc/nginx/ssl/icehrm.crt
|
||||
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
|
||||
|
||||
config.vm.hostname = "icehrm.os"
|
||||
|
||||
@@ -5,7 +5,7 @@ if(!file_exists('config.php')){
|
||||
}
|
||||
include ('config.php');
|
||||
if(!isset($_REQUEST['g']) || !isset($_REQUEST['n'])){
|
||||
header("Location:".CLIENT_BASE_URL."login.php");
|
||||
header("Location:".CLIENT_BASE_URL."login.php");
|
||||
exit();
|
||||
}
|
||||
$group = $_REQUEST['g'];
|
||||
@@ -14,9 +14,16 @@ $name= $_REQUEST['n'];
|
||||
$groups = array('admin','modules');
|
||||
|
||||
if($group == 'admin' || $group == 'modules'){
|
||||
$name = str_replace("..","",$name);
|
||||
$name = str_replace("..","",$name);
|
||||
$name = str_replace("/","",$name);
|
||||
include APP_BASE_PATH.'/'.$group.'/'.$name.'/index.php';
|
||||
}else if ($group == 'extension'){
|
||||
$name = str_replace("..","",$name);
|
||||
$name = str_replace("/","",$name);
|
||||
$moduleName = $name;
|
||||
$moduleGroup = 'extensions';
|
||||
$extensionIndex = APP_BASE_PATH.'/../extensions/'.$name.'/web/index.php';
|
||||
include APP_BASE_PATH.'extensions/wrapper.php';
|
||||
}else{
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?php
|
||||
include ('config.php');
|
||||
include (APP_BASE_PATH.'rest.php');
|
||||
include (APP_BASE_PATH.'rest.php');
|
||||
|
||||
1
bin/export-plural-rules
Symbolic link
1
bin/export-plural-rules
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/gettext/languages/bin/export-plural-rules
|
||||
1
bin/markdown
Symbolic link
1
bin/markdown
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/cebe/markdown/bin/markdown
|
||||
1
bin/pdepend
Symbolic link
1
bin/pdepend
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/pdepend/pdepend/src/bin/pdepend
|
||||
1
bin/phpcb
Symbolic link
1
bin/phpcb
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/mayflower/php-codebrowser/bin/phpcb
|
||||
1
bin/phpcbf
Symbolic link
1
bin/phpcbf
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/squizlabs/php_codesniffer/scripts/phpcbf
|
||||
1
bin/phpcpd
Symbolic link
1
bin/phpcpd
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/sebastian/phpcpd/composer/bin/phpcpd
|
||||
1
bin/phpcs
Symbolic link
1
bin/phpcs
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/squizlabs/php_codesniffer/scripts/phpcs
|
||||
1
bin/phploc
Symbolic link
1
bin/phploc
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/phploc/phploc/phploc
|
||||
1
bin/phpmd
Symbolic link
1
bin/phpmd
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/phpmd/phpmd/src/bin/phpmd
|
||||
1
bin/phpunit
Symbolic link
1
bin/phpunit
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/phpunit/phpunit/phpunit
|
||||
1
bin/release
Symbolic link
1
bin/release
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/consolidation/self-update/scripts/release
|
||||
1
bin/robo
Symbolic link
1
bin/robo
Symbolic link
@@ -0,0 +1 @@
|
||||
../core/lib/composer/vendor/consolidation/robo/robo
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="icehrm" default="build">
|
||||
<!-- 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="testdir" value="${basedir}/build/test"/>
|
||||
<property name="origin" value="${basedir}"/>
|
||||
|
||||
47
core/api-rest.php
Normal file
47
core/api-rest.php
Normal 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
41
core/api-url-based.php
Normal 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";
|
||||
}
|
||||
@@ -13,10 +13,10 @@ if(!defined('HOME_LINK_OTHERS')){
|
||||
}
|
||||
|
||||
//Version
|
||||
define('VERSION', '28.1.0.OS');
|
||||
define('CACHE_VALUE', '28.1.0.OS.2020-10311445');
|
||||
define('VERSION_NUMBER', '280100');
|
||||
define('VERSION_DATE', '31/10/2020');
|
||||
define('VERSION', '28.1.1.OS');
|
||||
define('CACHE_VALUE', '28.1.1.OS.2020-11071143');
|
||||
define('VERSION_NUMBER', '280101');
|
||||
define('VERSION_DATE', '07/11/2020');
|
||||
|
||||
if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');}
|
||||
if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');}
|
||||
@@ -36,3 +36,7 @@ define('ALL_CLIENT_BASE_PATH', '/var/www/icehrm.app/icehrmapp/');
|
||||
define('LDAP_ENABLED', true);
|
||||
define('RECRUITMENT_ENABLED', false);
|
||||
define('APP_WEB_URL', 'https://icehrm.com');
|
||||
|
||||
if (!defined('EXTENSIONS_URL')) {
|
||||
define('EXTENSIONS_URL', str_replace('/web/', '/extensions/', BASE_URL));
|
||||
}
|
||||
|
||||
31
core/extensions/wrapper.php
Normal file
31
core/extensions/wrapper.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
use Classes\ExtensionManager;
|
||||
use Utils\LogManager;
|
||||
|
||||
if (!isset($extensionIndex)) {
|
||||
exit();
|
||||
}
|
||||
define('MODULE_PATH',APP_BASE_PATH.'extensions/'.$moduleName);
|
||||
include APP_BASE_PATH.'header.php';
|
||||
$extensionManager = new ExtensionManager();
|
||||
$meta = $extensionManager->getExtensionMetaData($moduleName);
|
||||
if (!$meta) {
|
||||
LogManager::getInstance()->error("Extension metadata.json not found for $moduleName");
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($meta->headless) {
|
||||
LogManager::getInstance()->error("Extension running in headless mode for $moduleName");
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorReact.js'?>?v=<?=$jsVersion?>"></script>
|
||||
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorAntd.js'?>?v=<?=$jsVersion?>"></script>
|
||||
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorAntdIcons.js'?>?v=<?=$jsVersion?>"></script>
|
||||
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorAntv.js'?>?v=<?=$jsVersion?>"></script>
|
||||
<script type="text/javascript" src="<?=BASE_URL.'dist/vendorOther.js'?>?v=<?=$jsVersion?>"></script>
|
||||
<script type="text/javascript" src="<?=EXTENSIONS_URL.$moduleName.'/dist/'.$moduleName.'.js'?>?v=<?=$jsVersion?>"></script>
|
||||
<?php
|
||||
include $extensionIndex;
|
||||
include APP_BASE_PATH.'footer.php';
|
||||
?>
|
||||
@@ -215,6 +215,26 @@ if (defined('SYM_CLIENT')) {
|
||||
|
||||
<?php }?>
|
||||
|
||||
<?php foreach($extensions as $menu){?>
|
||||
<?php if(count($menu['menu']) == 0){continue;}?>
|
||||
<li class="treeview" ref="<?="extension_".str_replace(" ", "_", $menu['name'])?>">
|
||||
<a href="#">
|
||||
<i class="fa <?=!isset($mainIcons[$menu['name']])?"fa-th":$mainIcons[$menu['name']];?>"></i></i> <span><?=\Classes\LanguageManager::tran($menu['name'])?></span>
|
||||
<i class="fa fa-angle-left pull-right"></i>
|
||||
</a>
|
||||
|
||||
<ul class="treeview-menu" id="<?="extension_".str_replace(" ", "_", $menu['name'])?>">
|
||||
<?php foreach ($menu['menu'] as $item){?>
|
||||
<li>
|
||||
<a data-turbolinks="true" href="<?=CLIENT_BASE_URL?>?g=extension&n=<?=$item['name']?>&m=<?="extension_".str_replace(" ", "_", $menu['name'])?>">
|
||||
<i class="fa <?=!isset($item['icon'])?"fa-angle-double-right":$item['icon']?>"></i> <?=\Classes\LanguageManager::tran($item['label'])?>
|
||||
</a>
|
||||
</li>
|
||||
<?php }?>
|
||||
</ul>
|
||||
</li>
|
||||
<?php }?>
|
||||
|
||||
<?php
|
||||
if(file_exists(CLIENT_PATH.'/third_party_meta.json')){
|
||||
$tpModules = json_decode(file_get_contents(CLIENT_PATH.'/third_party_meta.json'),true);
|
||||
|
||||
@@ -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="bg-white-2 h-100 px-11 pt-11 pb-7">
|
||||
<div class="row d-flex justify-content-center">
|
||||
<img src="<?=$logoFileUrl?>"/>
|
||||
<img src="<?=$logoFileUrl?>" style="max-width:100%;max-height:280px;"/>
|
||||
</div>
|
||||
<hr/>
|
||||
<?php if ($gsuiteEnabled) {?>
|
||||
|
||||
@@ -291,6 +291,12 @@ foreach ($ams as $am) {
|
||||
}
|
||||
}
|
||||
|
||||
$extensionManager = new \Classes\ExtensionManager();
|
||||
$extensionData = $extensionManager->setupExtensions();
|
||||
$extensionIcons = $extensionData[0];
|
||||
$extensionTemp = $extensionData[1];
|
||||
$extensionMenus = array_keys($extensionIcons);
|
||||
|
||||
foreach ($adminModulesTemp as $k => $v) {
|
||||
ksort($adminModulesTemp[$k]);
|
||||
}
|
||||
@@ -299,6 +305,10 @@ foreach ($userModulesTemp as $k => $v) {
|
||||
ksort($userModulesTemp[$k]);
|
||||
}
|
||||
|
||||
foreach ($extensionTemp as $k => $v) {
|
||||
ksort($extensionTemp[$k]);
|
||||
}
|
||||
|
||||
$adminIcons = json_decode(file_get_contents(CLIENT_PATH.'/admin/meta.json'), true);
|
||||
$adminMenus = array_keys($adminIcons);
|
||||
|
||||
@@ -332,8 +342,6 @@ foreach ($userMenus as $menu) {
|
||||
}
|
||||
}
|
||||
|
||||
$mainIcons = array_merge($adminIcons, $userIcons);
|
||||
|
||||
foreach ($userModulesTemp as $k => $v) {
|
||||
if (!in_array($k, $added)) {
|
||||
$arr = array("name"=>$k,"menu"=>$userModulesTemp[$k]);
|
||||
@@ -341,6 +349,25 @@ foreach ($userModulesTemp as $k => $v) {
|
||||
}
|
||||
}
|
||||
|
||||
$extensions = array();
|
||||
foreach ($extensionMenus as $menu) {
|
||||
if (isset($extensionTemp[$menu])) {
|
||||
$arr = array("name"=>$menu,"menu"=>$extensionTemp[$menu]);
|
||||
$extensions[] = $arr;
|
||||
$added[] = $menu;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($extensionTemp as $k => $v) {
|
||||
if (!in_array($k, $added)) {
|
||||
$arr = array("name"=>$k,"menu"=>$extensionTemp[$k]);
|
||||
$extensions[] = $arr;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge icons
|
||||
$mainIcons = array_merge($adminIcons, $userIcons, $extensionIcons);
|
||||
|
||||
//Remove modules having no permissions
|
||||
if (!empty($user)) {
|
||||
if (!empty($user->user_roles)) {
|
||||
@@ -393,4 +420,24 @@ if (!empty($user)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($extensions as $fk => $menu) {
|
||||
foreach ($menu['menu'] as $key => $item) {
|
||||
// If the user's once of the user roles are blacklisted for the module
|
||||
$commonRoles = array_intersect($item['user_roles_blacklist'], $userRoles);
|
||||
if (!empty($commonRoles)) {
|
||||
unset($extensions[$fk]['menu'][$key]);
|
||||
}
|
||||
if (!in_array($user->user_level, $item['user_levels'])) {
|
||||
if (!empty($userRoles)) {
|
||||
$commonRoles = array_intersect($item['user_roles'], $userRoles);
|
||||
if (empty($commonRoles)) {
|
||||
unset($extensions[$fk]['menu'][$key]);
|
||||
}
|
||||
} else {
|
||||
unset($extensions[$fk]['menu'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,49 +3,8 @@ header('Access-Control-Allow-Origin: *');
|
||||
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('Content-Type: application/json');
|
||||
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";
|
||||
if (isset($_REQUEST['method']) && isset($_REQUEST['url'])) {
|
||||
include(APP_BASE_PATH . 'api-url-based.php');
|
||||
} else {
|
||||
include(APP_BASE_PATH . 'api-rest.php');
|
||||
}
|
||||
|
||||
@@ -278,4 +278,12 @@ abstract class AbstractModuleManager
|
||||
{
|
||||
BaseService::getInstance()->addCalculationHook($code, $name, $class, $method);
|
||||
}
|
||||
|
||||
public function install() {
|
||||
|
||||
}
|
||||
|
||||
public function uninstall() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,8 +292,8 @@ class BaseService
|
||||
|
||||
$childCompaniesIds = array();
|
||||
if (\Classes\SettingsManager::getInstance()->getSetting(
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
) {
|
||||
$childCompaniesResp = \Company\Common\Model\CompanyStructure::getAllChildCompanyStructures(
|
||||
$cempObj->department
|
||||
@@ -486,8 +486,8 @@ class BaseService
|
||||
|
||||
$childCompaniesIds = array();
|
||||
if (SettingsManager::getInstance()->getSetting(
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
) {
|
||||
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
|
||||
$childCompanies = $childCompaniesResp->getObject();
|
||||
@@ -567,8 +567,8 @@ class BaseService
|
||||
|
||||
$childCompaniesIds = array();
|
||||
if (SettingsManager::getInstance()->getSetting(
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
) {
|
||||
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
|
||||
$childCompanies = $childCompaniesResp->getObject();
|
||||
@@ -1783,8 +1783,8 @@ END;
|
||||
) {
|
||||
$departmentHeadFound = true;
|
||||
} elseif (SettingsManager::getInstance()->getSetting(
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
'System: Child Company Structure Managers Enabled'
|
||||
) == '1'
|
||||
) {
|
||||
$companyStructure = new CompanyStructure();
|
||||
$companyStructure->Load('id = ?', array($subordinate->department));
|
||||
|
||||
143
core/src/Classes/ExtensionManager.php
Normal file
143
core/src/Classes/ExtensionManager.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use Utils\LogManager;
|
||||
|
||||
class ExtensionManager
|
||||
{
|
||||
const GROUP = 'extension';
|
||||
protected function processExtensionInDB() {
|
||||
$dbModule = new \Modules\Common\Model\Module();
|
||||
$extensions = $dbModule->Find("mod_group = ?", array(self::GROUP));
|
||||
|
||||
$extensionsInDB = [];
|
||||
foreach ($extensions as $dbm) {
|
||||
$extensionsInDB[$dbm->name] = $dbm;
|
||||
ModuleAccessService::getInstance()->setModule($dbm->name, self::GROUP, $dbm);
|
||||
}
|
||||
|
||||
return $extensionsInDB;
|
||||
}
|
||||
|
||||
public function getExtensionsPath() {
|
||||
return APP_BASE_PATH.'../extensions/';
|
||||
}
|
||||
|
||||
public function getExtensionMetaData($extensionName)
|
||||
{
|
||||
return json_decode(file_get_contents($this->getExtensionsPath().$extensionName.'/meta.json'));
|
||||
}
|
||||
|
||||
public function setupExtensions() {
|
||||
$menu = [];
|
||||
$extensions = [];
|
||||
$extensionDirs = scandir($this->getExtensionsPath());
|
||||
$currentLocation = 0;
|
||||
|
||||
$extensionsInDB = $this->processExtensionInDB();
|
||||
|
||||
$needToInstall = false;
|
||||
|
||||
foreach ($extensionDirs as $extensionDir) {
|
||||
if (is_dir($this->getExtensionsPath().$extensionDir) && $extensionDir != '.' && $extensionDir != '..') {
|
||||
$meta = $this->getExtensionMetaData($extensionDir);
|
||||
|
||||
$arr = [];
|
||||
$arr['name'] = $extensionDir;
|
||||
$arr['label'] = $meta->label;
|
||||
$arr['icon'] = $meta->icon;
|
||||
$arr['menu'] = $meta->menu[0];
|
||||
$arr['order'] = 0;
|
||||
$arr['status'] = 'Enabled';
|
||||
$arr['user_levels'] = $meta->user_levels;
|
||||
$arr['user_roles'] = isset($meta->user_roles)?$meta->user_roles:"";
|
||||
$arr['model_namespace'] = $meta->model_namespace;
|
||||
$arr['manager'] = $meta->manager;
|
||||
|
||||
// Add menu
|
||||
$menu[$meta->menu[0]] = $meta->menu[1];
|
||||
|
||||
//Check in admin dbmodules
|
||||
if (isset($extensionsInDB[$arr['name']])) {
|
||||
$dbModule = $extensionsInDB[$arr['name']];
|
||||
|
||||
$arr['name'] = $dbModule->name;
|
||||
$arr['label'] = $dbModule->label;
|
||||
$arr['icon'] = $dbModule->icon;
|
||||
$arr['menu'] = $dbModule->menu;
|
||||
$arr['status'] = $dbModule->status;
|
||||
$arr['user_levels'] = json_decode($dbModule->user_levels);
|
||||
$arr['user_roles'] = empty($dbModule->user_roles)
|
||||
? [] : json_decode($dbModule->user_roles);
|
||||
$arr['user_roles_blacklist'] = empty($dbModule->user_roles_blacklist)
|
||||
? [] : json_decode($dbModule->user_roles_blacklist);
|
||||
} else {
|
||||
$dbModule = new \Modules\Common\Model\Module();
|
||||
$dbModule->menu = $arr['menu'];
|
||||
$dbModule->name = $arr['name'];
|
||||
$dbModule->label = $arr['label'];
|
||||
$dbModule->icon = $arr['icon'];
|
||||
$dbModule->mod_group = self::GROUP;
|
||||
$dbModule->mod_order = $arr['order'];
|
||||
$dbModule->status = "Enabled";
|
||||
$dbModule->version = isset($meta->version)?$meta->version:"";
|
||||
$dbModule->update_path = self::GROUP.">".$extensionDir;
|
||||
$dbModule->user_levels = isset($meta->user_levels)?json_encode($meta->user_levels):"";
|
||||
$dbModule->user_roles = isset($meta->user_roles)?json_encode($meta->user_roles):"";
|
||||
|
||||
$ok = $dbModule->Save();
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->error('Error saving module: '.$dbModule->name);
|
||||
}
|
||||
$needToInstall = $ok;
|
||||
}
|
||||
|
||||
/* @var \Classes\AbstractModuleManager */
|
||||
$manager = $this->includeModuleManager($extensionDir, $arr);
|
||||
if ($dbModule->status == 'Disabled') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($needToInstall) {
|
||||
$manager->install();
|
||||
}
|
||||
|
||||
$menuName = $arr['menu'];
|
||||
if (!isset($extensions[$menuName])) {
|
||||
$extensions[$menuName] = array();
|
||||
}
|
||||
|
||||
if (!$meta->headless) {
|
||||
if ($arr['order'] == '0' || $arr['order'] == '') {
|
||||
$extensions[$menuName]["Z".$currentLocation] = $arr;
|
||||
$currentLocation++;
|
||||
} else {
|
||||
$extensions[$arr['menu']]["A".$arr['order']] = $arr;
|
||||
}
|
||||
}
|
||||
|
||||
$initializer = $manager->getInitializer();
|
||||
if ($initializer !== null) {
|
||||
$initializer->setBaseService(BaseService::getInstance());
|
||||
$initializer->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$menu, $extensions];
|
||||
}
|
||||
|
||||
public function includeModuleManager($name, $data)
|
||||
{
|
||||
include($this->getExtensionsPath().$name.'/'.$name.'.php');
|
||||
$moduleManagerClass = $data['manager'];
|
||||
/* @var \Classes\AbstractModuleManager $moduleManagerObj*/
|
||||
$moduleManagerObj = new $moduleManagerClass();
|
||||
$moduleManagerObj->setModuleObject($data);
|
||||
$moduleManagerObj->setModuleType(self::GROUP);
|
||||
$moduleManagerObj->setModulePath(CLIENT_PATH.'/'.self::GROUP.'/'.$name);
|
||||
\Classes\BaseService::getInstance()->addModuleManager($moduleManagerObj);
|
||||
return $moduleManagerObj;
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,8 @@ class FileService
|
||||
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
|
||||
$result = $s3FileSys->putObject($s3Bucket, $uploadname, $localFile, 'authenticated-read');
|
||||
|
||||
$file->size = filesize($localFile);
|
||||
|
||||
unlink("/tmp/".$file->filename);
|
||||
unlink("/tmp/".$file->filename."_orig");
|
||||
|
||||
@@ -101,7 +103,6 @@ class FileService
|
||||
|
||||
$file->employee = $profileImage->employee;
|
||||
$file->file_group = 'profile_image_small';
|
||||
$file->size = filesize(CLIENT_BASE_PATH.'data/'.$file->filename);
|
||||
$file->size_text = $this->getReadableSize($file->size);
|
||||
|
||||
if (!empty($result)) {
|
||||
@@ -293,8 +294,7 @@ class FileService
|
||||
if ($file->employee == $profileId) {
|
||||
$ok = $file->Delete();
|
||||
if ($ok) {
|
||||
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
|
||||
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
|
||||
$this->deleteFileFromDisk($file);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -306,8 +306,7 @@ class FileService
|
||||
if ($file->employee == $profileId) {
|
||||
$ok = $file->Delete();
|
||||
if ($ok) {
|
||||
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
|
||||
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
|
||||
$this->deleteFileFromDisk($file);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -317,6 +316,30 @@ class FileService
|
||||
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)
|
||||
{
|
||||
LogManager::getInstance()->info("Delete file by field: $field / value: $value");
|
||||
|
||||
20
core/src/Classes/IceExtension.php
Normal file
20
core/src/Classes/IceExtension.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace Classes;
|
||||
|
||||
abstract class IceExtension extends AbstractModuleManager
|
||||
{
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
// TODO: Implement initializeUserClasses() method.
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
// TODO: Implement initializeFieldMappings() method.
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
// TODO: Implement initializeDatabaseErrorMappings() method.
|
||||
}
|
||||
}
|
||||
177
core/src/Classes/IceRoute.php
Executable file
177
core/src/Classes/IceRoute.php
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,8 @@ class Macaw
|
||||
array_push(self::$methods, strtoupper($method));
|
||||
array_push(self::$callbacks, $callback);
|
||||
|
||||
call_user_func('\Classes\IceRoute::'.$method, $params);
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace Classes\Migration;
|
||||
|
||||
use Utils\LogManager;
|
||||
|
||||
abstract class AbstractMigration
|
||||
{
|
||||
protected $file;
|
||||
@@ -16,7 +18,7 @@ abstract class AbstractMigration
|
||||
|
||||
protected $lastError;
|
||||
|
||||
public function __construct($file)
|
||||
public function __construct($file = null)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
@@ -50,6 +52,7 @@ abstract class AbstractMigration
|
||||
$ret = $this->db()->Execute($sql);
|
||||
if (!$ret) {
|
||||
$this->lastError = $this->db()->ErrorMsg();
|
||||
LogManager::getInstance()->error('Error in migration: '.$this->lastError);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class ModuleAccess
|
||||
* @param $name
|
||||
* @param $group
|
||||
*/
|
||||
public function __construct($name, $group)
|
||||
public function __construct($name, $group = 'extension')
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->group = $group;
|
||||
|
||||
@@ -420,6 +420,8 @@ class RestEndPoint
|
||||
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
|
||||
$token = $matches[1];
|
||||
}
|
||||
} else {
|
||||
$token = $_GET['token'];
|
||||
}
|
||||
|
||||
if (strlen($token) > 32) {
|
||||
|
||||
@@ -147,6 +147,10 @@ class EmployeesActionManager extends SubActionManager
|
||||
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);
|
||||
if ($passwordStrengthResponse->getStatus() === IceResponse::ERROR) {
|
||||
return $passwordStrengthResponse;
|
||||
@@ -158,6 +162,6 @@ class EmployeesActionManager extends SubActionManager
|
||||
return new IceResponse(IceResponse::ERROR, $user->ErrorMsg());
|
||||
}
|
||||
|
||||
return new IceResponse(IceResponse::SUCCESS, $user);
|
||||
return new IceResponse(IceResponse::SUCCESS, []);
|
||||
}
|
||||
}
|
||||
|
||||
1
extensions/gitkeep
Executable file
1
extensions/gitkeep
Executable file
@@ -0,0 +1 @@
|
||||
git keep
|
||||
13
extensions/tasks/meta.json
Normal file
13
extensions/tasks/meta.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"label": "My Tasks",
|
||||
"menu": ["Tasks", "fa-list"],
|
||||
"icon": "fa-tasks",
|
||||
"user_levels": [
|
||||
"Admin",
|
||||
"Manager",
|
||||
"User"
|
||||
],
|
||||
"model_namespace": "\\Tasks\\Model",
|
||||
"manager": "\\Tasks\\Extension",
|
||||
"headless": false
|
||||
}
|
||||
28
extensions/tasks/src/Tasks/Extension.php
Normal file
28
extensions/tasks/src/Tasks/Extension.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace Tasks;
|
||||
|
||||
use Classes\IceExtension;
|
||||
|
||||
class Extension extends IceExtension
|
||||
{
|
||||
|
||||
public function install() {
|
||||
$migration = new Migration();
|
||||
return $migration->up();
|
||||
}
|
||||
|
||||
public function uninstall() {
|
||||
$migration = new Migration();
|
||||
return $migration->down();
|
||||
}
|
||||
|
||||
public function setupModuleClassDefinitions()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function setupRestEndPoints()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
33
extensions/tasks/src/Tasks/Migration.php
Normal file
33
extensions/tasks/src/Tasks/Migration.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace Tasks;
|
||||
|
||||
use Classes\Migration\AbstractMigration;
|
||||
|
||||
class Migration extends AbstractMigration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$sql = <<<'SQL'
|
||||
create table `Tasks` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`employee` bigint(20) NULL,
|
||||
`name` varchar(250) NOT NULL,
|
||||
`description` TEXT NULL,
|
||||
`attachment` varchar(100) NULL,
|
||||
`created` DATETIME default NULL,
|
||||
`updated` DATETIME default NULL,
|
||||
primary key (`id`),
|
||||
CONSTRAINT `Fk_EmployeeTasks_Employees` FOREIGN KEY (`employee`) REFERENCES `Employees` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) engine=innodb default charset=utf8;
|
||||
SQL;
|
||||
return $this->executeQuery($sql);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$sql = <<<'SQL'
|
||||
DROP TABLE IF EXISTS `Tasks`;
|
||||
SQL;
|
||||
return $this->executeQuery($sql);
|
||||
}
|
||||
}
|
||||
38
extensions/tasks/src/Tasks/Model/Task.php
Normal file
38
extensions/tasks/src/Tasks/Model/Task.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Tasks\Model;
|
||||
|
||||
use Classes\ModuleAccess;
|
||||
use Model\BaseModel;
|
||||
|
||||
class Task extends BaseModel
|
||||
{
|
||||
public $table = 'Tasks';
|
||||
|
||||
public function getAdminAccess()
|
||||
{
|
||||
return ["get","element","save","delete"];
|
||||
}
|
||||
|
||||
public function getManagerAccess()
|
||||
{
|
||||
return ["get","element"];
|
||||
}
|
||||
|
||||
public function getUserAccess()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getAnonymousAccess()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getModuleAccess()
|
||||
{
|
||||
return [
|
||||
new ModuleAccess('tasks'),
|
||||
];
|
||||
}
|
||||
}
|
||||
4
extensions/tasks/tasks.php
Normal file
4
extensions/tasks/tasks.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
require_once __DIR__.'/src/Tasks/Extension.php';
|
||||
require_once __DIR__.'/src/Tasks/Migration.php';
|
||||
require_once __DIR__.'/src/Tasks/Model/Task.php';
|
||||
33
extensions/tasks/web/index.php
Normal file
33
extensions/tasks/web/index.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
$user = \Classes\BaseService::getInstance()->getCurrentUser();
|
||||
echo "Welcome ".$user->username."<br/>";
|
||||
|
||||
echo "Creating a task <br/>";
|
||||
|
||||
$task = new \Tasks\Model\Task();
|
||||
$taskName = 'Task-'.rand(rand(0, 100), 50000);
|
||||
|
||||
$task->name = $taskName;
|
||||
$task->employee = $user->employee;
|
||||
$task->description = $taskName.' description';
|
||||
$task->created = date('Y-m-d H:i:s');
|
||||
$task->updated = date('Y-m-d H:i:s');
|
||||
|
||||
/**
|
||||
* Saving the task, $ok will be false if there were any error during the creation
|
||||
*/
|
||||
$ok = $task->Save();
|
||||
|
||||
if (!$ok) {
|
||||
echo "Error: ".$task->ErrorMsg()." <br/>";
|
||||
}
|
||||
|
||||
echo "Find last task <br/>";
|
||||
|
||||
$taskFromDB = new \Tasks\Model\Task();
|
||||
/**
|
||||
* You can use load method to load the first matching task into an empty model
|
||||
*/
|
||||
$taskFromDB->Load('name = ?', [$taskName]);
|
||||
|
||||
var_dump($taskFromDB);
|
||||
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
42
gulpfile.js
42
gulpfile.js
@@ -359,6 +359,48 @@ gulp.task('modules-js', (done) => {
|
||||
.pipe(gulp.dest('./web/dist'));
|
||||
});
|
||||
|
||||
gulp.task('extension-js', (done) => {
|
||||
let extension = process.argv.filter((item) => item.substr(0, 3) === '--x');
|
||||
if (extension.length === 1) {
|
||||
extension = extension[0].substr(3);
|
||||
}
|
||||
|
||||
// map them to our stream function
|
||||
return browserify({
|
||||
entries: [`extensions/${extension}/web/js/index.js`],
|
||||
basedir: '.',
|
||||
debug: true,
|
||||
cache: {},
|
||||
packageCache: {},
|
||||
})
|
||||
.external(vendorsFlat)
|
||||
.transform('babelify', {
|
||||
plugins: [
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
],
|
||||
presets: ['@babel/preset-env', '@babel/preset-react'],
|
||||
extensions: ['.js', '.jsx'],
|
||||
})
|
||||
.transform(require('browserify-css'))
|
||||
.bundle()
|
||||
.pipe(source(`${extension}.js`))
|
||||
.pipe(buffer())
|
||||
.pipe(ifElse(!isProduction, () => sourcemaps.init({ loadMaps: true })))
|
||||
.pipe(ifElse(isProduction, () => uglifyes(
|
||||
{
|
||||
compress: true,
|
||||
mangle: {
|
||||
reserved: [],
|
||||
},
|
||||
},
|
||||
)))
|
||||
.pipe(ifElse(isProduction, () => javascriptObfuscator({
|
||||
compact: true,
|
||||
})))
|
||||
.pipe(ifElse(!isProduction, () => sourcemaps.write('./')))
|
||||
.pipe(gulp.dest(`./extensions/${extension}/dist`));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch('web/admin/src/*/*.js', gulp.series('admin-js'));
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<img src="web/images/logo-sq.png" align="right" />
|
||||
|
||||
IceHrm
|
||||
===========
|
||||
[](https://travis-ci.org/gamonoid/icehrm)
|
||||
|
||||
@@ -154,7 +154,7 @@ class EmployeeDocumentAdapter extends AdapterBase {
|
||||
|
||||
getFilters() {
|
||||
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'] }],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class AdapterBase extends ModuleBase {
|
||||
}
|
||||
|
||||
setupApiClient(token) {
|
||||
this.apiClient = new IceApiClient(this.apiUrl, token);
|
||||
this.apiClient = new IceApiClient(this.apiUrl, token, window.CLIENT_BASE_URL, true);
|
||||
}
|
||||
|
||||
setApiUrl(apiUrl) {
|
||||
|
||||
26
web/api/CustomAction.js
Normal file
26
web/api/CustomAction.js
Normal 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;
|
||||
@@ -1,12 +1,19 @@
|
||||
const axios = require('axios');
|
||||
|
||||
class IceApiClient {
|
||||
constructor(baseUrl, token) {
|
||||
constructor(baseUrl, token, clientBaseUrl, legacyApiWrapper = true) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.token = token;
|
||||
this.clientBaseUrl = clientBaseUrl;
|
||||
this.legacyApiWrapper = legacyApiWrapper;
|
||||
}
|
||||
|
||||
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, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
|
||||
@@ -61,10 +61,10 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Some browsers do not support sending JSON in get parameters. Set this to true to avoid sending JSON
|
||||
* @method setNoJSONRequests
|
||||
* @param val {Boolean}
|
||||
*/
|
||||
* Some browsers do not support sending JSON in get parameters. Set this to true to avoid sending JSON
|
||||
* @method setNoJSONRequests
|
||||
* @param val {Boolean}
|
||||
*/
|
||||
setNoJSONRequests(val) {
|
||||
this.noJSONRequests = val;
|
||||
}
|
||||
@@ -79,12 +79,12 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user has a permission
|
||||
* @method checkPermission
|
||||
* @param permission {String}
|
||||
* @example
|
||||
* this.checkPermission("Upload/Delete Profile Image")
|
||||
*/
|
||||
* Check if the current user has a permission
|
||||
* @method checkPermission
|
||||
* @param permission {String}
|
||||
* @example
|
||||
* this.checkPermission("Upload/Delete Profile Image")
|
||||
*/
|
||||
checkPermission(permission) {
|
||||
if (this.permissions[permission] === undefined || this.permissions[permission] == null || this.permissions[permission] === '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.
|
||||
* Override this method in module lib.js to hide action buttons
|
||||
* @method showActionButtons
|
||||
* @param permission {String}
|
||||
* @example
|
||||
* EmployeeLeaveEntitlementAdapter.method('showActionButtons() {
|
||||
* return false;
|
||||
* }
|
||||
*/
|
||||
* 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
|
||||
* @method showActionButtons
|
||||
* @param permission {String}
|
||||
* @example
|
||||
* EmployeeLeaveEntitlementAdapter.method('showActionButtons() {
|
||||
* return false;
|
||||
* }
|
||||
*/
|
||||
showActionButtons() {
|
||||
return true;
|
||||
}
|
||||
@@ -201,30 +201,30 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current profile
|
||||
* @method getCurrentProfile
|
||||
* @returns Profile of the current user if the profile is not switched if not switched profile
|
||||
*/
|
||||
* Get the current profile
|
||||
* @method getCurrentProfile
|
||||
* @returns Profile of the current user if the profile is not switched if not switched profile
|
||||
*/
|
||||
|
||||
getCurrentProfile() {
|
||||
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
|
||||
* @method initFieldMasterData
|
||||
* @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
|
||||
* @example
|
||||
* ReportAdapter.method('renderForm(object) {
|
||||
* var that = this;
|
||||
* this.processFormFieldsWithObject(object);
|
||||
* var cb = function(){
|
||||
* that.super.renderForm(object);
|
||||
* };
|
||||
* this.initFieldMasterData(cb);
|
||||
* }
|
||||
*/
|
||||
* 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
|
||||
* @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
|
||||
* @example
|
||||
* ReportAdapter.method('renderForm(object) {
|
||||
* var that = this;
|
||||
* this.processFormFieldsWithObject(object);
|
||||
* var cb = function(){
|
||||
* that.super.renderForm(object);
|
||||
* };
|
||||
* this.initFieldMasterData(cb);
|
||||
* }
|
||||
*/
|
||||
initFieldMasterData(callback, loadAllCallback, loadAllCallbackData) {
|
||||
this.fieldMasterData = {};
|
||||
this.fieldMasterDataKeys = {};
|
||||
@@ -236,10 +236,11 @@ class ModuleBase {
|
||||
for (let i = 0; i < remoteSourceFields.length; i++) {
|
||||
const fieldRemote = remoteSourceFields[i];
|
||||
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]}`;
|
||||
if (fieldRemote[1]['remote-source'].length === 4) {
|
||||
key = `${key}_${fieldRemote[1]['remote-source'][3]}`;
|
||||
}
|
||||
// let key = `${fieldRemote[1]['remote-source'][0]}_${fieldRemote[1]['remote-source'][1]}_${fieldRemote[1]['remote-source'][2]}`;
|
||||
// if (fieldRemote[1]['remote-source'].length === 4) {
|
||||
// key = `${key}_${fieldRemote[1]['remote-source'][3]}`;
|
||||
// }
|
||||
const key = this.getRemoteSourceKey(fieldRemote);
|
||||
this.fieldMasterDataKeys[key] = false;
|
||||
|
||||
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.
|
||||
* @method setShowFormOnPopup
|
||||
* @param val {Boolean}
|
||||
* @example
|
||||
* modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id}
|
||||
* modJs.subModJsList['tabCandidateApplication'].setShowFormOnPopup(true);
|
||||
*/
|
||||
* Pass true to this method after creating module JS object to open new/edit entry form for the module on a popup.
|
||||
* @method setShowFormOnPopup
|
||||
* @param val {Boolean}
|
||||
* @example
|
||||
* modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id}
|
||||
* modJs.subModJsList['tabCandidateApplication'].setShowFormOnPopup(true);
|
||||
*/
|
||||
|
||||
setShowFormOnPopup(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.
|
||||
* @method setRemoteTable
|
||||
* @param val {Boolean}
|
||||
* @example
|
||||
* modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id}
|
||||
* modJs.subModJsList['tabCandidateApplication'].setRemoteTable(true);
|
||||
*/
|
||||
* 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
|
||||
* @param val {Boolean}
|
||||
* @example
|
||||
* modJs.subModJsList['tabCandidateApplication'] = new CandidateApplicationAdapter('Application','CandidateApplication',{"candidate":data.id}
|
||||
* modJs.subModJsList['tabCandidateApplication'].setRemoteTable(true);
|
||||
*/
|
||||
|
||||
setRemoteTable(val) {
|
||||
this.createRemoteTable = val;
|
||||
@@ -372,14 +373,14 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
if (this.fieldMasterDataCallback !== null
|
||||
&& this.fieldMasterDataCallback !== undefined
|
||||
&& this.isAllLoaded(this.fieldMasterDataKeys)
|
||||
&& (this.fieldMasterDataCallbackData !== null && this.fieldMasterDataCallbackData !== undefined)
|
||||
&& this.fieldMasterDataCallback !== undefined
|
||||
&& this.isAllLoaded(this.fieldMasterDataKeys)
|
||||
&& (this.fieldMasterDataCallbackData !== null && this.fieldMasterDataCallbackData !== undefined)
|
||||
) {
|
||||
this.fieldMasterDataCallback(this.fieldMasterDataCallbackData);
|
||||
} else if (this.fieldMasterDataCallback !== null
|
||||
&& this.fieldMasterDataCallback !== undefined
|
||||
&& this.isAllLoaded(this.fieldMasterDataKeys)
|
||||
&& this.fieldMasterDataCallback !== undefined
|
||||
&& this.isAllLoaded(this.fieldMasterDataKeys)
|
||||
) {
|
||||
this.fieldMasterDataCallback();
|
||||
}
|
||||
@@ -597,10 +598,10 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the data table on provided element id
|
||||
* @method createTable
|
||||
* @param val {Boolean}
|
||||
*/
|
||||
* Create the data table on provided element id
|
||||
* @method createTable
|
||||
* @param val {Boolean}
|
||||
*/
|
||||
|
||||
createTable(elementId) {
|
||||
const that = this;
|
||||
@@ -678,10 +679,10 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a data table on provided element id which loads data page by page
|
||||
* @method createTableServer
|
||||
* @param val {Boolean}
|
||||
*/
|
||||
* Create a data table on provided element id which loads data page by page
|
||||
* @method createTableServer
|
||||
* @param val {Boolean}
|
||||
*/
|
||||
|
||||
createTableServer(elementId) {
|
||||
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.
|
||||
* @method getHeaders
|
||||
* @example
|
||||
SettingAdapter.method('getHeaders() {
|
||||
* This should be overridden in module lib.js classes to return module headers which are used to create the data table.
|
||||
* @method getHeaders
|
||||
* @example
|
||||
SettingAdapter.method('getHeaders() {
|
||||
return [
|
||||
{ "sTitle": "ID" ,"bVisible":false},
|
||||
{ "sTitle": "Name" },
|
||||
@@ -759,17 +760,17 @@ class ModuleBase {
|
||||
{ "sTitle": "Details"}
|
||||
];
|
||||
}
|
||||
*/
|
||||
*/
|
||||
getHeaders() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This should be overridden in module lib.js classes to return module field values which are used to create the data table.
|
||||
* @method getDataMapping
|
||||
* @example
|
||||
SettingAdapter.method('getDataMapping() {
|
||||
* This should be overridden in module lib.js classes to return module field values which are used to create the data table.
|
||||
* @method getDataMapping
|
||||
* @example
|
||||
SettingAdapter.method('getDataMapping() {
|
||||
return [
|
||||
"id",
|
||||
"name",
|
||||
@@ -777,23 +778,23 @@ class ModuleBase {
|
||||
"description"
|
||||
];
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
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.
|
||||
* @method getFormFields
|
||||
* @example
|
||||
SettingAdapter.method('getFormFields() {
|
||||
* 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
|
||||
* @example
|
||||
SettingAdapter.method('getFormFields() {
|
||||
return [
|
||||
[ "id", {"label":"ID","type":"hidden"}],
|
||||
[ "value", {"label":"Value","type":"text","validation":"none"}]
|
||||
];
|
||||
}
|
||||
*/
|
||||
*/
|
||||
getFormFields() {
|
||||
|
||||
}
|
||||
@@ -807,26 +808,26 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be overridden in module lib.js classes inorder to show a filter form
|
||||
* @method getFilters
|
||||
* @example
|
||||
EmployeeAdapter.method('getFilters() {
|
||||
* This can be overridden in module lib.js classes inorder to show a filter form
|
||||
* @method getFilters
|
||||
* @example
|
||||
EmployeeAdapter.method('getFilters() {
|
||||
return [
|
||||
[ "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"]}],
|
||||
[ "supervisor", {"label":"Supervisor","type":"select2","allow-null":true,"null-label":"Anyone","remote-source":["Employee","id","first_name+last_name"]}]
|
||||
];
|
||||
}
|
||||
*/
|
||||
*/
|
||||
getFilters() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the edit form for an item
|
||||
* @method edit
|
||||
* @param id {int} id of the item to edit
|
||||
*/
|
||||
* Show the edit form for an item
|
||||
* @method edit
|
||||
* @param id {int} id of the item to edit
|
||||
*/
|
||||
edit(id) {
|
||||
this.currentId = id;
|
||||
this.getElement(id, []);
|
||||
@@ -890,10 +891,10 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an item
|
||||
* @method deleteRow
|
||||
* @param id {int} id of the item to edit
|
||||
*/
|
||||
* Delete an item
|
||||
* @method deleteRow
|
||||
* @param id {int} id of the item to edit
|
||||
*/
|
||||
|
||||
deleteRow(id) {
|
||||
this.deleteParams.id = id;
|
||||
@@ -902,17 +903,17 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a popup with message
|
||||
* @method showMessage
|
||||
* @param title {String} title of the message box
|
||||
* @param message {String} message
|
||||
* @param closeCallback {Function} this will be called once the dialog is closed (optional)
|
||||
* @param closeCallback {Function} data to pass to close callback (optional)
|
||||
* @param closeCallbackData
|
||||
* @param isPlain {Boolean} if true buttons are not shown (optional / default = true)
|
||||
* @example
|
||||
* this.showMessage("Error Occured while Applying Leave", callBackData);
|
||||
*/
|
||||
* Show a popup with message
|
||||
* @method showMessage
|
||||
* @param title {String} title of the message box
|
||||
* @param message {String} message
|
||||
* @param closeCallback {Function} this will be called once the dialog is closed (optional)
|
||||
* @param closeCallback {Function} data to pass to close callback (optional)
|
||||
* @param closeCallbackData
|
||||
* @param isPlain {Boolean} if true buttons are not shown (optional / default = true)
|
||||
* @example
|
||||
* this.showMessage("Error Occured while Applying Leave", callBackData);
|
||||
*/
|
||||
showMessage(title, message, closeCallback = null, closeCallbackData = null, isPlain = false) {
|
||||
const that = this;
|
||||
let modelId = '';
|
||||
@@ -1005,11 +1006,11 @@ class ModuleBase {
|
||||
|
||||
|
||||
/**
|
||||
* Create or edit an element
|
||||
* @method save
|
||||
* @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
|
||||
*/
|
||||
* Create or edit an element
|
||||
* @method save
|
||||
* @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
|
||||
*/
|
||||
|
||||
save(callGetFunction, successCallback) {
|
||||
const validator = new FormValidation(`${this.getTableName()}_submit`, true, { ShowPopup: false, LabelErrorClass: 'error' });
|
||||
@@ -1040,7 +1041,7 @@ class ModuleBase {
|
||||
const fields = this.getFormFields();
|
||||
fields.forEach((field) => {
|
||||
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') {
|
||||
params[field[0]] = 'NULL';
|
||||
} else {
|
||||
@@ -1084,23 +1085,23 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to inject attitional parameters or modify existing parameters retrived from
|
||||
* add/edit form before sending to the server
|
||||
* @method forceInjectValuesBeforeSave
|
||||
* @param params {Array} keys and values in form
|
||||
* @returns {Array} modified parameters
|
||||
*/
|
||||
* Override this method to inject attitional parameters or modify existing parameters retrived from
|
||||
* add/edit form before sending to the server
|
||||
* @method forceInjectValuesBeforeSave
|
||||
* @param params {Array} keys and values in form
|
||||
* @returns {Array} modified parameters
|
||||
*/
|
||||
forceInjectValuesBeforeSave(params) {
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to do custom validations at client side
|
||||
* @method doCustomValidation
|
||||
* @param params {Array} keys and values in form
|
||||
* @returns {Null or String} return null if validation success, returns error message if unsuccessful
|
||||
* @example
|
||||
EmployeeLeaveAdapter.method('doCustomValidation(params) {
|
||||
* Override this method to do custom validations at client side
|
||||
* @method doCustomValidation
|
||||
* @param params {Array} keys and values in form
|
||||
* @returns {Null or String} return null if validation success, returns error message if unsuccessful
|
||||
* @example
|
||||
EmployeeLeaveAdapter.method('doCustomValidation(params) {
|
||||
try{
|
||||
if(params['date_start'] != params['date_end']){
|
||||
var ds = new Date(params['date_start']);
|
||||
@@ -1114,7 +1115,7 @@ class ModuleBase {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
doCustomValidation(params) {
|
||||
return null;
|
||||
@@ -1177,7 +1178,12 @@ class ModuleBase {
|
||||
value = 'Not Selected';
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
} else {
|
||||
@@ -1231,20 +1237,20 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to do custom validations at client side for values selected in filters
|
||||
* @method doCustomFilterValidation
|
||||
* @param params {Array} keys and values in form
|
||||
* @returns {Null or String} return null if validation success, returns error message if unsuccessful
|
||||
*/
|
||||
* Override this method to do custom validations at client side for values selected in filters
|
||||
* @method doCustomFilterValidation
|
||||
* @param params {Array} keys and values in form
|
||||
* @returns {Null or String} return null if validation success, returns error message if unsuccessful
|
||||
*/
|
||||
doCustomFilterValidation(params) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset selected filters
|
||||
* @method resetFilters
|
||||
*/
|
||||
* Reset selected filters
|
||||
* @method resetFilters
|
||||
*/
|
||||
|
||||
resetFilters() {
|
||||
this.filter = this.origFilter;
|
||||
@@ -1332,7 +1338,8 @@ class ModuleBase {
|
||||
try {
|
||||
modJs.filterQuery();
|
||||
} catch (err) {
|
||||
// Do Nothing
|
||||
console.log(err);
|
||||
console.log(err.message);
|
||||
}
|
||||
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
|
||||
* @method preRenderForm
|
||||
* @param object {Array} keys value list for populating form
|
||||
*/
|
||||
* Override this method in your module class to make changes to data fo the form before showing the form
|
||||
* @method preRenderForm
|
||||
* @param object {Array} keys value list for populating form
|
||||
*/
|
||||
|
||||
preRenderForm(object) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the form
|
||||
* @method renderForm
|
||||
* @param object {Array} keys value list for populating form
|
||||
*/
|
||||
* Create the form
|
||||
* @method renderForm
|
||||
* @param object {Array} keys value list for populating form
|
||||
*/
|
||||
|
||||
renderForm(object) {
|
||||
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
|
||||
* @method postRenderForm
|
||||
* @param object {Array} keys value list for populating form
|
||||
* @param $tempDomObj {DOM} a DOM element for the form
|
||||
* @example
|
||||
* UserAdapter.method('postRenderForm(object, $tempDomObj) {
|
||||
* Override this method in your module class to make changes to data fo the form after showing it
|
||||
* @method postRenderForm
|
||||
* @param object {Array} keys value list for populating form
|
||||
* @param $tempDomObj {DOM} a DOM element for the form
|
||||
* @example
|
||||
* UserAdapter.method('postRenderForm(object, $tempDomObj) {
|
||||
if(object == null || object == undefined){
|
||||
$tempDomObj.find("#changePasswordBtn").remove();
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
postRenderForm(object, $tempDomObj) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert data group field to HTML
|
||||
* @method dataGroupToHtml
|
||||
* @param val {String} value in the field
|
||||
* @param field {Array} field meta data
|
||||
*/
|
||||
* Convert data group field to HTML
|
||||
* @method dataGroupToHtml
|
||||
* @param val {String} value in the field
|
||||
* @param field {Array} field meta data
|
||||
*/
|
||||
|
||||
dataGroupToHtml(val, field) {
|
||||
const data = JSON.parse(val);
|
||||
@@ -1657,10 +1664,10 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the DataGroup for a given field
|
||||
* @method resetDataGroup
|
||||
* @param field {Array} field meta data
|
||||
*/
|
||||
* Reset the DataGroup for a given field
|
||||
* @method resetDataGroup
|
||||
* @param field {Array} field meta data
|
||||
*/
|
||||
resetDataGroup(field) {
|
||||
$(`#${field[0]}`).val('');
|
||||
$(`#${field[0]}_div`).html('');
|
||||
@@ -2054,12 +2061,12 @@ class ModuleBase {
|
||||
|
||||
|
||||
/**
|
||||
* Fill a form with required values after showing it
|
||||
* @method fillForm
|
||||
* @param object {Array} form data
|
||||
* @param formId {String} id of the form
|
||||
* @param formId {Array} field meta data
|
||||
*/
|
||||
* Fill a form with required values after showing it
|
||||
* @method fillForm
|
||||
* @param object {Array} form data
|
||||
* @param formId {String} id of the form
|
||||
* @param formId {Array} field meta data
|
||||
*/
|
||||
|
||||
fillForm(object, formId, fields) {
|
||||
let placeHolderVal;
|
||||
@@ -2094,7 +2101,8 @@ class ModuleBase {
|
||||
$(`${formId} #${fields[i][0]}`).html(object[fields[i][0]]);
|
||||
} else if (fields[i][1].type === 'placeholder') {
|
||||
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]]];
|
||||
} else {
|
||||
placeHolderVal = object[fields[i][0]];
|
||||
@@ -2172,7 +2180,7 @@ class ModuleBase {
|
||||
}
|
||||
} else if (fields[i][1].type === 'signature') {
|
||||
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]]);
|
||||
}
|
||||
} else if (fields[i][1].type === 'simplemde') {
|
||||
@@ -2189,9 +2197,9 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel edit or add new on modules
|
||||
* @method cancel
|
||||
*/
|
||||
* Cancel edit or add new on modules
|
||||
* @method cancel
|
||||
*/
|
||||
|
||||
cancel() {
|
||||
$(`#${this.getTableName()}Form`).hide();
|
||||
@@ -2218,10 +2226,11 @@ class ModuleBase {
|
||||
if (field[1].source !== undefined && field[1].source != null) {
|
||||
t = t.replace('_options_', this.renderFormSelectOptions(field[1].source, field));
|
||||
} 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]}`;
|
||||
if (field[1]['remote-source'].length === 4) {
|
||||
key = `${key}_${field[1]['remote-source'][3]}`;
|
||||
}
|
||||
// let key = `${field[1]['remote-source'][0]}_${field[1]['remote-source'][1]}_${field[1]['remote-source'][2]}`;
|
||||
// if (field[1]['remote-source'].length === 4) {
|
||||
// key = `${key}_${field[1]['remote-source'][3]}`;
|
||||
// }
|
||||
const key = this.getRemoteSourceKey(field);
|
||||
t = t.replace('_options_', this.renderFormSelectOptionsRemote(this.fieldMasterData[key], field));
|
||||
}
|
||||
} else if (field[1].type === 'colorpick') {
|
||||
@@ -2413,49 +2422,49 @@ class ModuleBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to change add new button label
|
||||
* @method getAddNewLabel
|
||||
*/
|
||||
* Override this method to change add new button label
|
||||
* @method getAddNewLabel
|
||||
*/
|
||||
|
||||
getAddNewLabel() {
|
||||
return 'Add New';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set whether to show the add new button for a module
|
||||
* @method setShowAddNew
|
||||
* @param showAddNew {Boolean} value
|
||||
*/
|
||||
* Used to set whether to show the add new button for a module
|
||||
* @method setShowAddNew
|
||||
* @param showAddNew {Boolean} value
|
||||
*/
|
||||
|
||||
setShowAddNew(showAddNew) {
|
||||
this.showAddNew = showAddNew;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set whether to show delete button for each entry in module
|
||||
* @method setShowDelete
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
* Used to set whether to show delete button for each entry in module
|
||||
* @method setShowDelete
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
setShowDelete(val) {
|
||||
this.showDelete = val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used to set whether to show edit button for each entry in module
|
||||
* @method setShowEdit
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
* Used to set whether to show edit button for each entry in module
|
||||
* @method setShowEdit
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
|
||||
setShowEdit(val) {
|
||||
this.showEdit = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set whether to show save button in form
|
||||
* @method setShowSave
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
* Used to set whether to show save button in form
|
||||
* @method setShowSave
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
|
||||
|
||||
setShowSave(val) {
|
||||
@@ -2464,20 +2473,20 @@ class ModuleBase {
|
||||
|
||||
|
||||
/**
|
||||
* Used to set whether to show cancel button in form
|
||||
* @method setShowCancel
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
* Used to set whether to show cancel button in form
|
||||
* @method setShowCancel
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
|
||||
setShowCancel(val) {
|
||||
this.showCancel = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Datatable option array will be extended with associative array provided here
|
||||
* @method getCustomTableParams
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
* Datatable option array will be extended with associative array provided here
|
||||
* @method getCustomTableParams
|
||||
* @param val {Boolean} value
|
||||
*/
|
||||
|
||||
|
||||
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.
|
||||
* @method getActionButtonsHtml
|
||||
* @param id {int} id of the row
|
||||
* @param data {Array} data for the row
|
||||
* @returns {String} html for 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
|
||||
* @param id {int} id of the row
|
||||
* @param data {Array} data for the row
|
||||
* @returns {String} html for action buttons
|
||||
*/
|
||||
|
||||
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>';
|
||||
@@ -2528,11 +2537,11 @@ class ModuleBase {
|
||||
|
||||
|
||||
/**
|
||||
* Generates a random string
|
||||
* @method generateRandom
|
||||
* @param length {int} required length of the string
|
||||
* @returns {String} random string
|
||||
*/
|
||||
* Generates a random string
|
||||
* @method generateRandom
|
||||
* @param length {int} required length of the string
|
||||
* @returns {String} random string
|
||||
*/
|
||||
|
||||
generateRandom(length) {
|
||||
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.
|
||||
* @method getHelpLink
|
||||
* @returns {String} help link
|
||||
*/
|
||||
* 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
|
||||
* @returns {String} help link
|
||||
*/
|
||||
|
||||
getHelpLink() {
|
||||
return null;
|
||||
|
||||
232
web/components/UpdatePasswordModal.js
Normal file
232
web/components/UpdatePasswordModal.js
Normal 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;
|
||||
@@ -943,3 +943,7 @@ table.dataTable{
|
||||
.table-row-dark {
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
|
||||
.mod-tab {
|
||||
margin-bottom:0px;margin-left:5px;border-bottom: none;
|
||||
}
|
||||
|
||||
30987
web/dist/admin-bundle.js
vendored
30987
web/dist/admin-bundle.js
vendored
File diff suppressed because one or more lines are too long
4
web/dist/common.js
vendored
4
web/dist/common.js
vendored
File diff suppressed because one or more lines are too long
4
web/dist/modules-bundle.js
vendored
4
web/dist/modules-bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,37 +1,32 @@
|
||||
import React, {Component} from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
Col,
|
||||
Card,
|
||||
Badge,
|
||||
Avatar,
|
||||
Input,
|
||||
Row,
|
||||
Descriptions,
|
||||
Typography,
|
||||
Table,
|
||||
Space,
|
||||
Button,
|
||||
Tag,
|
||||
message,
|
||||
Tabs,
|
||||
Spin,
|
||||
Skeleton
|
||||
} from 'antd';
|
||||
import {
|
||||
FilterOutlined,
|
||||
EditOutlined,
|
||||
PhoneTwoTone,
|
||||
MailTwoTone,
|
||||
SyncOutlined,
|
||||
LockOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import TagList from "../../../../components/TagList";
|
||||
const { Search } = Input;
|
||||
import UpdatePasswordModal from "../../../../components/UpdatePasswordModal";
|
||||
const { Title, Text } = Typography;
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
class EmployeeProfile extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
showPasswordResetModal: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@@ -42,6 +37,10 @@ class EmployeeProfile extends React.Component {
|
||||
this.setState({ loading: value });
|
||||
}
|
||||
|
||||
setShowPasswordUpdate(value) {
|
||||
this.setState({ showPasswordResetModal: value });
|
||||
}
|
||||
|
||||
updateProfileImage() {
|
||||
showUploadDialog(
|
||||
`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) {
|
||||
return (
|
||||
<Tag icon={<EditOutlined/>} color="processing"
|
||||
@@ -86,10 +112,15 @@ class EmployeeProfile extends React.Component {
|
||||
}
|
||||
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}>
|
||||
<Col span={24}>
|
||||
<Card title={this.props.adapter.gt('Employee Profile')}
|
||||
extra={this.getEditButtonJsx()}
|
||||
extra={this.getEditButtonJsxWithPassword()}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Space size={'large'}>
|
||||
|
||||
@@ -613,8 +613,15 @@ class EmployeeTimeEntryAdapter extends AdapterBase {
|
||||
return dateArray;
|
||||
}
|
||||
|
||||
|
||||
renderForm(object) {
|
||||
this.initMasterDataReader();
|
||||
this.masterDataReader.updateAllMasterData()
|
||||
.then(() => {
|
||||
this._renderForm(object);
|
||||
});
|
||||
}
|
||||
|
||||
_renderForm(object) {
|
||||
let formHtml = this.getCustomTemplate('time_entry_form.html');
|
||||
formHtml = formHtml.replace(/modJs/g, "modJsList['tabEmployeeTimeEntry']");
|
||||
let html = '';
|
||||
|
||||
Reference in New Issue
Block a user