Skip to content

Commit

Permalink
Schedule grid filter improvements and Folder css adjustments (#2181)
Browse files Browse the repository at this point in the history
* Folders : Improve css
* Schedule : Add two new filters to the grid for direct and shared schedules.
* Schedule : Improve SQL for shared and direct grid filtering. Add comments to each statement.
* Schedule Grid : Improve the SQL filter further. add date filters to the sub queries
  • Loading branch information
PeterMis authored Oct 30, 2023
1 parent 612190a commit be5ed68
Show file tree
Hide file tree
Showing 14 changed files with 312 additions and 113 deletions.
2 changes: 2 additions & 0 deletions lib/Controller/Schedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -2235,6 +2235,8 @@ public function grid(Request $request, Response $response)
'name' => $params->getString('name'),
'useRegexForName' => $params->getCheckbox('useRegexForName'),
'logicalOperatorName' => $params->getString('logicalOperatorName'),
'directSchedule' => $params->getCheckbox('directSchedule'),
'sharedSchedule' => $params->getCheckbox('sharedSchedule'),
'gridFilter' => 1,
], $params)
);
Expand Down
145 changes: 143 additions & 2 deletions lib/Factory/ScheduleFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,149 @@ public function query($sortOrder = null, $filterBy = [])
// End both dates

if ($parsedFilter->getIntArray('displayGroupIds') != null) {
$body .= ' AND `schedule`.eventId IN (SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
WHERE displayGroupId IN (' . implode(',', $parsedFilter->getIntArray('displayGroupIds')) . ')) ';
// parameterize the selected display/groups and number of selected display/groups
$selectedDisplayGroupIds = implode(',', $parsedFilter->getIntArray('displayGroupIds'));
$numberOfSelectedDisplayGroups = count($parsedFilter->getIntArray('displayGroupIds'));

// build date filter for sub-queries for shared schedules
$sharedScheduleDateFilter = '';
if ($parsedFilter->getInt('futureSchedulesFrom') !== null
&& $parsedFilter->getInt('futureSchedulesTo') === null
) {
// Get schedules that end after this date, or that recur after this date
$sharedScheduleDateFilter .= ' AND (IFNULL(`schedule`.toDt, `schedule`.fromDt) >= :futureSchedulesFrom
OR `schedule`.recurrence_range >= :futureSchedulesFrom OR (IFNULL(`schedule`.recurrence_range, 0) = 0)
AND IFNULL(`schedule`.recurrence_type, \'\') <> \'\') ';
$params['futureSchedulesFrom'] = $parsedFilter->getInt('futureSchedulesFrom');
}

if ($parsedFilter->getInt('futureSchedulesFrom') !== null
&& $parsedFilter->getInt('futureSchedulesTo') !== null
) {
// Get schedules that end after this date, or that recur after this date
$sharedScheduleDateFilter .= ' AND ((schedule.fromDt < :futureSchedulesTo
AND IFNULL(`schedule`.toDt, `schedule`.fromDt) >= :futureSchedulesFrom)
OR `schedule`.recurrence_range >= :futureSchedulesFrom OR (IFNULL(`schedule`.recurrence_range, 0) = 0
AND IFNULL(`schedule`.recurrence_type, \'\') <> \'\') ) ';
$params['futureSchedulesFrom'] = $parsedFilter->getInt('futureSchedulesFrom');
$params['futureSchedulesTo'] = $parsedFilter->getInt('futureSchedulesTo');
}

// non Schedule grid filter, keep it the way it was.
if ($parsedFilter->getInt('sharedSchedule') === null &&
$parsedFilter->getInt('directSchedule') === null
) {
$body .= ' AND `schedule`.eventId IN (
SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
WHERE displayGroupId IN (' . $selectedDisplayGroupIds . ')
) ';
} else {
// Schedule grid query
// check what options we were provided with and adjust query accordingly.
$sharedSchedule = ($parsedFilter->getInt('sharedSchedule') === 1);
$directSchedule = ($parsedFilter->getInt('directSchedule') === 1);

// shared and direct
// events scheduled directly on the selected displays/groups
// and scheduled on all selected displays/groups
// Example : Two Displays selected, return only events scheduled directly to both of them
if ($sharedSchedule && $directSchedule) {
$body .= ' AND `schedule`.eventId IN (
SELECT `lkscheduledisplaygroup`.eventId
FROM `lkscheduledisplaygroup`
INNER JOIN `schedule` ON `schedule`.eventId = `lkscheduledisplaygroup`.eventId
WHERE displayGroupId IN (' . $selectedDisplayGroupIds . ')' .
$sharedScheduleDateFilter . '
GROUP BY eventId
HAVING COUNT(DISTINCT displayGroupId) >= ' .
$numberOfSelectedDisplayGroups .
') ';
}

// shared and not direct
// 1 - events scheduled on the selected display/groups
// 2 - events scheduled on a display group selected display is a member of
// 3 - events scheduled on a parent display group of selected display group
// and scheduled on all selected displays/groups
// Example : Two Displays selected, return only events scheduled directly to both of them
if ($sharedSchedule && !$directSchedule) {
$body .= ' AND (
( `schedule`.eventId IN (
SELECT `lkscheduledisplaygroup`.eventId
FROM `lkscheduledisplaygroup`
INNER JOIN `schedule` ON `schedule`.eventId = `lkscheduledisplaygroup`.eventId
WHERE displayGroupId IN (' . $selectedDisplayGroupIds . ')' .
$sharedScheduleDateFilter . '
GROUP BY eventId
HAVING COUNT(DISTINCT displayGroupId) >= ' . $numberOfSelectedDisplayGroups . '
))
OR `schedule`.eventID IN (
SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
INNER JOIN `schedule` ON `schedule`.eventId = `lkscheduledisplaygroup`.eventId
INNER JOIN `lkdgdg` ON `lkdgdg`.parentId = `lkscheduledisplaygroup`.displayGroupId
INNER JOIN `lkdisplaydg` ON lkdisplaydg.DisplayGroupID = `lkdgdg`.childId
WHERE `lkdisplaydg`.DisplayID IN (
SELECT lkdisplaydg.displayId FROM lkdisplaydg
INNER JOIN displaygroup ON lkdisplaydg.displayGroupId = displaygroup.displayGroupId
WHERE lkdisplaydg.displayGroupId IN (' . $selectedDisplayGroupIds . ')
AND displaygroup.isDisplaySpecific = 1 ) ' .
$sharedScheduleDateFilter . '
GROUP BY eventId
HAVING COUNT(DISTINCT `lkdisplaydg`.displayId) >= ' .
$numberOfSelectedDisplayGroups . '
)
OR `schedule`.eventID IN (
SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
INNER JOIN `schedule` ON `schedule`.eventId = `lkscheduledisplaygroup`.eventId
INNER JOIN `lkdgdg` ON `lkdgdg`.parentId = `lkscheduledisplaygroup`.displayGroupId
WHERE `lkscheduledisplaygroup`.displayGroupId IN (
SELECT lkdgdg.childId FROM lkdgdg
WHERE lkdgdg.parentId IN (' . $selectedDisplayGroupIds .') AND lkdgdg.depth > 0)' .
$sharedScheduleDateFilter . '
GROUP BY eventId
HAVING COUNT(DISTINCT `lkscheduledisplaygroup`.displayGroupId) >= ' .
$numberOfSelectedDisplayGroups . '
)
) ';
}

// not shared and direct (old default)
// events scheduled directly on selected displays/groups
if (!$sharedSchedule && $directSchedule) {
$body .= ' AND `schedule`.eventId IN (
SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
WHERE displayGroupId IN (' . $selectedDisplayGroupIds . ')
) ';
}

