first commit

This commit is contained in:
BACHIR SOULDI
2025-09-28 08:49:37 +01:00
commit 2794e62571
16819 changed files with 2664196 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
{*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************}
{* modules/Settings/SharingAccess/views/IndexAjax.php *}
{* START YOUR IMPLEMENTATION FROM BELOW. Use {debug} for information *}
{strip}
{assign var=RULE_MODEL_EXISTS value=true}
{assign var=RULE_ID value=$RULE_MODEL->getId()}
{if empty($RULE_ID)}
{assign var=RULE_MODEL_EXISTS value=false}
{/if}
<div class="modal-dialog modelContainer"'>
{assign var=HEADER_TITLE value={vtranslate('LBL_ADD_CUSTOM_RULE_TO', $QUALIFIED_MODULE)}|cat:" "|cat:{vtranslate($MODULE_MODEL->get('name'), $MODULE)}}
{include file="ModalHeader.tpl"|vtemplate_path:$MODULE TITLE=$HEADER_TITLE}
<div class="modal-content">
<form class="form-horizontal" id="editCustomRule" method="post">
<input type="hidden" name="for_module" value="{$MODULE_MODEL->get('name')}" />
<input type="hidden" name="record" value="{$RULE_ID}" />
<div name='massEditContent'>
<div class="modal-body">
<div class="form-group">
<label class="control-label fieldLabel col-sm-5">{vtranslate($MODULE_MODEL->get('name'), $MODULE)}&nbsp;{vtranslate('LBL_OF', $MODULE)}</label>
<div class="controls fieldValue col-xs-6">
<select class="select2 col-sm-9" name="source_id">
{foreach from=$ALL_RULE_MEMBERS key=GROUP_LABEL item=ALL_GROUP_MEMBERS}
<optgroup label="{vtranslate($GROUP_LABEL, $QUALIFIED_MODULE)}">
{foreach from=$ALL_GROUP_MEMBERS item=MEMBER}
<option value="{$MEMBER->getId()}"
{if $RULE_MODEL_EXISTS} {if $RULE_MODEL->getSourceMember()->getId() == $MEMBER->getId()}selected{/if}{/if}>
{$MEMBER->getName()}
</option>
{/foreach}
</optgroup>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label fieldLabel col-sm-5">{vtranslate('LBL_CAN_ACCESSED_BY', $QUALIFIED_MODULE)}</label>
<div class="controls fieldValue col-xs-6">
<select class="select2 col-sm-9" name="target_id">
{foreach from=$ALL_RULE_MEMBERS key=GROUP_LABEL item=ALL_GROUP_MEMBERS}
<optgroup label="{vtranslate($GROUP_LABEL, $QUALIFIED_MODULE)}">
{foreach from=$ALL_GROUP_MEMBERS item=MEMBER}
<option value="{$MEMBER->getId()}"
{if $RULE_MODEL_EXISTS}{if $RULE_MODEL->getTargetMember()->getId() == $MEMBER->getId()}selected{/if}{/if}>
{$MEMBER->getName()}
</option>
{/foreach}
</optgroup>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label fieldLabel col-sm-5">{vtranslate('LBL_WITH_PERMISSIONS', $QUALIFIED_MODULE)}</label>
<div class="controls fieldValue col-sm-5" style="margin-left: 3%;">
<label class="radio">
<input type="radio" value="0" name="permission" {if $RULE_MODEL_EXISTS} {if $RULE_MODEL->isReadOnly()} checked {/if} {else} checked {/if}/>&nbsp;{vtranslate('LBL_READ', $QUALIFIED_MODULE)}&nbsp;
</label>
<label class="radio">
<input type="radio" value="1" name="permission" {if $RULE_MODEL->isReadWrite()} checked {/if} />&nbsp;{vtranslate('LBL_READ_WRITE', $QUALIFIED_MODULE)}&nbsp;
</label>
</div>
</div>
</div>
</div>
{include file='ModalFooter.tpl'|@vtemplate_path:$MODULE}
</form>
</div>
</div>
{/strip}

View File

