timeline bust timeframes

This commit is contained in:
yuri
2018-11-02 12:44:20 +02:00
parent 4fd5555146
commit 20a139ca0a
6 changed files with 248 additions and 42 deletions
@@ -54,7 +54,7 @@ class EntityManager
private $linkForbiddenNameList = ['posts', 'stream', 'subscription'];
private $forbiddenEntityTypeNameList = ['PortalUser', 'ApiUser'];
private $forbiddenEntityTypeNameList = ['PortalUser', 'ApiUser', 'Timeline'];
public function __construct(Metadata $metadata, Language $language, File\Manager $fileManager, Config $config, Container $container = null)
{
@@ -69,19 +69,58 @@ class Activities extends \Espo\Core\Controllers\Base
if ($teamIdList) {
$teamIdList = explode(',', $teamIdList);
return $userResultList = $service->getEventsForTeams($teamIdList, $from, $to, $scopeList);
return $userResultList = $service->getTeamsEventList($teamIdList, $from, $to, $scopeList);
}
if ($userIdList) {
$userIdList = explode(',', $userIdList);
return $service->getEventsForUsers($userIdList, $from, $to, $scopeList);
return $service->getUsersEventList($userIdList, $from, $to, $scopeList);
} else {
if (!$userId) {
$userId = $this->getUser()->id;
}
}
return $service->getEvents($userId, $from, $to, $scopeList);
return $service->getEventList($userId, $from, $to, $scopeList);
}
public function getActionGetTimeline($params, $data, $request)
{
if (!$this->getAcl()->check('Calendar')) {
throw new Forbidden();
}
$from = $request->get('from');
$to = $request->get('to');
if (empty($from) || empty($to)) {
throw new BadRequest();
}
if (strtotime($to) - strtotime($from) > $this->maxCalendarRange * 24 * 3600) {
throw new Forbidden('Too long range.');
}
$service = $this->getService('Activities');
$scopeList = null;
if ($request->get('scopeList') !== null) {
$scopeList = explode(',', $request->get('scopeList'));
}
$userId = $request->get('userId');
$userIdList = $request->get('userIdList');
if ($userIdList) {
$userIdList = explode(',', $userIdList);
} else {
$userIdList = [];
}
if ($userId) {
$userIdList[] = $userId;
}
return $service->getUsersTimeline($userIdList, $from, $to, $scopeList);
}
public function actionListUpcoming($params, $data, $request)
@@ -18,6 +18,14 @@
"action": "listCalendarEvents"
}
},
{
"route": "/Timeline",
"method": "get",
"params": {
"controller": "Activities",
"action": "getTimeline"
}
},
{
"route": "/Activities/:scope/:id/:name/list/:entityType",
"method": "get",
@@ -860,7 +860,7 @@ class Activities extends \Espo\Core\Services\Base
return $result;
}
protected function getCalendarMeetingQuery($userId, $from, $to)
protected function getCalendarMeetingQuery($userId, $from, $to, $skipAcl)
{
$selectManager = $this->getSelectManagerFactory()->create('Meeting');
@@ -902,12 +902,14 @@ class Activities extends \Espo\Core\Services\Base
'customJoin' => ''
);
$selectManager->applyAccess($selectParams);
if (!$skipAcl) {
$selectManager->applyAccess($selectParams);
}
return $this->getEntityManager()->getQuery()->createSelectQuery('Meeting', $selectParams);
}
protected function getCalendarCallQuery($userId, $from, $to)
protected function getCalendarCallQuery($userId, $from, $to, $skipAcl)
{
$selectManager = $this->getSelectManagerFactory()->create('Call');
@@ -949,12 +951,14 @@ class Activities extends \Espo\Core\Services\Base
'customJoin' => ''
);
$selectManager->applyAccess($selectParams);
if (!$skipAcl) {
$selectManager->applyAccess($selectParams);
}
return $this->getEntityManager()->getQuery()->createSelectQuery('Call', $selectParams);
}
protected function getCalendarTaskQuery($userId, $from, $to)
protected function getCalendarTaskQuery($userId, $from, $to, $skipAcl = false)
{
$selectManager = $this->getSelectManagerFactory()->create('Task');
@@ -1002,12 +1006,14 @@ class Activities extends \Espo\Core\Services\Base
$selectParams['whereClause'][] = ['assignedUserId' => $userId];
}
$selectManager->applyAccess($selectParams);
if (!$skipAcl) {
$selectManager->applyAccess($selectParams);
}
return $this->getEntityManager()->getQuery()->createSelectQuery('Task', $selectParams);
}
protected function getCalendarSelectParams($scope, $userId, $from, $to)
protected function getCalendarSelectParams($scope, $userId, $from, $to, $skipAcl = false)
{
$selectManager = $this->getSelectManagerFactory()->create($scope);
@@ -1079,25 +1085,27 @@ class Activities extends \Espo\Core\Services\Base
$selectParams['leftJoins'][] = 'assignedUsers';
}
$selectManager->applyAccess($selectParams);
if (!$skipAcl) {
$selectManager->applyAccess($selectParams);
}
return $selectParams;
}
protected function getCalendarQuery($scope, $userId, $from, $to)
protected function getCalendarQuery($scope, $userId, $from, $to, $skipAcl = false)
{
$selectManager = $this->getSelectManagerFactory()->create($scope);
if (method_exists($selectManager, 'getCalendarSelectParams')) {
$selectParams = $selectManager->getCalendarSelectParams($userId, $from, $to);
$selectParams = $selectManager->getCalendarSelectParams($userId, $from, $to, $skipAcl);
return $this->getEntityManager()->getQuery()->createSelectQuery($scope, $selectParams);
}
$methodName = 'getCalendar' . $scope . 'Query';
if (method_exists($this, $methodName)) {
return $this->$methodName($userId, $from, $to);
return $this->$methodName($userId, $from, $to, $skipAcl);
}
$selectParams = $this->getCalendarSelectParams($scope, $userId, $from, $to);
$selectParams = $this->getCalendarSelectParams($scope, $userId, $from, $to, $skipAcl);
return $this->getEntityManager()->getQuery()->createSelectQuery($scope, $selectParams);
}
@@ -1178,7 +1186,35 @@ class Activities extends \Espo\Core\Services\Base
return $selectParams;
}
public function getUsersTimeline($userIdList, $from, $to, $scopeList = null)
{
$resultData = (object) [];
foreach ($userIdList as $userId) {
$userData = (object) [
'eventList' => [],
'busyRangeList' => []
];
try {
$userData->eventList = $this->getEventList($userId, $from, $to, $scopeList);
$userData->busyRangeList = $this->getBusyRangeList($userId, $from, $to, $scopeList);
} catch (\Exception $e) {
if ($e instanceof Forbidden) {
continue;
}
throw new \Exception($e->getMessage(), $e->getCode(), $e);
}
$resultData->$userId = $userData;
}
return $resultData;
}
public function getEventsForUsers($userIdList, $from, $to, $scopeList = null)
{
return $this->getUsersEventList($userIdList, $from, $to, $scopeList);
}
public function getUsersEventList($userIdList, $from, $to, $scopeList = null)
{
$resultList = [];
foreach ($userIdList as $userId) {
@@ -1199,6 +1235,11 @@ class Activities extends \Espo\Core\Services\Base
}
public function getEventsForTeams($teamIdList, $from, $to, $scopeList = null)
{
return $this->getTeamsEventList($teamIdList, $from, $to, $scopeList);
}
public function getTeamsEventList($teamIdList, $from, $to, $scopeList = null)
{
if ($this->getAcl()->get('userPermission') === 'no') {
throw new Forbidden("User Permission not allowing to view calendars of other users.");
@@ -1226,10 +1267,9 @@ class Activities extends \Espo\Core\Services\Base
$userNames->{$user->id} = $user->get('name');
}
$eventList = [];
foreach ($userIdList as $userId) {
$userEventList = $this->getEvents($userId, $from, $to, $scopeList);
$userEventList = $this->getEventList($userId, $from, $to, $scopeList);
foreach ($userEventList as $event) {
foreach ($eventList as &$e) {
if ($e['scope'] == $event['scope'] && $e['id'] == $event['id']) {
@@ -1255,7 +1295,84 @@ class Activities extends \Espo\Core\Services\Base
return $eventList;
}
public function getEvents($userId, $from, $to, $scopeList = null)
public function getBusyRangeList($userId, $from, $to, $scopeList = null)
{
$rangeList = [];
$eventList = $this->getEventList($userId, $from, $to, $scopeList, true);
foreach ($eventList as $i => $item) {
$eventList[$i] = (object) $item;
}
foreach ($eventList as $event) {
if (empty($event->dateStart) || empty($event->dateEnd)) continue;
try {
$start = new \DateTime($event->dateStart);
$end = new \DateTime($event->dateEnd);
foreach ($rangeList as &$range) {
if (
$start->getTimestamp() < $range->start->getTimestamp()
&&
$end->getTimestamp() > $range->end->getTimestamp()
) {
$range->dateStart = $event->dateStart;
$range->start = $start;
$range->dateEnd = $event->dateEnd;
$range->end = $end;
continue 2;
}
if (
$start->getTimestamp() < $range->start->getTimestamp()
&&
$end->getTimestamp() > $range->start->getTimestamp()
) {
$range->dateStart = $event->dateStart;
$range->start = $start;
if ($end->getTimestamp() > $range->end->getTimestamp()) {
$range->dateEnd = $event->dateEnd;
$range->end = $end;
}
continue 2;
}
if (
$start->getTimestamp() < $range->end->getTimestamp()
&&
$end->getTimestamp() > $range->end->getTimestamp()
) {
$range->dateEnd = $event->dateEnd;
$range->end = $end;
if ($start->getTimestamp() < $range->start->getTimestamp()) {
$range->dateStart = $event->dateStart;
$range->start = $start;
}
continue 2;
}
}
$busyItem = (object) [
'dateStart' => $event->dateStart,
'dateEnd' => $event->dateEnd,
'start' => $start,
'end' => $end
];
$rangeList[] = $busyItem;
} catch (\Exception $e) {}
}
foreach ($rangeList as &$item) {
unset($item->start);
unset($item->end);
}
return $rangeList;
}
public function getEventList($userId, $from, $to, $scopeList = null, $skipAcl = false)
{
$user = $this->getEntityManager()->getEntity('User', $userId);
if (!$user) {
@@ -1278,8 +1395,8 @@ class Activities extends \Espo\Core\Services\Base
continue;
}
if ($this->getAcl()->checkScope($scope)) {
if ($this->getMetadata()->get('scopes.' . $scope . '.calendar')) {
$sqlPartList[] = $this->getCalendarQuery($scope, $userId, $from, $to);
if ($this->getMetadata()->get(['scopes', $scope, 'calendar'])) {
$sqlPartList[] = $this->getCalendarQuery($scope, $userId, $from, $to, $skipAcl);
}
}
}
@@ -1292,9 +1409,14 @@ class Activities extends \Espo\Core\Services\Base
$sth = $pdo->prepare($sql);
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
$rowList = $sth->fetchAll(PDO::FETCH_ASSOC);
return $rows;
return $rowList;
}
public function getEvents($userId, $from, $to, $scopeList = null, $skipAcl = false)
{
return $this->getEventList($userId, $from, $to, $scopeList, $skipAcl);
}
public function removeReminder($id)
@@ -317,18 +317,29 @@ Espo.define('crm:views/calendar/timeline', ['view', 'lib!vis'], function (Dep, V
convertEvent: function (o) {
var userId = o.userId || this.userList[0].id || this.getUser().id;
var event = {
content: o.name,
title: o.name,
id: userId + '-' + o.scope + '-' + o.id,
group: userId,
'record-id': o.id,
scope: o.scope,
status: o.status,
'date-start': o.dateStart,
'date-end': o.dateEnd,
type: 'range'
};
var event;
if (o.isBusyRange) {
var event = {
className: 'busy',
group: userId,
'date-start': o.dateStart,
'date-end': o.dateEnd,
type: 'background'
};
} else {
event = {
content: o.name,
title: o.name,
id: userId + '-' + o.scope + '-' + o.id,
group: userId,
'record-id': o.id,
scope: o.scope,
status: o.status,
'date-start': o.dateStart,
'date-end': o.dateEnd,
type: 'range'
};
}
this.eventAttributes.forEach(function (attr) {
event[attr] = o[attr];
@@ -348,6 +359,10 @@ Espo.define('crm:views/calendar/timeline', ['view', 'lib!vis'], function (Dep, V
}
}
if (o.isBusyRange) {
return event;
}
if (~this.allDayScopeList.indexOf(o.scope)) {
event.type = 'box';
if (event.end) {
@@ -405,8 +420,8 @@ Espo.define('crm:views/calendar/timeline', ['view', 'lib!vis'], function (Dep, V
convertEventList: function (list) {
var resultList = [];
list.forEach(function (o) {
var event = this.convertEvent(o);
list.forEach(function (iten) {
var event = this.convertEvent(iten);
if (!event) return;
resultList.push(event);
}, this);
@@ -778,7 +793,7 @@ Espo.define('crm:views/calendar/timeline', ['view', 'lib!vis'], function (Dep, V
var fromString = from.utc().format(this.getDateTime().internalDateTimeFormat);
var toString = to.utc().format(this.getDateTime().internalDateTimeFormat);
var url = 'Activities?from=' + fromString + '&to=' + toString;
var url = 'Timeline?from=' + fromString + '&to=' + toString;
var userIdList = this.userList.map(function (user) {
return user.id
}, this);
@@ -794,9 +809,27 @@ Espo.define('crm:views/calendar/timeline', ['view', 'lib!vis'], function (Dep, V
this.ajaxGetRequest(url).then(function (data) {
this.fetchedStart = from.clone();
this.fetchedEnd = to.clone();
var eventList = [];
var eventList = this.convertEventList(data);
callback(eventList);
for (var userId in data) {
var userEventList = data[userId].eventList;
userEventList.forEach(function (item) {
item.userId = userId;
eventList.push(item);
}, this);
if (userId == this.getUser().id) continue;
var userBusyRangeList = data[userId].busyRangeList;
userBusyRangeList.forEach(function (item) {
item.userId = userId;
item.isBusyRange = true;
eventList.push(item);
}, this);
}
var convertedEventList = this.convertEventList(eventList);
callback(convertedEventList);
this.notify(false);
}.bind(this));
},
@@ -42,11 +42,11 @@
}
.vis-item.event-canceled .vis-item-content {
text-decoration: line-through !important;
text-decoration: line-through !important;
}
.vis-item.vis-range, .vis-item.vis-box {
border-radius: 0 !important;
border-radius: 0 !important;
}
.vis-current-time {
@@ -61,4 +61,8 @@
.calendar-container .timeline .vis-tooltip {
display: none;
}
.vis-item.vis-background.busy {
background-color: @gray-lighter;
}