// not shared and not direct (new default)
// 1 - events scheduled on the selected display/groups
// 2 - events scheduled on a display group selected display is a member of
// 3 - events scheduled on a parent display group of selected display group
if (!$sharedSchedule && !$directSchedule) {
$body .= ' AND (
( `schedule`.eventId IN (SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
WHERE displayGroupId IN (' . $selectedDisplayGroupIds . ')) )
OR `schedule`.eventID IN (
SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
INNER JOIN `lkdgdg` ON `lkdgdg`.parentId = `lkscheduledisplaygroup`.displayGroupId
INNER JOIN `lkdisplaydg` ON lkdisplaydg.DisplayGroupID = `lkdgdg`.childId
WHERE `lkdisplaydg`.DisplayID IN (
SELECT lkdisplaydg.displayId FROM lkdisplaydg
INNER JOIN displaygroup ON lkdisplaydg.displayGroupId = displaygroup.displayGroupId
WHERE lkdisplaydg.displayGroupId IN (' . $selectedDisplayGroupIds . ')
AND displaygroup.isDisplaySpecific = 1 )
)
OR `schedule`.eventID IN (
SELECT `lkscheduledisplaygroup`.eventId FROM `lkscheduledisplaygroup`
INNER JOIN `lkdgdg` ON `lkdgdg`.parentId = `lkscheduledisplaygroup`.displayGroupId
WHERE `lkscheduledisplaygroup`.displayGroupId IN (
SELECT lkdgdg.childId FROM lkdgdg
WHERE lkdgdg.parentId IN (' . $selectedDisplayGroupIds .') AND lkdgdg.depth > 0)
)
) ';
}
}
}

// Future schedules?
Expand Down
24 changes: 13 additions & 11 deletions views/campaign-page.twig
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,25 @@
</div>