@@ -0,0 +1,110 @@
{*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************}
{* modules/Settings/SharingAccess/views/Index.php *}
{* START YOUR IMPLEMENTATION FROM BELOW. Use {debug} for information *}
{strip}
<div class="listViewPageDiv " id="sharingAccessContainer">
<div class="col-sm-12 col-xs-12">
<form name="EditSharingAccess" action="index.php" method="post" class="form-horizontal" id="EditSharingAccess">
<input type="hidden" name="module" value="SharingAccess" />
<input type="hidden" name="action" value="SaveAjax" />
<input type="hidden" name="parent" value="Settings" />
<input type="hidden" class="dependentModules" value='{ZEND_JSON::encode($DEPENDENT_MODULES)}' />
<br>
<div class="contents">
<table class="table table-bordered table-condensed sharingAccessDetails marginBottom50px">
<colgroup>
<col width="20%">
<col width="15%">
<col width="15%">
<col width="20%">
<col width="10%">
<col width="20%">
</colgroup>
<thead>
<tr class="blockHeader">
<th>
{vtranslate('LBL_MODULE', $QUALIFIED_MODULE)}
</th>
{foreach from=$ALL_ACTIONS key=ACTION_ID item=ACTION_MODEL}
<th>
{$ACTION_MODEL->getName()|vtranslate:$QUALIFIED_MODULE}
</th>
{/foreach}
<th nowrap="nowrap">{'LBL_ADVANCED_SHARING_RULES'|vtranslate:$QUALIFIED_MODULE}</th>
</tr>
</thead>
<tbody>
<tr data-module-name="Calendar">
<td>{'SINGLE_Calendar'|vtranslate:'Calendar'}</td>
<td class="">
<center><div><input type="radio" disabled="disabled" /></div></center>
</td>
<td class="">
<center><div><input type="radio" disabled="disabled" /></div></center>
</td>
<td class="">
<center><div><input type="radio" disabled="disabled" /></div></center>
</td>
<td class="">
<center><div><input type="radio" checked="true" disabled="disabled" /></div></center>
</td>
<td>
<div class="row">
<span class="col-sm-4">&nbsp;</span>
<span class="col-sm-4">
<button type="button" class="btn btn-sm btn-default vtButton arrowDown row-fluid" disabled="disabled" style="padding-right: 20px; padding-left: 20px;">
<i class="fa fa-chevron-down"></i>
</button>
</span>
</div>
</td>
</tr>
{foreach from=$ALL_MODULES key=TABID item=MODULE_MODEL}
<tr data-module-name="{$MODULE_MODEL->get('name')}">
<td>
{$MODULE_MODEL->get('label')|vtranslate:$MODULE_MODEL->getName()}
</td>
{foreach from=$ALL_ACTIONS key=ACTION_ID item=ACTION_MODEL}
<td class="">
{if $ACTION_MODEL->isModuleEnabled($MODULE_MODEL)}
<center>
<div><input type="radio" name="permissions[{$TABID}]" data-action-state="{$ACTION_MODEL->getName()}" value="{$ACTION_ID}"{if $MODULE_MODEL->getPermissionValue() eq $ACTION_ID}checked="true"{/if}></div>
</center>
{/if}
</td>
{/foreach}
<td class="triggerCustomSharingAccess">
<div class="row">
<span class="col-sm-4">&nbsp;</span>
<span class="col-sm-4">
<button type="button" class="btn btn-sm btn-default vtButton" data-handlerfor="fields" data-togglehandler="{$TABID}-rules" style="padding-right: 20px; padding-left: 20px;">
<i class="fa fa-chevron-down"></i>
</button>
</span>
</div>
</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<div class='modal-overlay-footer clearfix saveSharingAccess hide'>
<div class="row clearfix">
<div class=' textAlignCenter col-lg-12 col-md-12 col-sm-12 '>
<button class="btn btn-success saveButton" name="saveButton" type="submit">{vtranslate('LBL_APPLY_NEW_SHARING_RULES', $QUALIFIED_MODULE)}</button>&nbsp;&nbsp;
</div>
</div>
</div>
</form>
</div>
</div>
{/strip}

View File

