diff --git a/www/controllers/Task/Task.php b/www/controllers/Task/Task.php
index 405c4c85..4cef0c6b 100644
--- a/www/controllers/Task/Task.php
+++ b/www/controllers/Task/Task.php
@@ -820,9 +820,83 @@ public function getChildrenPid(int $pid)
}
/**
- * Get logs from a task
+ * Get task previous log lines
*/
- public function getMoreLogs(int $taskId, string $step, string $substepLastKey)
+ public function getPreviousLogLines(int $taskId, string $step, string $substepLastKey)
+ {
+ try {
+ /**
+ * If task log does not exist, throw an exception
+ */
+ if (!file_exists(MAIN_LOGS_DIR . '/' . $taskId . '.json')) {
+ throw new Exception('no log file found for this task.');
+ }
+
+ /**
+ * Load task log content
+ */
+ $content = file_get_contents(MAIN_LOGS_DIR . '/' . $taskId . '.json');
+
+ if ($content === false) {
+ throw new Exception('could not read log file.');
+ }
+
+ /**
+ * Decode JSON content
+ */
+ $content = json_decode($content, true);
+
+ if ($content === null) {
+ throw new Exception('could not decode log file.');
+ }
+
+ /**
+ * If step does not exist in the log, throw an exception
+ */
+ if (!array_key_exists($step, $content['steps'])) {
+ throw new Exception('step does not exist in the log.');
+ }
+
+ /**
+ * If substep does not exist in the log, throw an exception
+ */
+ if (!isset($substepLastKey, $content['steps'][$step]['substeps'][$substepLastKey])) {
+ throw new Exception('substep does not exist in the log.');
+ }
+
+ /**
+ * Return the 20 previous substeps before the provided substep key
+ */
+ $substeps = array_slice($content['steps'][$step]['substeps'], array_search($substepLastKey, array_keys($content['steps'][$step]['substeps'])) - 20, 20, true);
+
+ if (empty($substeps)) {
+ return '';
+ }
+
+ ob_start();
+
+ foreach ($substeps as $substepKey => $substep) {
+ $substepTitle = $substep['title'];
+ $substepNote = $substep['note'];
+ $substepStatus = $substep['status'];
+ $substepOutput = $substep['output'];
+ $substepStart = $substep['start'];
+ $substepDuration = $substep['duration'];
+
+ // Include substep template
+ include(ROOT . '/views/includes/containers/tasks/log/substep.inc.php');
+ }
+
+ return ob_get_clean();
+ } catch (Exception $e) {
+ throw new Exception('Cannot load more logs: ' . $e->getMessage());
+ }
+ }
+
+ /**
+ * Get task next log lines
+ */
+ public function getNextLogLines(int $taskId, string $step, string $substepLastKey)
{
try {
/**
diff --git a/www/controllers/ajax/task.php b/www/controllers/ajax/task.php
index 9bb7751b..f3ccddbc 100644
--- a/www/controllers/ajax/task.php
+++ b/www/controllers/ajax/task.php
@@ -88,11 +88,11 @@
}
/**
- * Get task log content on scroll
+ * Get task previous log lines on scroll
*/
-if ($_POST['action'] == 'getMoreLogs' and !empty($_POST['taskId']) and !empty($_POST['step']) and !empty($_POST['substepLastKey'])) {
+if ($_POST['action'] == 'get-previous-log-lines' and !empty($_POST['taskId']) and !empty($_POST['step']) and !empty($_POST['substepFirstKey'])) {
try {
- $content = $myTask->getMoreLogs($_POST['taskId'], $_POST['step'], $_POST['substepLastKey']);
+ $content = $myTask->getPreviousLogLines($_POST['taskId'], $_POST['step'], $_POST['substepFirstKey']);
} catch (\Exception $e) {
response(HTTP_BAD_REQUEST, $e->getMessage());
}
@@ -100,5 +100,17 @@
response(HTTP_OK, $content);
}
+/**
+ * Get task next log lines on scroll
+ */
+if ($_POST['action'] == 'get-next-log-lines' and !empty($_POST['taskId']) and !empty($_POST['step']) and !empty($_POST['substepLastKey'])) {
+ try {
+ $content = $myTask->getNextLogLines($_POST['taskId'], $_POST['step'], $_POST['substepLastKey']);
+ } catch (\Exception $e) {
+ response(HTTP_BAD_REQUEST, $e->getMessage());
+ }
+
+ response(HTTP_OK, $content);
+}
response(HTTP_BAD_REQUEST, 'Invalid action');
diff --git a/www/public/resources/js/events/task/actions.js b/www/public/resources/js/events/task/actions.js
index 9ce6a541..cbd884ce 100644
--- a/www/public/resources/js/events/task/actions.js
+++ b/www/public/resources/js/events/task/actions.js
@@ -1,10 +1,109 @@
/**
- * Event: load more logs on scroll down
+ * Event: show logfile
+ */
+$(document).on('click','.show-task-btn',function () {
+ var taskId = $(this).attr('task-id');
+
+ // Go to task page
+ window.location.href = '/run/' + taskId;
+});
+
+/**
+ * Event: print all log
+ */
+$(document).on('click','#display-log-btn',function () {
+ var display = $(this).attr('display');
+
+ if (display == 'true') {
+ $('.getPackagesDiv').css('display', 'block');
+ $('.signRepoDiv').css('display', 'block');
+ $('.createRepoDiv').css('display', 'block');
+ $('#display-log-btn').attr('display', 'false');
+ $('#display-log-btn').attr('title', 'Hide details');
+ $('#display-log-btn').find('img').attr('src', '/assets/icons/view.svg');
+ $('.task-step-content').show();
+ }
+
+ if (display == 'false') {
+ $('.getPackagesDiv').css('display', 'none');
+ $('.signRepoDiv').css('display', 'none');
+ $('.createRepoDiv').css('display', 'none');
+ $('#display-log-btn').attr('display', 'true');
+ $('#display-log-btn').attr('title', 'Show details');
+ $('#display-log-btn').find('img').attr('src', '/assets/icons/view-off.svg');
+ $('.task-step-content').hide();
+ }
+});
+
+/**
+ * Event: load more logs on scroll
*/
$('.task-step-content').scroll(function () {
var taskId = $(this).attr('task-id');
var step = $(this).attr('step');
+ /**
+ * Load more logs on scroll up
+ */
+ if ($(this).scrollTop() == 0) {
+ // Get first substep key
+ var substepFirstKey = $(this).find('.task-sub-step-content:first').attr('key');
+
+ // TODO debug
+ console.log('task: ' + taskId);
+ console.log('step: ' + step);
+ console.log('key: ' + substepFirstKey);
+
+ // If there is already a loading icon, then do not print another one
+ if ($('.task-step-content[task-id="' + taskId + '"][step="' + step + '"] .step-loading').length) {
+ return;
+ }
+
+ // Print loading icon
+ $('.task-step-content[task-id="' + taskId + '"][step="' + step + '"]').find('div.task-sub-step-container').prepend('\
+
\
+
\
+
Loading...
\
+
'
+ );
+
+ // Get more logs from server
+ // Server will return a html with the new logs
+ ajaxRequest(
+ // Controller:
+ 'task',
+ // Action:
+ 'get-previous-log-lines',
+ // Data:
+ {
+ taskId: taskId,
+ step: step,
+ substepFirstKey: substepFirstKey
+ },
+ // Print success alert:
+ false,
+ // Print error alert:
+ true,
+ // Reload containers:
+ [],
+ // Execute functions on success:
+ [
+ // Remove loading icon
+ "$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .step-loading').remove();",
+
+ // Prepend new logs
+ "$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .task-sub-step-container').prepend(jsonValue.message);",
+
+ // Delete previous logs and all below
+ // Start from substepFirstKey, keep 10 substeps below and remove the rest
+ "$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .task-sub-step-content[key=\"" + substepFirstKey + "\"]').nextAll().slice(10).remove();"
+ ]
+ );
+ }
+
+ /**
+ * Load more logs on scroll down
+ */
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
// Get last substep key
var substepLastKey = $(this).find('.task-sub-step-content:last').attr('key');
@@ -33,7 +132,7 @@ $('.task-step-content').scroll(function () {
// Controller:
'task',
// Action:
- 'getMoreLogs',
+ 'get-next-log-lines',
// Data:
{
taskId: taskId,
@@ -52,8 +151,146 @@ $('.task-step-content').scroll(function () {
"$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .step-loading').remove();",
// Append new logs
- "$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .task-sub-step-container').append(jsonValue.message);"
+ "$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .task-sub-step-container').append(jsonValue.message);",
+
+ // Delete previous logs and all above
+ // Start from substepLastKey, keep 10 substeps above and remove the rest
+ "$('.task-step-content[task-id=\"" + taskId + "\"][step=\"" + step + "\"] .task-sub-step-content[key=\"" + substepLastKey + "\"]').prevAll().slice(10).remove();"
]
);
}
+});
+
+/**
+ * Event: show or hide scheduled task informations
+ */
+$(document).on('click','.show-scheduled-task-info-btn',function (e) {
+ // Prevent parent to be triggered
+ e.stopPropagation();
+
+ var taskId = $(this).attr('task-id');
+
+ /**
+ * Show or hide task informations
+ */
+ $('.scheduled-task-info[task-id="' + taskId + '"]').toggle();
+});
+
+/**
+ * Event: disable scheduled task execution
+ */
+$(document).on('click','.disable-scheduled-task-btn',function (e) {
+ // Prevent parent to be triggered
+ e.stopPropagation();
+
+ var taskId = $(this).attr('task-id');
+
+ ajaxRequest(
+ // Controller:
+ 'task',
+ // Action:
+ 'disableTask',
+ // Data:
+ {
+ taskId: taskId,
+ },
+ // Print success alert:
+ true,
+ // Print error alert:
+ true,
+ // Reload containers:
+ ['tasks/list']
+ );
+});
+
+/**
+ * Event: enable scheduled task execution
+ */
+$(document).on('click','.enable-scheduled-task-btn',function (e) {
+ // Prevent parent to be triggered
+ e.stopPropagation();
+
+ var taskId = $(this).attr('task-id');
+
+ ajaxRequest(
+ // Controller:
+ 'task',
+ // Action:
+ 'enableTask',
+ // Data:
+ {
+ taskId: taskId,
+ },
+ // Print success alert:
+ true,
+ // Print error alert:
+ true,
+ // Reload containers:
+ ['tasks/list']
+ );
+});
+
+/**
+ * Event: cancel scheduled task
+ */
+$(document).on('click','.cancel-scheduled-task-btn',function (e) {
+ // Prevent parent to be triggered
+ e.stopPropagation();
+
+ var taskId = $(this).attr('task-id');
+
+ confirmBox(
+ {
+ 'title': 'Cancel and delete scheduled task',
+ 'message': 'Are you sure you want to cancel and delete this task?',
+ 'buttons': [
+ {
+ 'text': 'Delete',
+ 'color': 'red',
+ 'callback': function () {
+ ajaxRequest(
+ // Controller:
+ 'task',
+ // Action:
+ 'deleteTask',
+ // Data:
+ {
+ taskId: taskId,
+ },
+ // Print success alert:
+ true,
+ // Print error alert:
+ true,
+ // Reload containers:
+ ['tasks/list']
+ )
+ }
+ }]
+ }
+ );
+});
+
+/**
+ * Event: relaunch task
+ */
+$(document).on('click','.relaunch-task-btn',function (e) {
+ // Prevent parent to be triggered
+ e.stopPropagation();
+
+ var taskId = $(this).attr('task-id');
+
+ ajaxRequest(
+ // Controller:
+ 'task',
+ // Action:
+ 'relaunchTask',
+ // Data:
+ {
+ taskId: taskId,
+ },
+ // Print success alert:
+ true,
+ // Print error alert:
+ true
+ );
});
\ No newline at end of file
diff --git a/www/public/resources/js/run.js b/www/public/resources/js/run.js
deleted file mode 100644
index c4a99494..00000000
--- a/www/public/resources/js/run.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * Event: print full log
- */
-$(document).on('click','#display-log-btn',function () {
- var display = $(this).attr('display');
-
- if (display == 'true') {
- $('.getPackagesDiv').css('display', 'block');
- $('.signRepoDiv').css('display', 'block');
- $('.createRepoDiv').css('display', 'block');
- $('#display-log-btn').attr('display', 'false');
- $('#display-log-btn').attr('title', 'Hide details');
- $('#display-log-btn').find('img').attr('src', '/assets/icons/view.svg');
- $('.task-step-content').show();
- }
-
- if (display == 'false') {
- $('.getPackagesDiv').css('display', 'none');
- $('.signRepoDiv').css('display', 'none');
- $('.createRepoDiv').css('display', 'none');
- $('#display-log-btn').attr('display', 'true');
- $('#display-log-btn').attr('title', 'Show details');
- $('#display-log-btn').find('img').attr('src', '/assets/icons/view-off.svg');
- $('.task-step-content').hide();
- }
-});
-
-/**
- * Event: show logfile content
- */
-$(document).on('click','.show-task-btn',function () {
- var taskId = $(this).attr('task-id');
-
- // Go to task page
- window.location.href = '/run/' + taskId;
-});
-
-
-
-/**
- * Event: relaunch task
- */
-$(document).on('click','.relaunch-task-btn',function (e) {
- // Prevent parent to be triggered
- e.stopPropagation();
-
- var taskId = $(this).attr('task-id');
-
- ajaxRequest(
- // Controller:
- 'task',
- // Action:
- 'relaunchTask',
- // Data:
- {
- taskId: taskId,
- },
- // Print success alert:
- true,
- // Print error alert:
- true
- );
-});
-
-/**
- * Event: show or hide scheduled task informations
- */
-$(document).on('click','.show-scheduled-task-info-btn',function (e) {
- // Prevent parent to be triggered
- e.stopPropagation();
-
- var taskId = $(this).attr('task-id');
-
- /**
- * Show or hide task informations
- */
- $('.scheduled-task-info[task-id="' + taskId + '"]').toggle();
-});
-
-/**
- * Event: disable scheduled task execution
- */
-$(document).on('click','.disable-scheduled-task-btn',function (e) {
- // Prevent parent to be triggered
- e.stopPropagation();
-
- var taskId = $(this).attr('task-id');
-
- ajaxRequest(
- // Controller:
- 'task',
- // Action:
- 'disableTask',
- // Data:
- {
- taskId: taskId,
- },
- // Print success alert:
- true,
- // Print error alert:
- true,
- // Reload containers:
- ['tasks/list']
- );
-});
-
-/**
- * Event: enable scheduled task execution
- */
-$(document).on('click','.enable-scheduled-task-btn',function (e) {
- // Prevent parent to be triggered
- e.stopPropagation();
-
- var taskId = $(this).attr('task-id');
-
- ajaxRequest(
- // Controller:
- 'task',
- // Action:
- 'enableTask',
- // Data:
- {
- taskId: taskId,
- },
- // Print success alert:
- true,
- // Print error alert:
- true,
- // Reload containers:
- ['tasks/list']
- );
-});
-
-/**
- * Event: cancel scheduled task
- */
-$(document).on('click','.cancel-scheduled-task-btn',function (e) {
- // Prevent parent to be triggered
- e.stopPropagation();
-
- var taskId = $(this).attr('task-id');
-
- confirmBox(
- {
- 'title': 'Cancel and delete scheduled task',
- 'message': 'Are you sure you want to cancel and delete this task?',
- 'buttons': [
- {
- 'text': 'Delete',
- 'color': 'red',
- 'callback': function () {
- ajaxRequest(
- // Controller:
- 'task',
- // Action:
- 'deleteTask',
- // Data:
- {
- taskId: taskId,
- },
- // Print success alert:
- true,
- // Print error alert:
- true,
- // Reload containers:
- ['tasks/list']
- )
- }
- }]
- }
- );
-});
diff --git a/www/public/resources/styles/main.css b/www/public/resources/styles/main.css
index e5e82c9a..ffe0f394 100644
--- a/www/public/resources/styles/main.css
+++ b/www/public/resources/styles/main.css
@@ -362,13 +362,12 @@ article {
align-items: center;
align-content: flex-start;
justify-content: space-evenly;
- column-gap: 2px;
padding: 6px 0 0 0 !important;
position: inherit !important;
}
.item-info img, .item-env-info img {
- height: 17px;
+ height: 19px;
margin-left: 4px !important;
margin-right: 4px !important;
}
diff --git a/www/views/includes/containers/tasks/log/step.inc.php b/www/views/includes/containers/tasks/log/step.inc.php
index 94cfad3e..a9e2ad79 100644
--- a/www/views/includes/containers/tasks/log/step.inc.php
+++ b/www/views/includes/containers/tasks/log/step.inc.php
@@ -17,7 +17,7 @@
Running';
+ echo '
Running
';
}
if ($step['status'] == 'completed') {
echo '
Completed
';
diff --git a/www/views/includes/footer.inc.php b/www/views/includes/footer.inc.php
index bd9a0b58..31b3bad5 100644
--- a/www/views/includes/footer.inc.php
+++ b/www/views/includes/footer.inc.php
@@ -71,7 +71,7 @@
$jsFiles = ['functions/environment', 'events/environment/actions', 'settings'];
}
if (__ACTUAL_URI__[1] == 'run') {
- $jsFiles = ['run', 'events/task/actions'];
+ $jsFiles = ['events/task/actions'];
}
if (__ACTUAL_URI__[1] == 'history') {
$jsFiles = ['events/history/actions'];
diff --git a/www/views/includes/repos-list.inc.php b/www/views/includes/repos-list.inc.php
index 953a73f6..561831e7 100644
--- a/www/views/includes/repos-list.inc.php
+++ b/www/views/includes/repos-list.inc.php
@@ -296,7 +296,6 @@
- Calc.
';
} ?>
+
+ Calc.