<div class="row">
<div class="col-sm-2 p-3 bg-light" id="grid-folder-filter">
<input id="jstree-search" class="form-control" type="text" placeholder="{% trans "Search" %}">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button">
<label class="form-check-label" for="folder-tree-clear-selection-button" title="{% trans "Search in all folders" %}">{% trans "All Folders" %}</label>
<div class="col-sm-2 grid-folder-tree-container" id="grid-folder-filter">
<div class="p-3 mr-2">
<input id="jstree-search" class="form-control" type="text" placeholder="{% trans "Search" %}">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button">
<label class="form-check-label" for="folder-tree-clear-selection-button" title="{% trans "Search in all folders" %}">{% trans "All Folders" %}</label>
</div>
<div class="folder-search-no-results d-none">
<p>{% trans 'No Folders matching the search term' %}</p>
</div>
<div id="container-folder-tree"></div>
</div>
<div class="folder-search-no-results d-none">
<p>{% trans 'No Folders matching the search term' %}</p>
</div>
<div id="container-folder-tree"></div>
</div>
<div class="folder-controller d-none">
<button type="button" id="folder-tree-select-folder-button" class="btn btn-outline-secondary" title="{% trans "Open / Close Folder Search options" %}"><i class="fas fa-folder fa-1x"></i></button>
<div id="breadcrumbs" class="mt-2 pl-2"></div>
</div>
<div id="datatable-container" class="card col-sm-10 pt-4 px-2">
<div class="XiboData">
<div id="datatable-container" class="col-sm-10 pr-0">
<div class="XiboData card pt-4 px-2">
<table id="campaigns" class="table table-striped" data-content-type="campaign" data-content-id-name="campaignId" data-state-preference-name="campaignGrid" style="width: 100%;">
<thead>
<tr>
Expand Down
24 changes: 13 additions & 11 deletions views/dataset-page.twig
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,25 @@
</div>

<div class="row">
<div class="col-sm-2 p-3 bg-light" id="grid-folder-filter">
<input id="jstree-search" class="form-control" type="text" placeholder="{% trans "Search" %}">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button">
<label class="form-check-label" for="folder-tree-clear-selection-button" title="{% trans "Search in all folders" %}">{% trans "All Folders" %}</label>
</div>
<div class="folder-search-no-results d-none">
<p>{% trans 'No Folders matching the search term' %}</p>
<div class="col-sm-2 grid-folder-tree-container" id="grid-folder-filter">
<div class="p-3 mr-2">
<input id="jstree-search" class="form-control" type="text" placeholder="{% trans "Search" %}">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button">
<label class="form-check-label" for="folder-tree-clear-selection-button" title="{% trans "Search in all folders" %}">{% trans "All Folders" %}</label>
</div>
<div class="folder-search-no-results d-none">
<p>{% trans 'No Folders matching the search term' %}</p>
</div>
<div id="container-folder-tree"></div>
</div>
<div id="container-folder-tree"></div>
</div>
<div class="folder-controller d-none">
<button type="button" id="folder-tree-select-folder-button" class="btn btn-outline-secondary" title="{% trans "Open / Close Folder Search options" %}"><i class="fas fa-folder fa-1x"></i></button>
<div id="breadcrumbs" class="mt-2 pl-2"></div>
</div>
<div id="datatable-container" class="card col-sm-10 pt-4 px-2">
<div class="XiboData">
<div id="datatable-container" class="col-sm-10 pr-0">
<div class="XiboData card pt-4 px-2">
<table id="datasets" class="table table-striped" data-state-preference-name="dataSetGrid" style="width: 100%;">
<thead>
<tr>
Expand Down
24 changes: 13 additions & 11 deletions views/display-page.twig
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,18 @@
</div>
</div>
<div class="row">
<div class="col-sm-2 p-3 bg-light" id="grid-folder-filter">
<input id="jstree-search" class="form-control" type="text" placeholder="{% trans "Search" %}">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button">
<label class="form-check-label" for="folder-tree-clear-selection-button" title="{% trans "Search in all folders" %}">{% trans "All Folders" %}</label>
</div>
<div class="folder-search-no-results d-none">
<p>{% trans 'No Folders matching the search term' %}</p>
<div class="col-sm-2 grid-folder-tree-container" id="grid-folder-filter">
<div class="p-3 mr-2">
<input id="jstree-search" class="form-control" type="text" placeholder="{% trans "Search" %}">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="folder-tree-clear-selection-button">
<label class="form-check-label" for="folder-tree-clear-selection-button" title="{% trans "Search in all folders" %}">{% trans "All Folders" %}</label>
</div>
<div class="folder-search-no-results d-none">
<p>{% trans 'No Folders matching the search term' %}</p>
</div>
<div id="container-folder-tree"></div>
</div>
<div id="container-folder-tree"></div>
</div>
<div class="folder-controller d-none">
<button type="button" id="folder-tree-select-folder-button" class="btn btn-outline-secondary" title="{{ "Open / Close Folder Search options"|trans }}"><i class="fas fa-folder fa-1x"></i></button>
Expand All @@ -200,8 +202,8 @@
<button type="button" id="list_button" class="btn btn-primary" title="{{ "List"|trans }}"><i class="fa fa-list"></i></button>
</div>

<div id="datatable-container" class="card col-sm-10 pt-4 px-2">
<div class="XiboData">
<div id="datatable-container" class="col-sm-10 pr-0">
<div class="XiboData card pt-4 px-2">
<table id="displays" class="table table-striped" data-content-type="display" data-content-id-name="displayId" data-state-preference-name="displayGrid" style="width: 100%;">
<thead>
<tr>
Expand Down
Loading

0 comments on commit be5ed68

Please sign in to comment.