@@ -0,0 +1,80 @@
{*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************}
{* modules/Settings/SharingAccess/views/IndexAjax.php *}
{* START YOUR IMPLEMENTATION FROM BELOW. Use {debug} for information *}
{strip}
<div class="ruleListContainer">
<div class="title row">
<div class="rulehead col-sm-6">
<!-- Check if the module should the for module to get the translations-->
<strong>{vtranslate('LBL_SHARING_RULE', $QUALIFIED_MODULE)}&nbsp;{vtranslate('LBL_FOR', $MODULE)}&nbsp;
{if $FOR_MODULE == 'Accounts'}{vtranslate($FOR_MODULE, $QUALIFIED_MODULE)}{else}{vtranslate($FOR_MODULE, $MODULE)}{/if} :</strong>
</div>
<div class="col-sm-6">
<div class="pull-right">
<button class="btn btn-sm btn-default addButton addCustomRule" type="button" data-url="{$MODULE_MODEL->getCreateRuleUrl()}">
<i class="fa fa-plus"></i> &nbsp;&nbsp;{vtranslate('LBL_ADD_CUSTOM_RULE', $QUALIFIED_MODULE)}
</button>
</div>
</div>
</div>
<hr>
<div class="contents">
{if $RULE_MODEL_LIST}
<table class="table table-bordered table-condensed customRuleTable">
<thead>
<tr class="customRuleHeaders">
<th>{vtranslate('LBL_RULE_NO', $QUALIFIED_MODULE)}</th>
<!-- Check if the module should the for module to get the translations -->
<th>{if $FOR_MODULE == 'Accounts'}{vtranslate($FOR_MODULE, $QUALIFIED_MODULE)}{else}{vtranslate($FOR_MODULE, $MODULE)}{/if}
&nbsp;{vtranslate('LBL_OF', $MODULE)}</th>
<th>{vtranslate('LBL_CAN_ACCESSED_BY', $QUALIFIED_MODULE)}</th>
<th>{vtranslate('LBL_PRIVILEGES', $QUALIFIED_MODULE)}</th>
</tr>
</thead>
<tbody>
{foreach item=RULE_MODEL key=RULE_ID from=$RULE_MODEL_LIST name="customRuleIterator"}
<tr class="customRuleEntries">
<td class="sequenceNumber">
{$smarty.foreach.customRuleIterator.index + 1}
</td>
<td>
<a href="{$RULE_MODEL->getSourceDetailViewUrl()}">{vtranslate('SINGLE_'|cat:$RULE_MODEL->getSourceMemberName(), $QUALIFIED_MODULE)}::{$RULE_MODEL->getSourceMember()->getName()}</a>
</td>
<td>
<a href="{$RULE_MODEL->getTargetDetailViewUrl()}">{vtranslate('SINGLE_'|cat:$RULE_MODEL->getTargetMemberName(), $QUALIFIED_MODULE)}::{$RULE_MODEL->getTargetMember()->getName()}</a>
</td>
<td>
{if $RULE_MODEL->isReadOnly()}
{vtranslate('Read Only', $QUALIFIED_MODULE)}
{else}
{vtranslate('Read Write', $QUALIFIED_MODULE)}
{/if}
<div class="table-actions pull-right">
<span><a href="javascript:void(0);" class="edit" data-url="{$RULE_MODEL->getEditViewUrl()}"><i title="{vtranslate('LBL_EDIT', $MODULE)}" class="fa fa-pencil"></i></a></span>
&nbsp;<span><a href="javascript:void(0);" class="delete" data-url="{$RULE_MODEL->getDeleteActionUrl()}"><i title="{vtranslate('LBL_DELETE', $MODULE)}" class="fa fa-trash"></i></a></span>
</div>
</td>
</tr>
{/foreach}
</tbody>
</table>
<div class="recordDetails hide">
<p class="textAlignCenter">{vtranslate('LBL_CUSTOM_ACCESS_MESG', $QUALIFIED_MODULE)}.<!--<a href="">{vtranslate('LBL_CLICK_HERE', $QUALIFIED_MODULE)}</a>&nbsp;{vtranslate('LBL_CREATE_RULE_MESG', $QUALIFIED_MODULE)}--></p>
</div>
{else}
<div class="recordDetails">
<p class="textAlignCenter">{vtranslate('LBL_CUSTOM_ACCESS_MESG', $QUALIFIED_MODULE)}.<!--<a href="">{vtranslate('LBL_CLICK_HERE', $QUALIFIED_MODULE)}</a>&nbsp;{vtranslate('LBL_CREATE_RULE_MESG', $QUALIFIED_MODULE)}--></p>
</div>
{/if}
</div>
</div>
{/strip}

View File

