Merge branch 'master' into feature/tree

This commit is contained in:
yuri
2015-05-05 11:38:51 +03:00
53 changed files with 386 additions and 201 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ use \Espo\ORM\Entity;
class Email extends \Espo\Core\Acl\Base
{
public function checkRead(User $user, Entity $entity, $data)
public function checkEntityRead(User $user, Entity $entity, $data)
{
if ($this->checkEntity($user, $entity, $data, 'read')) {
return true;
+25
View File
@@ -194,5 +194,30 @@ class Base implements Injectable
}
return false;
}
public function checkEntityDelete(User $user, Entity $entity, $data)
{
$result = $this->checkEntity($user, $entity, $data, 'delete');
if (!$result) {
if (is_array($data)) {
if ($data['edit'] != 'no') {
if ($entity->has('createdById') && $entity->get('createdById') == $user->id) {
if (!$entity->has('assignedUserId')) {
return true;
} else {
if (!$entity->get('assignedUserId')) {
return true;
}
if ($entity->get('assignedUserId') == $entity->get('createdById')) {
return true;
}
}
}
}
}
}
return $result;
}
}
+31 -2
View File
@@ -166,11 +166,30 @@ class Table
return $result;
}
private function getScopeList()
{
$scopeList = [];
$scopes = $this->metadata->get('scopes');
foreach ($scopes as $scope => $d) {
if (!empty($d['acl'])) {
$scopeList[] = $scope;
}
}
return $scopeList;
}
private function merge($tables)
{
$data = array();
$scopeList = $this->getScopeList();
foreach ($tables as $table) {
foreach ($table as $scope => $row) {
foreach ($scopeList as $scope) {
if (!isset($table->$scope)) {
continue;
}
$row = $table->$scope;
if ($row == false) {
if (!isset($data[$scope])) {
$data[$scope] = false;
@@ -184,7 +203,8 @@ class Table
if ($data[$scope] == false) {
$data[$scope] = array();
}
if (is_array($row)) {
if (is_array($row) || $row instanceof \stdClass) {
foreach ($row as $action => $level) {
if (!isset($data[$scope][$action])) {
$data[$scope][$action] = $level;
@@ -198,6 +218,15 @@ class Table
}
}
}
foreach ($scopeList as $scope) {
if (!array_key_exists($scope, $data)) {
$aclType = $this->metadata->get('scopes.' . $scope . '.acl');
if (!empty($aclType) && ($aclType === true || $aclType === 'record')) {
$data[$scope] = $this->metadata->get('app.acl.recordDefault');
}
}
}
return $data;
}
+2 -2
View File
@@ -149,13 +149,13 @@ class AclManager
$entityType = $entity->getEntityType();
$impl = $this->getImplementation($entityType);
$methodName = 'check' . ucfirst($action);
$methodName = 'checkEntity' . ucfirst($action);
if (method_exists($impl, $methodName)) {
$data = $this->getTable($user)->getScopeData($entityType);
return $impl->$methodName($user, $entity, $data);
}
return $this->checkEntity($user, $entity, $action, $isOwner, $inTeam, $entity);
return $this->checkEntity($user, $entity, $action);
}
}
}
+11 -4
View File
@@ -284,11 +284,18 @@ class Sender
$message->setBody($body);
if (!$message->getHeaders()->has('content-type')) {
$contentTypeHeader = new \Zend\Mail\Header\ContentType();
$message->getHeaders()->addHeader($contentTypeHeader);
if ($messageType == 'text/plain') {
if ($message->getHeaders()->has('content-type')) {
$message->getHeaders()->removeHeader('content-type');
}
$message->getHeaders()->addHeaderLine('Content-Type', 'text/plain; charset=UTF-8');
} else {
if (!$message->getHeaders()->has('content-type')) {
$contentTypeHeader = new \Zend\Mail\Header\ContentType();
$message->getHeaders()->addHeader($contentTypeHeader);
}
$message->getHeaders()->get('content-type')->setType($messageType);
}
$message->getHeaders()->get('content-type')->setType($messageType);
$message->setEncoding('UTF-8');
+28 -2
View File
@@ -33,10 +33,14 @@ class Job
private $entityManager;
private $cronScheduledJob;
public function __construct(Config $config, EntityManager $entityManager)
{
$this->config = $config;
$this->entityManager = $entityManager;
$this->cronScheduledJob = new ScheduledJob($this->config, $this->entityManager);
}
protected function getConfig()
@@ -49,6 +53,11 @@ class Job
return $this->entityManager;
}
protected function getCronScheduledJob()
{
return $this->cronScheduledJob;
}
/**
* Get Pending Jobs
*
@@ -145,13 +154,30 @@ class Job
$currentTime = time();
$periodTime = $currentTime - intval($jobConfigs['jobPeriod']);
$update = "UPDATE job SET `status` = '" . CronManager::FAILED ."' WHERE
$pdo = $this->getEntityManager()->getPDO();
$select = "SELECT id, scheduled_job_id, execute_time FROM `job` WHERE
(`status` = '" . CronManager::RUNNING ."')
AND execute_time < '".date('Y-m-d H:i:s', $periodTime)."' ";
$sth = $pdo->prepare($select);
$sth->execute();
$pdo = $this->getEntityManager()->getPDO();
$jobData = array();
while ($row = $sth->fetch(PDO::FETCH_ASSOC)){
$jobData[$row['id']] = $row;
}
$update = "UPDATE job SET `status` = '". CronManager::FAILED ."' WHERE id IN ('".implode("', '", array_keys($jobData))."')";
$sth = $pdo->prepare($update);
$sth->execute();
//add status 'Failed' to SchediledJobLog
$cronScheduledJob = $this->getCronScheduledJob();
foreach ($jobData as $jobId => $job) {
if (!empty($job['scheduled_job_id'])) {
$cronScheduledJob->addLogRecord($job['scheduled_job_id'], CronManager::FAILED, $job['execute_time']);
}
}
}
/**
@@ -81,14 +81,16 @@ class ScheduledJob
*
* @return string ID of created ScheduledJobLogRecord
*/
public function addLogRecord($scheduledJobId, $status)
public function addLogRecord($scheduledJobId, $status, $runTime = null)
{
$lastRun = date('Y-m-d H:i:s');
if (!isset($runTime)) {
$runTime = date('Y-m-d H:i:s');
}
$entityManager = $this->getEntityManager();
$scheduledJob = $entityManager->getEntity('ScheduledJob', $scheduledJobId);
$scheduledJob->set('lastRun', $lastRun);
$scheduledJob->set('lastRun', $runTime);
$entityManager->saveEntity($scheduledJob);
$scheduledJobLog = $entityManager->getEntity('ScheduledJobLogRecord');
@@ -96,7 +98,7 @@ class ScheduledJob
'scheduledJobId' => $scheduledJobId,
'name' => $scheduledJob->get('name'),
'status' => $status,
'executionTime' => $lastRun,
'executionTime' => $runTime,
));
$scheduledJobLogId = $entityManager->saveEntity($scheduledJobLog);
@@ -29,7 +29,7 @@ class Converter
{
private $metadata;
private $fileManager;
private $metadataUtils;
private $metadataHelper;
private $relationManager;
@@ -82,7 +82,6 @@ class Converter
'len' => '24',
);
public function __construct(\Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\File\Manager $fileManager)
{
$this->metadata = $metadata;
@@ -90,10 +89,9 @@ class Converter
$this->relationManager = new RelationManager($this->metadata);
$this->metadataUtils = new \Espo\Core\Utils\Metadata\Utils($this->metadata);
$this->metadataHelper = new \Espo\Core\Utils\Metadata\Helper($this->metadata);
}
protected function getMetadata()
{
return $this->metadata;
@@ -118,9 +116,9 @@ class Converter
return $this->relationManager;
}
protected function getMetadataUtils()
protected function getMetadataHelper()
{
return $this->metadataUtils;
return $this->metadataHelper;
}
public function process()
@@ -225,31 +223,16 @@ class Converter
foreach($entityMeta['fields'] as $fieldName => $fieldParams) {
/** check if "fields" option exists in $fieldMeta */
$fieldTypeMeta = $this->getMetadataUtils()->getFieldDefsByType($fieldParams);
$fieldTypeMeta = $this->getMetadataHelper()->getFieldDefsByType($fieldParams);
if (isset($fieldTypeMeta['fields']) && is_array($fieldTypeMeta['fields'])) {
foreach($fieldTypeMeta['actualFields'] as $subFieldName) {
$subField = $this->convertActualFields($entityName, $fieldName, $fieldParams, $subFieldName, $fieldTypeMeta);
if (!isset($outputMeta[ $subField['naming'] ])) {
$subFieldDefs = $this->convertField($entityName, $subField['name'], $subField['params']);
if ($subFieldDefs !== false) {
$outputMeta[ $subField['naming'] ] = $subFieldDefs; //push fieldDefs to the main array
}
}
}
} else {
$fieldDefs = $this->convertField($entityName, $fieldName, $fieldParams, $fieldTypeMeta);
if ($fieldDefs !== false) {
$outputMeta[$fieldName] = $fieldDefs; //push fieldDefs to the main array
}
$fieldDefs = $this->convertField($entityName, $fieldName, $fieldParams, $fieldTypeMeta);
if ($fieldDefs !== false) {
$outputMeta[$fieldName] = $fieldDefs; //push fieldDefs to the main array
}
/** check and set the linkDefs from 'fields' metadata */
if (isset($fieldTypeMeta['linkDefs'])) {
$linkDefs = $this->getMetadataUtils()->getLinkDefsInFieldMeta($entityName, $fieldParams, $fieldTypeMeta['linkDefs']);
$linkDefs = $this->getMetadataHelper()->getLinkDefsInFieldMeta($entityName, $fieldParams, $fieldTypeMeta['linkDefs']);
if (isset($linkDefs)) {
if (!isset($entityMeta['links'])) {
$entityMeta['links'] = array();
@@ -310,17 +293,12 @@ class Converter
if (isset($scopeDefs['stream']) && $scopeDefs['stream']) {
if (!isset($entityMeta['fields']['isFollowed'])) {
$ormMeta[$entityName]['fields']['isFollowed'] = array(
'type' => 'bool',
'type' => 'varchar',
'notStorable' => true,
);
}
} //END: add a field 'isFollowed' for stream => true
$ormMeta[$entityName]['fields']['isEditable'] = array(
'type' => 'bool',
'notStorable' => true
);
return $ormMeta;
}
@@ -334,15 +312,15 @@ class Converter
/** merge fieldDefs option from field definition */
if (!isset($fieldTypeMeta)) {
$fieldTypeMeta = $this->getMetadataUtils()->getFieldDefsByType($fieldParams);
$fieldTypeMeta = $this->getMetadataHelper()->getFieldDefsByType($fieldParams);
}
if (isset($fieldTypeMeta['fieldDefs'])) {
$fieldParams = Util::merge($fieldParams, $fieldTypeMeta['fieldDefs']);
}
/** check if need to skip this field in ORM metadata */
if (isset($fieldParams['skip']) && $fieldParams['skip'] === true) {
/** check if need to skipOrmDefs this field in ORM metadata */
if (isset($fieldParams['skipOrmDefs']) && $fieldParams['skipOrmDefs'] === true) {
return false;
}
@@ -366,37 +344,6 @@ class Converter
return $fieldDefs;
}
protected function convertActualFields($entityName, $fieldName, $fieldParams, $subFieldName, $fieldTypeMeta)
{
$subField = array();
$subField['params'] = $this->getInitValues($fieldParams);
if (isset($fieldTypeMeta['fieldDefs'])) {
$subField['params'] = Util::merge($subField['params'], $fieldTypeMeta['fieldDefs']);
}
//if empty field name, then use the main field
if (trim($subFieldName) == '') {
$subField['name'] = $fieldName;
$subField['naming'] = $fieldName;
} else {
$namingType = isset($fieldTypeMeta['naming']) ? $fieldTypeMeta['naming'] : $this->defaultNaming;
$subField['name'] = $subFieldName;
$subField['naming'] = Util::getNaming($fieldName, $subFieldName, $namingType);
if (isset($fieldTypeMeta['fields'][$subFieldName])) {
$subField['params'] = Util::merge($subField['params'], $fieldTypeMeta['fields'][$subFieldName]);
}
}
return $subField;
}
protected function convertLinks($entityName, $entityMeta, $ormMeta)
{
if (!isset($entityMeta['links'])) {
@@ -22,6 +22,8 @@
namespace Espo\Core\Utils\Database\Orm\Relations;
use Espo\Core\Utils\Util;
class Base extends \Espo\Core\Utils\Database\Orm\Base
{
private $params;
@@ -119,8 +121,11 @@ class Base extends \Espo\Core\Utils\Database\Orm\Base
$additionalParrams = $this->getAllowedAdditionalParams($name);
if (isset($additionalParrams) && !isset($linkParams[$name])) {
if (isset($additionalParrams)) {
$linkParams[$name] = $additionalParrams;
if (isset($linkParams[$name]) && is_array($linkParams[$name])) {
$linkParams[$name] = Util::merge($linkParams[$name], $additionalParrams);
}
}
}
}
@@ -35,7 +35,7 @@ class EntityManager
private $fileManager;
private $metadataUtils;
private $metadataHelper;
public function __construct(Metadata $metadata, Language $language, File\Manager $fileManager)
{
@@ -43,7 +43,7 @@ class EntityManager
$this->language = $language;
$this->fileManager = $fileManager;
$this->metadataUtils = new \Espo\Core\Utils\Metadata\Utils($this->metadata);
$this->metadataHelper = new \Espo\Core\Utils\Metadata\Helper($this->metadata);
}
protected function getMetadata()
@@ -61,9 +61,9 @@ class EntityManager
return $this->fileManager;
}
protected function getMetadataUtils()
protected function getMetadataHelper()
{
return $this->metadataUtils;
return $this->metadataHelper;
}
public function create($name, $type, $params = array())
@@ -352,6 +352,10 @@ class EntityManager
)
)
);
if ($entityForeign == $entity) {
$dataLeft['links'][$link]['midKeys'] = ['leftId', 'rightId'];
$dataRight['links'][$linkForeign]['midKeys'] = ['rightId', 'leftId'];
}
break;
}
+11 -11
View File
@@ -31,7 +31,7 @@ class FieldManager
private $language;
private $metadataUtils;
private $metadataHelper;
protected $isChanged = null;
@@ -44,7 +44,7 @@ class FieldManager
$this->metadata = $metadata;
$this->language = $language;
$this->metadataUtils = new \Espo\Core\Utils\Metadata\Utils($this->metadata);
$this->metadataHelper = new \Espo\Core\Utils\Metadata\Helper($this->metadata);
}
protected function getMetadata()
@@ -57,9 +57,9 @@ class FieldManager
return $this->language;
}
protected function getMetadataUtils()
protected function getMetadataHelper()
{
return $this->metadataUtils;
return $this->metadataHelper;
}
public function read($name, $scope)
@@ -187,11 +187,6 @@ class FieldManager
}
}
if (isset($fieldDef['linkDefs'])) {
$linkDefs = $fieldDef['linkDefs'];
unset($fieldDef['linkDefs']);
}
$currentOptionList = array_keys((array) $this->getFieldDef($name, $scope));
foreach ($fieldDef as $defName => $defValue) {
if ( (!isset($defValue) || $defValue === '') && !in_array($defName, $currentOptionList) ) {
@@ -214,11 +209,16 @@ class FieldManager
{
$fieldDef = $this->prepareFieldDef($fieldName, $fieldDef, $scope);
$metaFieldDef = $this->getMetadataUtils()->getFieldDefsInFieldMeta($fieldDef);
$metaFieldDef = $this->getMetadataHelper()->getFieldDefsInFieldMeta($fieldDef);
if (isset($metaFieldDef)) {
$fieldDef = Util::merge($metaFieldDef, $fieldDef);
}
if (isset($fieldDef['linkDefs'])) {
$linkDefs = $fieldDef['linkDefs'];
unset($fieldDef['linkDefs']);
}
$defs = array(
'fields' => array(
$fieldName => $fieldDef,
@@ -226,7 +226,7 @@ class FieldManager
);
/** Save links for a field. */
$metaLinkDef = $this->getMetadataUtils()->getLinkDefsInFieldMeta($scope, $fieldDef);
$metaLinkDef = $this->getMetadataHelper()->getLinkDefsInFieldMeta($scope, $fieldDef);
if (isset($linkDefs) || isset($metaLinkDef)) {
$linkDefs = Util::merge((array) $metaLinkDef, (array) $linkDefs);
$defs['links'] = array(
+60 -11
View File
@@ -35,6 +35,7 @@ class Metadata
private $fileManager;
private $converter;
private $moduleConfig;
private $metadataHelper;
/**
* @var string - uses for loading default values
@@ -76,12 +77,6 @@ class Metadata
{
$this->config = $config;
$this->fileManager = $fileManager;
$this->unifier = new \Espo\Core\Utils\File\Unifier($this->fileManager);
$this->converter = new \Espo\Core\Utils\Database\Converter($this, $this->fileManager);
$this->moduleConfig = new \Espo\Core\Utils\Module($this->config, $this->fileManager);
}
protected function getConfig()
@@ -89,26 +84,47 @@ class Metadata
return $this->config;
}
protected function getUnifier()
{
return $this->unifier;
}
protected function getFileManager()
{
return $this->fileManager;
}
protected function getUnifier()
{
if (!isset($this->unifier)) {
$this->unifier = new \Espo\Core\Utils\File\Unifier($this->fileManager);
}
return $this->unifier;
}
protected function getConverter()
{
if (!isset($this->converter)) {
$this->converter = new \Espo\Core\Utils\Database\Converter($this, $this->fileManager);
}
return $this->converter;
}
protected function getModuleConfig()
{
if (!isset($this->moduleConfig)) {
$this->moduleConfig = new \Espo\Core\Utils\Module($this->config, $this->fileManager);
}
return $this->moduleConfig;
}
protected function getMetadataHelper()
{
if (!isset($this->metadataHelper)) {
$this->metadataHelper = new Metadata\Helper($this);
}
return $this->metadataHelper;
}
public function isCached()
{
if (!$this->getConfig()->get('useCache')) {
@@ -139,6 +155,7 @@ class Metadata
} else {
$this->meta = $this->getUnifier()->unify($this->name, $this->paths, true);
$this->meta = $this->setLanguageFromConfig($this->meta);
$this->meta = $this->addAdditionalFields($this->meta);
if ($this->getConfig()->get('useCache')) {
$isSaved = $this->getFileManager()->putPhpContents($this->cacheFile, $this->meta);
@@ -197,6 +214,7 @@ class Metadata
}
/**
* todo: move to a separate file
* Set language list and default for Settings, Preferences metadata
*
* @param array $data Meta
@@ -222,6 +240,37 @@ class Metadata
return $data;
}
/**
* todo: move to a separate file
* Add additional fields defined from metadata -> fields
*
* @param array $meta
*/
protected function addAdditionalFields(array $meta)
{
$metaCopy = $meta;
$definitionList = $meta['fields'];
foreach ($metaCopy['entityDefs'] as $entityName => $entityParams) {
foreach ($entityParams['fields'] as $fieldName => $fieldParams) {
$additionalFields = $this->getMetadataHelper()->getAdditionalFieldList($fieldName, $fieldParams, $definitionList);
if (!empty($additionalFields)) {
//merge or add to the end of meta array
foreach ($additionalFields as $subFieldName => $subFieldParams) {
if (isset($entityParams['fields'][$subFieldName])) {
$meta['entityDefs'][$entityName]['fields'][$subFieldName] = Util::merge($subFieldParams, $entityParams['fields'][$subFieldName]);
} else {
$meta['entityDefs'][$entityName]['fields'][$subFieldName] = $subFieldParams;
}
}
}
}
}
return $meta;
}
/**
* Set Metadata data
* Ex. $key1 = menu, $key2 = Account then will be created a file metadataFolder/menu/Account.json
@@ -22,10 +22,26 @@
namespace Espo\Core\Utils\Metadata;
class Utils
use Espo\Core\Utils\Util;
class Helper
{
private $metadata;
protected $defaultNaming = 'postfix';
/**
* List of copied params for metadata -> 'fields' from parent items
*/
protected $copiedDefParams = array(
'readOnly',
'notStorable',
'layoutListDisabled',
'layoutDetailDisabled',
'layoutMassUpdateDisabled',
'layoutFiltersDisabled',
);
public function __construct(\Espo\Core\Utils\Metadata $metadata)
{
$this->metadata = $metadata;
@@ -102,7 +118,41 @@ class Utils
return $linkFieldDefsByType;
}
}
/**
* Get additional field list based on field definition in metadata 'fields'
*
* @param string $fieldName
* @param array $fieldParams
* @param array|null $definitionList
*
* @return array
*/
public function getAdditionalFieldList($fieldName, array $fieldParams, array $definitionList = null)
{
if (empty($fieldParams['type'])) {
return;
}
$fieldType = $fieldParams['type'];
$fieldDefinition = isset($definitionList[$fieldType]) ? $definitionList[$fieldType] : $this->getMetadata()->get('fields.'.$fieldType);
?>
if (!empty($fieldDefinition['fields']) && is_array($fieldDefinition['fields'])) {
$copiedParams = array_intersect_key($fieldParams, array_flip($this->copiedDefParams));
$additionalFields = array();
//add additional fields
foreach ($fieldDefinition['fields'] as $subFieldName => $subFieldParams) {
$namingType = isset($fieldDefinition['naming']) ? $fieldDefinition['naming'] : $this->defaultNaming;
$subFieldNaming = Util::getNaming($fieldName, $subFieldName, $namingType);
$additionalFields[$subFieldNaming] = array_merge($copiedParams, $subFieldParams);
}
return $additionalFields;
}
}
}
+18 -13
View File
@@ -49,21 +49,26 @@ class Cleanup extends \Espo\Core\Jobs\Base
protected function cleanupScheduledJobLog()
{
$lastTenRecords = "SELECT c.id FROM (
SELECT i1.id
FROM scheduled_job_log_record i1
CROSS JOIN scheduled_job_log_record i2 ON ( i1.scheduled_job_id = i2.scheduled_job_id
AND i1.id < i2.id )
GROUP BY i1.id
HAVING COUNT( * ) <10
ORDER BY i1.created_at DESC
) AS c";
$query = "DELETE FROM `scheduled_job_log_record` WHERE DATE(created_at) < '".$this->getDate()."' AND id NOT IN (".$lastTenRecords.") ";
$pdo = $this->getEntityManager()->getPDO();
$sth = $pdo->prepare($query);
$sql = "SELECT id FROM scheduled_job";
$sth = $pdo->prepare($sql);
$sth->execute();
while ($row = $sth->fetch(\PDO::FETCH_ASSOC)) {
$id = $row['id'];
$lastRowsSql = "SELECT id FROM scheduled_job_log_record WHERE scheduled_job_id = '".$id."' ORDER BY created_at DESC LIMIT 0,10";
$lastRowsSth = $pdo->prepare($lastRowsSql);
$lastRowsSth->execute();
$lastRowIds = $lastRowsSth->fetchAll(\PDO::FETCH_COLUMN, 0);
$delSql = "DELETE FROM `scheduled_job_log_record`
WHERE scheduled_job_id = '".$id."'
AND DATE(created_at) < '".$this->getDate()."'
AND id NOT IN ('".implode("', '", $lastRowIds)."')
";
$pdo->query($delSql);
}
}
protected function getDate($format = 'Y-m-d')
@@ -11,9 +11,11 @@
"description": "Description",
"isOverdue": "Is Overdue",
"account": "Account",
"dateCompleted": "Date Completed"
"dateCompleted": "Date Completed",
"attachments": "Attachments"
},
"links": {
"attachments": "Attachments"
},
"options": {
"status": {
@@ -7,7 +7,8 @@
{"name":"priority"}],
[{"name":"dateStart"},{"name":"dateCompleted"}],
[{"name":"dateEnd"},false],
[{"name":"description", "fullWidth": true}]
[{"name":"description", "fullWidth": true}],
[{"name":"attachments"},false]
]
}
]
@@ -147,7 +147,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"contacts": {
@@ -127,7 +127,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"users": {
@@ -137,7 +137,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"targetLists": {
@@ -84,7 +84,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"inboundEmail": {
@@ -160,7 +160,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"account": {
@@ -209,7 +209,7 @@
},
"emails": {
"type": "hasChildren",
"entity": "Task",
"entity": "Email",
"foreign": "parent",
"layoutRelationshipsDisabled": true
},
@@ -90,7 +90,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
}
},
@@ -169,7 +169,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"opportunities": {
@@ -122,7 +122,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"users": {
@@ -106,7 +106,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"account": {
@@ -103,7 +103,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
}
},
@@ -55,7 +55,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"campaigns": {
@@ -79,6 +79,10 @@
},
"teams": {
"type": "linkMultiple"
},
"attachments": {
"type": "linkMultiple",
"view": "Fields.AttachmentMultiple"
}
},
"links": {
@@ -97,7 +101,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"parent": {
@@ -108,6 +112,13 @@
"account": {
"type": "belongsTo",
"entity": "Account"
},
"attachments": {
"type": "hasChildren",
"entity": "Attachment",
"foreign": "parent",
"relationName": "attachments",
"layoutRelationshipsDisabled": true
}
},
"collection": {
@@ -6,7 +6,7 @@
"body": "Тело",
"subject": "Тема",
"attachments": "Вложения",
"insertField": "Project-Id-Version: Russian Translation\nPOT-Creation-Date: \nPO-Revision-Date: \nLast-Translator: \nLanguage-Team: EspoCRM <infobox@espocrm.com>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nLanguage: ru_RU\nX-Generator: Poedit 1.6.5\n"
"insertField": ""
},
"links": {
},
@@ -31,5 +31,10 @@
"delete": "own"
},
"Role": false
},
"recordDefault": {
"read": "all",
"edit": "all",
"delete": "no"
}
}
@@ -174,7 +174,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam"
"relationName": "entityTeam"
},
"users": {
"type": "hasMany",
@@ -191,7 +191,7 @@
"type": "hasChildren",
"entity": "Attachment",
"foreign": "parent",
"relationName": "Attachments"
"relationName": "attachments"
},
"parent": {
"type": "belongsToParent",
@@ -205,7 +205,7 @@
"toEmailAddresses": {
"type": "hasMany",
"entity": "EmailAddress",
"relationName": "EmailEmailAddress",
"relationName": "emailEmailAddress",
"conditions": {
"addressType": "to"
},
@@ -219,7 +219,7 @@
"ccEmailAddresses": {
"type": "hasMany",
"entity": "EmailAddress",
"relationName": "EmailEmailAddress",
"relationName": "emailEmailAddress",
"conditions": {
"addressType": "cc"
},
@@ -233,7 +233,7 @@
"bccEmailAddresses": {
"type": "hasMany",
"entity": "EmailAddress",
"relationName": "EmailEmailAddress",
"relationName": "emailEmailAddress",
"conditions": {
"addressType": "bcc"
},
@@ -52,7 +52,7 @@
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam"
"relationName": "entityTeam"
},
"assignedUser": {
"type": "belongsTo",
@@ -49,7 +49,7 @@
"attachments": {
"type": "hasChildren",
"entity": "Attachment",
"relationName": "Attachments",
"relationName": "attachments",
"foreign": "parent"
},
"parent": {
@@ -27,5 +27,8 @@
},
"mergable":false,
"notCreatable": false,
"filter": true
"filter": true,
"fieldDefs":{
"skipOrmDefs":true
}
}
@@ -4,6 +4,6 @@
"filter": true,
"notCreatable": true,
"fieldDefs":{
"skip": true
"skipOrmDefs": true
}
}
@@ -18,6 +18,6 @@
"entity": "Attachment"
},
"fieldDefs":{
"skip": true
"skipOrmDefs": true
}
}
@@ -10,8 +10,5 @@
}
],
"filter": true,
"notCreatable": true,
"fieldDefs":{
"skip": false
}
"notCreatable": true
}
@@ -24,6 +24,6 @@
"entity": "Attachment"
},
"fieldDefs":{
"skip": true
"skipOrmDefs": true
}
}
@@ -20,6 +20,6 @@
"notCreatable": true,
"filter": true,
"fieldDefs":{
"default":""
"notStorable":true
}
}
@@ -28,9 +28,13 @@ Espo.define('Crm:Views.Calendar.CalendarPage', 'View', function (Dep) {
el: '#main',
setup: function () {
var mode = this.options.mode || null;
if (!mode) {
var mode = this.getStorage().get('state', 'calendarMode') || null;
}
this.createView('calendar', 'Crm:Calendar.Calendar', {
date: this.options.date,
mode: this.options.mode,
mode: mode,
el: '#main > .calendar-container',
}, function (view) {
var first = true;
@@ -39,7 +43,10 @@ Espo.define('Crm:Views.Calendar.CalendarPage', 'View', function (Dep) {
this.getRouter().navigate('#Calendar/show/date=' + date + '&mode=' + mode);
}
first = false;
}.bind(this));
}, this);
this.listenTo(view, 'change:mode', function (mode) {
this.getStorage().set('state', 'calendarMode', mode);
}, this);
}.bind(this));
},
@@ -80,6 +80,7 @@ Espo.define('Crm:Views.Calendar.Calendar', ['View', 'lib!FullCalendar'], functio
this.$el.find('button[data-mode="' + mode + '"]').addClass('active');
this.$calendar.fullCalendar('changeView', mode);
this.updateDate();
this.trigger('change:mode', mode);
},
'click [data-action="refresh"]': function (e) {
this.$calendar.fullCalendar('refetchEvents');
@@ -92,7 +92,7 @@
<label>{{label}}</label>
</div>
{{#if ../editable}}
<div class="right"><a href="javascript:" data-action="edit-field" class="edit-field"><i class="glyphicon glyphicon-pencil"></i></a></div>
<div class="right"><a href="javascript:" data-action="editField" class="edit-field"><i class="glyphicon glyphicon-pencil"></i></a></div>
{{/if}}
</li>
{{/each}}
+11 -9
View File
@@ -75,25 +75,27 @@ _.extend(Espo.Acl.prototype, {
return true;
}
if (!value || value === 'no') {
return false;
}
if (typeof isOwner === 'undefined') {
return true;
}
if (isOwner && action == 'delete' && value === 'no') {
return this.check(controller, 'edit', isOwner);
}
if (!value || value === 'no') {
return false;
}
if (isOwner) {
if (value === 'own' || value === 'team') {
return true;
}
}
//if (inTeam) {
if (value === 'team') {
return true;
}
//}
if (value === 'team') {
return true;
}
return false;
}
+18 -18
View File
@@ -17,31 +17,31 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
Espo.define('Views.Admin.Layouts.Rows', 'Views.Admin.Layouts.Base', function (Dep) {
************************************************************************/
Espo.define('Views.Admin.Layouts.Rows', 'Views.Admin.Layouts.Base', function (Dep) {
return Dep.extend({
return Dep.extend({
template: 'admin.layouts.rows',
events: _.extend({
'click #layout a[data-action="editField"]': function (e) {
'click #layout a[data-action="editField"]': function (e) {
var data = {};
this.dataAttributes.forEach(function (attr) {
data[attr] = $(e.target).closest('li').data(Espo.Utils.toDom(attr))
});
});
this.openEditDialog(data);
},
}, Dep.prototype.events),
dataAttributes: null,
dataAttributesDefs: {},
editable: false,
data: function () {
return {
scope: this.scope,
@@ -54,14 +54,14 @@ Espo.define('Views.Admin.Layouts.Rows', 'Views.Admin.Layouts.Base', function (De
dataAttributesDefs: this.dataAttributesDefs,
editable: this.editable,
};
},
},
afterRender: function () {
$('#layout ul.enabled, #layout ul.disabled').sortable({
connectWith: '#layout ul.connected'
});
},
fetch: function () {
var layout = [];
$("#layout ul.enabled > li").each(function (i, el) {
@@ -71,19 +71,19 @@ Espo.define('Views.Admin.Layouts.Rows', 'Views.Admin.Layouts.Base', function (De
if (value) {
o[attr] = value;
}
});
});
layout.push(o);
}.bind(this));
return layout;
},
validate: function (layout) {
if (layout.length == 0) {
this.notify('Layout cannot be empty', 'error');
return false;
}
return true;
},
}
});
});
@@ -167,7 +167,7 @@ Espo.define('Views.Admin.LinkManager.Index', 'View', function (Dep) {
this.getMetadata().load(function () {
this.setupLinkData();
this.render();
}.bind(this));
}.bind(this), true);
}.bind(this));
},
@@ -343,7 +343,7 @@ Espo.define('Views.Admin.LinkManager.Modals.Edit', ['Views.Modal', 'Views.Admin.
this.getMetadata().load(function () {
this.trigger('after:save');
this.close();
}.bind(this));
}.bind(this), true);
}.bind(this));
},
@@ -31,11 +31,13 @@ Espo.define('Views.Email.Modals.Detail', ['Views.Modals.Detail', 'Views.Email.De
'label': 'Reply',
'style': 'danger'
});
this.listenToOnce(this.model, 'sync', function () {
setTimeout(function () {
this.model.set('isRead', true);
}.bind(this), 50);
}, this);
if (this.model) {
this.listenToOnce(this.model, 'sync', function () {
setTimeout(function () {
this.model.set('isRead', true);
}.bind(this), 50);
}, this);
}
},
@@ -220,7 +220,7 @@ Espo.define('Views.Fields.LinkMultiple', 'Views.Fields.Base', function (Dep) {
this.ids.forEach(function (id) {
names.push(this.getDetailLinkHtml(id));
}, this);
return names.join(', ');
return '<div>' + names.join('</div><div>') + '</div>';
}
},
@@ -152,7 +152,7 @@ Espo.define('Views.Modals.SelectRecords', 'Views.Modal', function (Dep) {
type: 'listSmall',
searchManager: searchManager,
checkAllResultDisabled: !this.massRelateEnabled,
disableButtons: true
buttonsDisabled: true
}, function (list) {
list.once('select', function (model) {
this.trigger('select', model);
+7 -2
View File
@@ -199,6 +199,8 @@ Espo.define('Views.Record.List', 'View', function (Dep) {
checkAllResultDisabled: false,
buttonsDisabled: false,
allResultIsChecked: false,
data: function () {
@@ -218,7 +220,7 @@ Espo.define('Views.Record.List', 'View', function (Dep) {
checkboxes: this.checkboxes,
massActionList: this.massActionList,
rows: this.rows,
topBar: paginationTop || this.checkboxes || (this.buttonList.length && !this.disableButtons),
topBar: paginationTop || this.checkboxes || (this.buttonList.length && !this.buttonsDisabled),
bottomBar: paginationBottom,
checkAllResultDisabled: this.checkAllResultDisabled,
buttonList: this.buttonList
@@ -235,7 +237,10 @@ Espo.define('Views.Record.List', 'View', function (Dep) {
this.rowActionsView = _.isUndefined(this.options.rowActionsView) ? this.rowActionsView : this.options.rowActionsView;
this.showMore = _.isUndefined(this.options.showMore) ? this.showMore : this.options.showMore;
this.disableButtons = this.options.disableButtons || false;
if ('buttonsDisabled' in this.options) {
this.buttonsDisabled = this.options.buttonsDisabled;
}
if ('checkAllResultDisabled' in this.options) {
this.checkAllResultDisabled = this.options.checkAllResultDisabled;
@@ -113,7 +113,7 @@ Espo.define('Views.Record.Panels.Relationship', ['Views.Record.Panels.Bottom', '
listLayout: listLayout,
checkboxes: false,
rowActionsView: this.defs.readOnly ? false : (this.defs.rowActionsView || this.rowActionsView),
disableButtons: true,
buttonsDisabled: true,
el: this.options.el + ' .list-container',
}, function (view) {
view.render();
+2 -2
View File
@@ -1,7 +1,7 @@
{
"labels": {
"Main page title": "Welcome to EspoCRM",
"Main page header": "Project-Id-Version: Russian Translation\nPOT-Creation-Date: \nPO-Revision-Date: \nLast-Translator: \nLanguage-Team: EspoCRM <infobox@espocrm.com>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nLanguage: ru_RU\nX-Generator: Poedit 1.6.5\n",
"Main page header": "",
"Start page title": "License Agreement",
"Step1 page title": "License Agreement",
"License Agreement": "License Agreement",
@@ -120,7 +120,7 @@
"windows": "<br> <pre>1. Find the httpd.conf file (usually you will find it in a folder called conf, config or something along those lines)<br>\n2. Inside the httpd.conf file uncomment the line LoadModule rewrite_module modules/mod_rewrite.so (remove the pound '#' sign from in front of the line)<br>\n3. Also find the line ClearModuleList is uncommented then find and make sure that the line AddModule mod_rewrite.c is not commented out.\n</pre>"
},
"microsoft-iis": {
"windows": "Project-Id-Version: Russian Translation\nPOT-Creation-Date: \nPO-Revision-Date: \nLast-Translator: \nLanguage-Team: EspoCRM <infobox@espocrm.com>\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nLanguage: ru_RU\nX-Generator: Poedit 1.6.5\n"
"windows": ""
}
},
"modRewriteHelp": {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"labels": {
"Main page title": "Ласкаво просимо EspoCRM",
"Main page header": "Project-Id-Version: \nPOT-Creation-Date: \nPO-Revision-Date: 2015-04-09 15:16+0300\nLast-Translator: alihor <ihor.aleksejev@gmail.com>\nLanguage-Team: EspoCRM <infobox@espocrm.com>\nLanguage: uk\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\nX-Generator: Virtaal 0.7.1\n",
"Main page header": "",
"Start page title": "Ліцензійна Угода",
"Step1 page title": "Ліцензійна Угода",
"License Agreement": "Ліцензійна Угода",