1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-02 04:15:28 +02:00

feat(log-viewer): introduce the log viewer component (#1666)

This commit is contained in:
Anthony Lapenna 2018-02-28 07:19:28 +01:00 committed by GitHub
parent 81de2a5afb
commit 0c5152fb5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 458 additions and 304 deletions

View file

@ -196,7 +196,7 @@
<td ng-if="$ctrl.settings.showQuickActionStats || $ctrl.settings.showQuickActionLogs || $ctrl.settings.showQuickActionConsole || $ctrl.settings.showQuickActionInspect">
<div class="btn-group btn-group-xs" role="group" aria-label="..." style="display:inline-flex;">
<a ng-if="$ctrl.settings.showQuickActionStats" style="margin: 0 2.5px;" ui-sref="docker.containers.container.stats({id: item.Id})" title="Stats"><i class="fa fa-area-chart space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionLogs" style="margin: 0 2.5px;" ui-sref="docker.containers.container.logs({id: item.Id})" title="Logs"><i class="fa fa-exclamation-circle space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionLogs" style="margin: 0 2.5px;" ui-sref="docker.containers.container.logs({id: item.Id})" title="Logs"><i class="fa fa-file-text-o space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionConsole" style="margin: 0 2.5px;" ui-sref="docker.containers.container.console({id: item.Id})" title="Console"><i class="fa fa-terminal space-right" aria-hidden="true"></i></a>
<a ng-if="$ctrl.settings.showQuickActionInspect" style="margin: 0 2.5px;" ui-sref="docker.containers.container.inspect({id: item.Id})" title="Inspect"><i class="fa fa-info-circle space-right" aria-hidden="true"></i></a>
</div>

View file

@ -54,6 +54,7 @@
<i class="fa fa-sort-alpha-desc" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Updated' && $ctrl.state.reverseOrder"></i>
</a>
</th>
<th ng-if="$ctrl.showLogsButton">Actions</th>
</tr>
</thead>
<tbody>
@ -63,6 +64,11 @@
<td ng-if="$ctrl.showSlotColumn">{{ item.Slot ? item.Slot : '-' }}</td>
<td>{{ item.NodeId | tasknodename: $ctrl.nodes }}</td>
<td>{{ item.Updated | getisodate }}</td>
<td ng-if="$ctrl.showLogsButton">
<a ui-sref="docker.tasks.task.logs({id: item.Id})">
<i class="fa fa-file-text-o" aria-hidden="true"></i> View logs
</a>
</td>
</tr>
<tr ng-if="!$ctrl.dataset">
<td colspan="5" class="text-center text-muted">Loading...</td>

View file

@ -10,6 +10,7 @@ angular.module('portainer.docker').component('tasksDatatable', {
reverseOrder: '<',
nodes: '<',
showTextFilter: '<',
showSlotColumn: '<'
showSlotColumn: '<',
showLogsButton: '<'
}
});

View file

@ -0,0 +1,8 @@
angular.module('portainer.docker').component('logViewer', {
templateUrl: 'app/docker/components/log-viewer/logViewer.html',
controller: 'LogViewerController',
bindings: {
data: '=',
logCollectionChange: '<'
}
});

View file

@ -0,0 +1,62 @@
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-header icon="fa-file-text-o" title="Log viewer settings"></rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<div class="form-group">
<div class="col-sm-12">
<label for="tls" class="control-label text-left">
Log collection
<portainer-tooltip position="bottom" message="Disabling this option allows you to pause the log collection process."></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="$ctrl.state.logCollection" ng-change="$ctrl.logCollectionChange($ctrl.state.logCollection)"><i></i>
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="tls" class="control-label text-left">
Auto-scrolling
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="$ctrl.state.autoScroll"><i></i>
</label>
</div>
</div>
<div class="form-group">
<label for="logs_search" class="col-sm-1 control-label text-left">
Search
</label>
<div class="col-sm-11">
<input class="form-control" type="text" name="logs_search" ng-model="$ctrl.state.search" ng-change="$ctrl.state.selectedLines.length = 0;" placeholder="Filter...">
</div>
</div>
<div class="form-group" ng-if="$ctrl.state.copySupported">
<label class="col-sm-1 control-label text-left">
Actions
</label>
<div class="col-sm-11">
<button class="btn btn-primary btn-sm" ng-click="$ctrl.copy()" ng-disabled="($ctrl.state.filteredLogs.length === 1 && !$ctrl.state.filteredLogs[0]) || !$ctrl.state.filteredLogs.length"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</button>
<button class="btn btn-primary btn-sm" ng-click="$ctrl.copySelection()" ng-disabled="($ctrl.state.filteredLogs.length === 1 && !$ctrl.state.filteredLogs[0]) || !$ctrl.state.filteredLogs.length || !$ctrl.state.selectedLines.length"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy selected lines</button>
<span>
<i id="refreshRateChange" class="fa fa-check green-icon" aria-hidden="true" style="margin-left: 7px; display: none;"></i>
</span>
</div>
</div>
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row" style="height:54%;">
<div class="col-sm-12" style="height:100%;">
<pre class="log_viewer" scroll-glue="$ctrl.state.autoScroll">
<div ng-repeat="line in $ctrl.state.filteredLogs = ($ctrl.data | filter:$ctrl.state.search) track by $index" class="line" ng-if="line"><p class="inner_line" ng-click="active=!active; $ctrl.selectLine(line)" ng-class="{'line_selected': active}">{{ line }}</p></div>
<div ng-if="!$ctrl.state.filteredLogs.length" class="line"><p class="inner_line">No log line matching the '{{ $ctrl.state.search }}' filter</p></div>
<div ng-if="$ctrl.state.filteredLogs.length === 1 && !$ctrl.state.filteredLogs[0]" class="line"><p class="inner_line">No logs available</p></div>
</pre>
</div>
</div>

View file

@ -0,0 +1,35 @@
angular.module('portainer.docker')
.controller('LogViewerController', ['clipboard',
function (clipboard) {
var ctrl = this;
this.state = {
copySupported: clipboard.supported,
logCollection: true,
autoScroll: true,
search: '',
filteredLogs: [],
selectedLines: []
};
this.copy = function() {
clipboard.copyText(this.state.filteredLogs);
$('#refreshRateChange').show();
$('#refreshRateChange').fadeOut(1500);
};
this.copySelection = function() {
clipboard.copyText(this.state.selectedLines);
$('#refreshRateChange').show();
$('#refreshRateChange').fadeOut(1500);
};
this.selectLine = function(line) {
var idx = this.state.selectedLines.indexOf(line);
if (idx === -1) {
this.state.selectedLines.push(line);
} else {
this.state.selectedLines.splice(idx, 1);
}
};
}]);