@@ -0,0 +1,348 @@
/*+***********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
*************************************************************************************/
Vtiger.Class('Settings_Sharing_Access_Js', {}, {
contentTable : false,
contentsContainer : false,
init : function() {
this.setContentTable('.sharingAccessDetails').setContentContainer('#sharingAccessContainer');
},
setContentTable : function(element) {
if(element instanceof jQuery){
this.contentTable = element;
return this;
}
this.contentTable = jQuery(element);
return this;
},
setContentContainer : function(element) {
if(element instanceof jQuery){
this.contentsContainer = element;
return this;
}
this.contentsContainer = jQuery(element);
return this;
},
getContentTable : function() {
return this.contentTable;
},
getContentContainer : function() {
return this.contentsContainer;
},
getCustomRuleContainerClassName : function(parentModuleName) {
return parentModuleName+'CustomRuleList';
},
showCustomRulesNextToElement : function(parentElement, rulesListElement) {
var moduleName = parentElement.data('moduleName')
var trElementForRuleList = jQuery('<tr class="'+this.getCustomRuleContainerClassName(moduleName)+'"><td class="customRuleContainer row-fluid" colspan="6"></td></tr>');
jQuery('td',trElementForRuleList).append(rulesListElement);
jQuery('.ruleListContainer', trElementForRuleList).css('display', 'none');
parentElement.after(trElementForRuleList).addClass('collapseRow');
jQuery('.ruleListContainer', trElementForRuleList).slideDown('slow');
},
/*
* function to get custom rules data based on the module
* @params: forModule.
*/
getCustomRules : function(forModule) {
var aDeferred = jQuery.Deferred();
var params = {}
params['for_module'] = forModule;
params['module'] = app.getModuleName();
params['parent'] = app.getParentModuleName();
params['view'] = 'IndexAjax';
params['mode'] = 'showRules';
app.request.get({'data' : params}).then(
function(err, data) {
if(err === null) {
aDeferred.resolve(data);
}else {
//TODO : Handle error
aDeferred.reject(error);
}
});
return aDeferred.promise();
},
save : function(data) {
var aDeferred = jQuery.Deferred();
app.helper.showProgress();
if(typeof data == 'undefined') {
data = {};
}
app.request.post({'data' : data}).then(
function(err, data){
app.helper.hideProgress();
if(err == null) {
aDeferred.resolve(data);
}else {
aDeferred.reject();
}
});
return aDeferred.promise();
},
/*
* function to Save the Custom Rule
*/
saveCustomRule : function(form, e) {
var thisInstance = this;
var data = form.serializeFormData();
if(typeof data == 'undefined' ) {
data = {};
}
app.helper.showProgress();
data.module = app.getModuleName();
data.parent = app.getParentModuleName();
data.action = 'IndexAjax';
data.mode = 'saveRule';
app.request.post({'data' : data}).then(
function(err, data) {
app.helper.hideProgress();
if(err === null) {
app.helper.hideModal();
thisInstance.displaySaveCustomRuleResponse(data);
var moduleName = jQuery('[name="for_module"]', form).val();
thisInstance.loadCustomRulesList(moduleName);
}
}
);
},
/*
* function to load the CustomRules List for the module after save the custom rule
*/
loadCustomRulesList : function(moduleName) {
var thisInstance = this;
var contentTable = this.getContentTable();
thisInstance.getCustomRules(moduleName).then(
function(data){
var customRuleListContainer = jQuery('.'+thisInstance.getCustomRuleContainerClassName(moduleName),contentTable);
customRuleListContainer.find('td.customRuleContainer').html(data);
},
function(error){
//TODO: Handle Error
}
);
},
/*
* Function to display the SaveCustomRule response message
*/
displaySaveCustomRuleResponse : function(data) {
var success = data['success'];
var params;
if(success) {
params = app.vtranslate('JS_CUSTOM_RULE_SAVED_SUCCESSFULLY');
} else {
params = app.vtranslate('JS_CUSTOM_RULE_SAVING_FAILED');
}
app.helper.showSuccessNotification({'message' : params})
},
editCustomRule : function(url) {
var thisInstance = this;
app.helper.showProgress();
app.request.get({'url' : url}).then(function(err, data){
app.helper.hideProgress();
if(err === null) {
var params = {
cb : function(modalContainer){
var form = jQuery('#editCustomRule');
form.on('submit', function(e) {
//To stop the submit of form
e.preventDefault();
var formElement = jQuery(e.currentTarget);
thisInstance.saveCustomRule(formElement, e);
})
}
};
app.helper.showModal(data, params);
}
});
},
/*
* function to delete Custom Rule from the list
* @params: deleteElement.
*/
deleteCustomRule : function(deleteElement) {
var deleteUrl = deleteElement.data('url');
var currentRow = deleteElement.closest('tr.customRuleEntries');
var message = app.vtranslate('LBL_DELETE_CONFIRMATION');
app.helper.showConfirmationBox({'message' : message}).then(function(data) {
app.request.post({'url' : deleteUrl}).then(
function(err, data){
if(err === null){
currentRow.fadeOut('slow');
var customRuleTable = currentRow.closest('table .customRuleTable');
//after delete the custom rule, update the sequence number of existing rules
var nextRows = currentRow.nextAll('tr.customRuleEntries');
if(nextRows.length > 0){
jQuery.each(nextRows,function(i,element) {
var currentSequenceElement = jQuery(element).find('.sequenceNumber');
var updatedNumber = parseInt(currentSequenceElement.text())-1;
currentSequenceElement.text(updatedNumber);
});
}
currentRow.remove();
var customRuleEntries = customRuleTable.find('.customRuleEntries');
//if there are no custom rule entries, we have to hide headers also and show the empty message div
if(customRuleEntries.length < 1) {
customRuleTable.find('.customRuleHeaders').fadeOut('slow').remove();
customRuleTable.parent().find('.recordDetails').removeClass('hide');
customRuleTable.addClass('hide');
}
}else{
app.helper.showSuccessNotification({'message' : err.message});
}
});
},
function(error, err){
}
);
},
/*
* function to register click event for radio buttons
*/
registerSharingAccessEdit : function() {
var contentContainer = this.getContentContainer();
contentContainer.one('click','input:radio', function(e){
contentContainer.find('.saveSharingAccess').removeClass('hide');
});
},
/*
* Function to register change event for dependent modules privileges
*/
registerDependentModulesPrivilegesChange : function() {
var thisInstance = this;
var container = thisInstance.getContentContainer();
var contentTable = this.getContentTable();
var modulesList = JSON.parse(container.find('.dependentModules').val());
jQuery.each(modulesList, function(moduleName, dependentList) {
var dependentPrivilege = contentTable.find('[data-module-name="'+moduleName+'"]').find('[data-action-state="Private"]');
dependentPrivilege.change(function(e) {
var currentTarget = jQuery(e.currentTarget);
if(currentTarget.is(':checked')) {
var message = app.vtranslate('JS_DEPENDENT_PRIVILEGES_SHOULD_CHANGE');
app.helper.showAlertBox({'message': message});
jQuery.each(dependentList, function(index, module) {
contentTable.find('[data-module-name="'+module+'"]').find('[data-action-state="Private"]').prop('checked', true);
})
}
})
})
},
registerEvents : function() {
var thisInstance = this;
var contentTable = this.getContentTable();
var contentContainer = this.getContentContainer();
thisInstance.registerSharingAccessEdit();
thisInstance.registerDependentModulesPrivilegesChange();
contentTable.on('click', 'td.triggerCustomSharingAccess', function(e){
var element = jQuery(e.currentTarget);
var trElement = element.closest('tr');
var moduleName = trElement.data('moduleName');
var customRuleListContainer = jQuery('.'+thisInstance.getCustomRuleContainerClassName(moduleName),contentTable);
if(customRuleListContainer.length > 0) {
if(customRuleListContainer.css('display') === 'none') {
customRuleListContainer.show();
jQuery('.ruleListContainer', customRuleListContainer).slideDown('slow');
trElement.addClass('collapseRow');
element.find('button i').removeClass('fa-chevron-down').addClass('fa-chevron-up');
}else{
jQuery('.ruleListContainer', customRuleListContainer).slideUp('slow', function(e) {
customRuleListContainer.css('display', 'none');
});
element.find('button i').removeClass('fa-chevron-up').addClass('fa-chevron-down');
trElement.removeClass('collapseRow');
}
return;
}
app.helper.showProgress();
thisInstance.getCustomRules(moduleName).then(
function(data){
app.helper.hideProgress();
thisInstance.showCustomRulesNextToElement(trElement, data);
element.find('button i').removeClass('fa-chevron-down').addClass('fa-chevron-up');
});
});
contentTable.on('click', 'button.addCustomRule' , function(e) {
var button = jQuery(e.currentTarget);
thisInstance.editCustomRule(button.data('url'));
})
contentTable.on('click', '.edit', function(e){
var editElement = jQuery(e.currentTarget);
var editUrl = editElement.data('url');
thisInstance.editCustomRule(editUrl);
});
contentTable.on('click', '.delete', function(e){
var deleteElement = jQuery(e.currentTarget);
thisInstance.deleteCustomRule(deleteElement);
});
contentContainer.on('submit', '#EditSharingAccess', function(e){
e.preventDefault();
var form = jQuery(e.currentTarget);
var data = form.serializeFormData();
thisInstance.save(data).then(
function(data) {
contentContainer.find('.saveSharingAccess').addClass('hide');
thisInstance.registerSharingAccessEdit();
app.helper.showSuccessNotification({'message' : app.vtranslate('JS_NEW_SHARING_RULES_APPLIED_SUCCESSFULLY')});
},
function(error,err){
}
);
});
//scrollbar is not needed for shaing access
}
});
Settings_Sharing_Access_Js('Settings_SharingAccess_Index_Js',{},{
init : function() {
this._super();
this.addComponents();
},
addComponents : function() {
this.addModuleSpecificComponent('Index','Vtiger',app.getParentModuleName());
},
});