Resuelve conflicto de fusión en CHANGELOG.md
commit
cb1e6a0fa9
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -1,5 +1,21 @@
|
|||
# Changelog
|
||||
|
||||
## [1.7.0] - 2026-05-14
|
||||
|
||||
### Added
|
||||
- Visor de logs de disco en las páginas de estado de ogcore, ogboot, ogdhcp
|
||||
y ogrepository: muestra entries del journal en tiempo real sin necesidad
|
||||
de oglog/OpenSearch, con polling cada 5 segundos y modo live/pausa
|
||||
- Soporte de múltiples `SYSLOG_IDENTIFIER` por componente: ogdhcp incluye
|
||||
kea, ogrepository incluye samba, ogboot incluye tftpd-hpa
|
||||
- Host basado en IP del servidor seleccionado para lectura del fichero de
|
||||
journal remoto (`/var/log/journal/remote/<IP>.journal`)
|
||||
|
||||
### Changed
|
||||
- `StatusLogsComponent`: `@Input() identifier` reemplazado por
|
||||
`@Input() identifiers: string[]`; respuesta parseada como array de entries
|
||||
JSON estructurados con formato `[timestamp] IDENTIFIER: mensaje`
|
||||
|
||||
## [1.6.1] - 2026-05-14
|
||||
### Improved
|
||||
- Modificada recepcion de mensajes de mercure durante la importación
|
||||
|
|
|
|||
|
|
@ -61,6 +61,19 @@ pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
stage('Generate Changelog (Devel)') {
|
||||
when {
|
||||
branch 'devel'
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def devName = params.DEV_NAME ? params.DEV_NAME : env.DEFAULT_DEV_NAME
|
||||
def devEmail = params.DEV_EMAIL ? params.DEV_EMAIL : env.DEFAULT_DEV_EMAIL
|
||||
generateDebianChangelog(env.BUILD_DIR, devName, devEmail, "devel")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
|
|
@ -97,20 +110,38 @@ pipeline {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage ('Publish to Debian Repository (Devel)') {
|
||||
when {
|
||||
branch 'devel'
|
||||
}
|
||||
agent { label 'debian-repo' }
|
||||
steps {
|
||||
script {
|
||||
def versionPattern = "-${env.BUILD_NUMBER}~devel"
|
||||
publicarEnAptly('/var/tmp/opengnsys/debian-repo/oggui', 'devel', versionPattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
// Solo lanzar cuando el build sea exitoso y en la rama main
|
||||
if (env.BRANCH_NAME == 'main') {
|
||||
build job: 'Aptly publish nightly repository',
|
||||
wait: false,
|
||||
parameters: [
|
||||
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
|
||||
]
|
||||
build job: 'Aptly publish nightly repository',
|
||||
wait: false,
|
||||
parameters: [
|
||||
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
|
||||
]
|
||||
}
|
||||
if (env.BRANCH_NAME == 'devel') {
|
||||
build job: 'Aptly publish develop repository',
|
||||
wait: false,
|
||||
parameters: [
|
||||
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
always {
|
||||
notifyBuildStatus('opengnsys@qindel.com')
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ import { OgcoreStatusComponent } from './components/global-status/ogcore-status/
|
|||
import { GlobalOgbootStatusComponent } from './components/global-status/ogboot-status/ogboot-status.component';
|
||||
import { OgrepositoryStatusComponent } from './components/global-status/ogrepository-status/ogrepository-status.component';
|
||||
import { OgdhcpStatusComponent } from './components/global-status/ogdhcp-status/ogdhcp-status.component';
|
||||
import { StatusLogsComponent } from './components/global-status/status-logs/status-logs.component';
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||
}
|
||||
|
|
@ -344,6 +345,7 @@ registerLocaleData(localeEs, 'es-ES');
|
|||
GlobalOgbootStatusComponent,
|
||||
OgrepositoryStatusComponent,
|
||||
OgdhcpStatusComponent,
|
||||
StatusLogsComponent,
|
||||
ImportLegacyComponent,
|
||||
PageNotFoundComponent
|
||||
],
|
||||
|
|
|
|||
|
|
@ -42,15 +42,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="logs-section" id="ogboot-logs-section">
|
||||
<div class="logs-header">
|
||||
<h3>{{ 'ogbootLogs' | translate }}</h3>
|
||||
<p>{{ 'realTimeOgbootLogs' | translate }}</p>
|
||||
</div>
|
||||
<div class="logs-container">
|
||||
<iframe [src]="getBootServerIframeUrl()" width="100%" height="800" frameborder="0" class="ogboot-logs-iframe">
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="ogboot-logs-section">
|
||||
<app-status-logs
|
||||
[title]="'ogbootLogs'"
|
||||
[identifiers]="['ogboot', 'tftpd-hpa']"
|
||||
[host]="getSelectedBootServerIp()"
|
||||
[oglogUrl]="getBootServerIframeUrl()">
|
||||
</app-status-logs>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,11 @@ export class GlobalOgbootStatusComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
getSelectedBootServerIp(): string {
|
||||
const s = this.bootServers.find(s => s.uuid === this.selectedBootServerUuid);
|
||||
return s ? s.ip : '';
|
||||
}
|
||||
|
||||
getSelectedBootServerName(): string {
|
||||
const selectedBootServer = this.bootServers.find(server => server.uuid === this.selectedBootServerUuid);
|
||||
return selectedBootServer ? selectedBootServer.name : '';
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
<div class="section-content">
|
||||
<div class="tab-content">
|
||||
<div class="logs-section" id="ogcore-logs-section">
|
||||
<div class="logs-header">
|
||||
<h3>{{ 'ogcoreLogs' | translate }}</h3>
|
||||
<p>{{ 'realTimeOgcoreLogs' | translate }}</p>
|
||||
</div>
|
||||
<div class="logs-container">
|
||||
<iframe [src]="getOgCoreIframeUrl()" width="100%" height="800" frameborder="0" class="ogcore-logs-iframe">
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="ogcore-logs-section">
|
||||
<app-status-logs
|
||||
[title]="'ogcoreLogs'"
|
||||
[identifiers]="['ogcore']"
|
||||
[host]="''"
|
||||
[oglogUrl]="getOgCoreIframeUrl()">
|
||||
</app-status-logs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,15 +42,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="logs-section" id="dhcp-logs-section">
|
||||
<div class="logs-header">
|
||||
<h3>{{ 'dhcpLogs' | translate }}</h3>
|
||||
<p>{{ 'realTimeDhcpLogs' | translate }}</p>
|
||||
</div>
|
||||
<div class="logs-container">
|
||||
<iframe [src]="getDhcpIframeUrl()" width="100%" height="800" frameborder="0" class="dhcp-logs-iframe">
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="dhcp-logs-section">
|
||||
<app-status-logs
|
||||
[title]="'dhcpLogs'"
|
||||
[identifiers]="['ogdhcp', 'kea-dhcp4', 'kea-ctrl-agent', 'DhcpLFC']"
|
||||
[host]="getSelectedDhcpIp()"
|
||||
[oglogUrl]="getDhcpIframeUrl()">
|
||||
</app-status-logs>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@ export class OgdhcpStatusComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
getSelectedDhcpIp(): string {
|
||||
const d = this.dhcps.find(d => d.uuid === this.selectedDhcpUuid);
|
||||
return d ? d.ip : '';
|
||||
}
|
||||
|
||||
getSelectedDhcpName(): string {
|
||||
const selectedDhcp = this.dhcps.find(dhcp => dhcp.uuid === this.selectedDhcpUuid);
|
||||
return selectedDhcp ? selectedDhcp.name : '';
|
||||
|
|
|
|||
|
|
@ -49,16 +49,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="repository-logs-section" id="repository-logs-section">
|
||||
<div class="logs-header">
|
||||
<h3>Datos del repositorio: {{ getSelectedRepositoryName() }}</h3>
|
||||
<p>{{ 'specificRepoInfo' | translate }}</p>
|
||||
</div>
|
||||
<div class="logs-container">
|
||||
<iframe [src]="getRepositoryIframeUrl()" width="100%" height="600" frameborder="0"
|
||||
class="repository-logs-iframe">
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="repository-logs-section">
|
||||
<app-status-logs
|
||||
[title]="'ogrepositoryLogs'"
|
||||
[identifiers]="['ogrepo-api', 'ogrepo-api_DEBUG', '(smbd)', '(nmbd)']"
|
||||
[host]="getSelectedRepositoryIp()"
|
||||
[oglogUrl]="getRepositoryIframeUrl()">
|
||||
</app-status-logs>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@ export class OgrepositoryStatusComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
getSelectedRepositoryIp(): string {
|
||||
const r = this.repositories.find(r => r.uuid === this.selectedRepositoryUuid);
|
||||
return r ? r.ip : '';
|
||||
}
|
||||
|
||||
getSelectedRepositoryName(): string {
|
||||
const selectedRepo = this.repositories.find(repo => repo.uuid === this.selectedRepositoryUuid);
|
||||
return selectedRepo ? selectedRepo.name : '';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
.logs-section {
|
||||
background-color: var(--surface-card, #ffffff);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-top: 16px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logs-header {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.logs-header h3 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
color: var(--text-primary, #111827);
|
||||
}
|
||||
|
||||
.logs-header p {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary, #6b7280);
|
||||
margin: 2px 0 0;
|
||||
}
|
||||
|
||||
.logs-tabs {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.logs-container {
|
||||
position: relative;
|
||||
background-color: #0d1117;
|
||||
border-radius: 8px;
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tab-actions-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4px 12px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.header-actions button {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
|
||||
.header-actions button:hover:not([disabled]) {
|
||||
color: white !important;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.header-actions button[disabled] {
|
||||
color: rgba(255, 255, 255, 0.2) !important;
|
||||
}
|
||||
|
||||
.header-actions button[color="warn"] {
|
||||
color: #ff4081 !important;
|
||||
}
|
||||
|
||||
.live-badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
color: #ff4081;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.live-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: #ff4081;
|
||||
border-radius: 50%;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.log-viewer {
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
color: #e6edf3;
|
||||
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.4;
|
||||
overflow-y: auto;
|
||||
max-height: 50vh;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba(255, 64, 129, 0.7);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 0 0 8px rgba(255, 64, 129, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0 0 0 rgba(255, 64, 129, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(13, 17, 23, 0.7);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
padding: 32px;
|
||||
text-align: center;
|
||||
color: #f85149;
|
||||
}
|
||||
|
||||
.error-message mat-icon {
|
||||
font-size: 48px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.logs-iframe {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.no-oglog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 64px;
|
||||
color: #8b949e;
|
||||
}
|
||||
|
||||
.no-oglog mat-icon {
|
||||
font-size: 48px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<div class="logs-section">
|
||||
<div class="logs-header">
|
||||
<h3>{{ title | translate }}</h3>
|
||||
<p>{{ 'realTimeLogs' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<mat-tab-group class="logs-tabs" animationDuration="0ms" (selectedTabChange)="onTabChange($event)">
|
||||
<mat-tab [label]="'diskLogs' | translate">
|
||||
<div class="logs-container disk-logs">
|
||||
<div class="tab-actions-header">
|
||||
<div class="header-actions">
|
||||
<button mat-icon-button
|
||||
(click)="toggleLive()"
|
||||
[matTooltip]="(isLive ? 'diskLogsStopLive' : 'diskLogsStartLive') | translate"
|
||||
[color]="isLive ? 'warn' : ''">
|
||||
<mat-icon>{{ isLive ? 'pause_circle' : 'play_circle' }}</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="refreshLogs()" [matTooltip]="'buttonUpdateData' | translate" [disabled]="isLive">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="isLive" class="live-badge">
|
||||
<span class="live-dot"></span>
|
||||
LIVE
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (loadingDiskLogs && !diskLogsContent) {
|
||||
<div class="loading-overlay">
|
||||
<mat-spinner diameter="40"></mat-spinner>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (errorDiskLogs) {
|
||||
<div class="error-message">
|
||||
<mat-icon>error_outline</mat-icon>
|
||||
<p>{{ errorDiskLogs }}</p>
|
||||
<button mat-button (click)="loadDiskLogs()">{{ 'buttonRetry' | translate }}</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<pre #logContent class="log-viewer">{{ diskLogsContent }}</pre>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab [label]="'oglogLogs' | translate">
|
||||
<div class="logs-container oglog-logs">
|
||||
@if (oglogUrl) {
|
||||
<iframe [src]="oglogUrl" width="100%" height="600" frameborder="0" class="logs-iframe"></iframe>
|
||||
} @else {
|
||||
<div class="no-oglog">
|
||||
<mat-icon>info_outline</mat-icon>
|
||||
<p>oglog no está disponible o no se ha configurado la URL.</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
import { Component, Input, OnInit, OnDestroy, inject, ViewChild, ElementRef, AfterViewChecked } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { SafeResourceUrl } from '@angular/platform-browser';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { MatTabChangeEvent } from '@angular/material/tabs';
|
||||
|
||||
interface JournalEntry {
|
||||
MESSAGE: string;
|
||||
SYSLOG_IDENTIFIER?: string;
|
||||
_HOSTNAME?: string;
|
||||
__REALTIME_TIMESTAMP?: string;
|
||||
PRIORITY?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-status-logs',
|
||||
templateUrl: './status-logs.component.html',
|
||||
styleUrl: './status-logs.component.css'
|
||||
})
|
||||
export class StatusLogsComponent implements OnInit, OnDestroy, AfterViewChecked {
|
||||
@ViewChild('logContent') private logContainer!: ElementRef;
|
||||
@Input() identifiers: string[] = [];
|
||||
@Input() host: string = '';
|
||||
@Input() oglogUrl: SafeResourceUrl | null = null;
|
||||
@Input() title: string = '';
|
||||
|
||||
public translate = inject(TranslateService);
|
||||
diskLogsContent: string = '';
|
||||
loadingDiskLogs: boolean = false;
|
||||
errorDiskLogs: string | null = null;
|
||||
isLive: boolean = true;
|
||||
|
||||
private pollInterval: any;
|
||||
private readonly POLL_INTERVAL_MS = 5000;
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private configService: ConfigService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadDiskLogs();
|
||||
if (this.isLive) {
|
||||
this.startPolling();
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewChecked() {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
toggleLive(): void {
|
||||
this.isLive = !this.isLive;
|
||||
if (this.isLive) {
|
||||
this.loadDiskLogs();
|
||||
this.startPolling();
|
||||
} else {
|
||||
this.stopPolling();
|
||||
}
|
||||
}
|
||||
|
||||
onTabChange(event: MatTabChangeEvent): void {
|
||||
if (event.index === 0) {
|
||||
if (this.isLive) {
|
||||
this.loadDiskLogs();
|
||||
this.startPolling();
|
||||
}
|
||||
} else {
|
||||
this.stopPolling();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.stopPolling();
|
||||
}
|
||||
|
||||
loadDiskLogs(): void {
|
||||
if (!this.identifiers.length) return;
|
||||
|
||||
if (!this.isLive) {
|
||||
this.loadingDiskLogs = true;
|
||||
}
|
||||
|
||||
const idParam = this.identifiers.join(',');
|
||||
const hostParam = this.host ? `&host=${encodeURIComponent(this.host)}` : '';
|
||||
const url = `${this.configService.apiUrl}/opengnsys/system/disk-logs?SYSLOG_IDENTIFIER=${encodeURIComponent(idParam)}${hostParam}&lines=200`;
|
||||
|
||||
this.http.get<{ entries: JournalEntry[] }>(url).subscribe({
|
||||
next: (response) => {
|
||||
this.diskLogsContent = this.formatEntries(response.entries || []);
|
||||
this.loadingDiskLogs = false;
|
||||
this.errorDiskLogs = null;
|
||||
},
|
||||
error: () => {
|
||||
this.errorDiskLogs = 'Error al cargar logs de disco';
|
||||
this.loadingDiskLogs = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private formatEntries(entries: JournalEntry[]): string {
|
||||
return entries.map(entry => {
|
||||
const ts = entry.__REALTIME_TIMESTAMP
|
||||
? new Date(parseInt(entry.__REALTIME_TIMESTAMP, 10) / 1000).toISOString().replace('T', ' ').substring(0, 23)
|
||||
: ' ';
|
||||
const id = entry.SYSLOG_IDENTIFIER ?? '';
|
||||
return `[${ts}] ${id}: ${entry.MESSAGE ?? ''}`;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
private startPolling(): void {
|
||||
this.stopPolling();
|
||||
this.pollInterval = setInterval(() => {
|
||||
if (this.isLive) {
|
||||
this.loadDiskLogs();
|
||||
}
|
||||
}, this.POLL_INTERVAL_MS);
|
||||
}
|
||||
|
||||
private stopPolling(): void {
|
||||
if (this.pollInterval) {
|
||||
clearInterval(this.pollInterval);
|
||||
this.pollInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
refreshLogs(): void {
|
||||
this.loadDiskLogs();
|
||||
}
|
||||
|
||||
private scrollToBottom(): void {
|
||||
if (this.isLive && this.logContainer) {
|
||||
try {
|
||||
this.logContainer.nativeElement.scrollTop = this.logContainer.nativeElement.scrollHeight;
|
||||
} catch (err) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -232,6 +232,10 @@
|
|||
"clientListPartition": "Llistat de clients on es realitzarà el particionat",
|
||||
"clientLogs": "Registres de client",
|
||||
"diskLogs": "Registres de disc",
|
||||
"oglogLogs": "Registres d'oglog",
|
||||
"realTimeLogs": "Visualització de registres en temps real",
|
||||
"diskLogsStartLive": "Activar mode en temps real",
|
||||
"diskLogsStopLive": "Aturar mode en temps real",
|
||||
"clientMacOS": "Client MacOS",
|
||||
"clientOff": "Client apagat",
|
||||
"clientOgLive": "Client OGLive",
|
||||
|
|
@ -1032,6 +1036,7 @@
|
|||
"ogbootServers": "Servidors OgBoot",
|
||||
"ogBootServerStatus": "Estat del servidor OgBoot",
|
||||
"ogcoreLogs": "Logs d'OgCore",
|
||||
"ogrepositoryLogs": "Logs d'OgRepository",
|
||||
"ogCoreServer": "Servidor OgCore",
|
||||
"ogLive": "ogLive",
|
||||
"ogLiveDeletedSuccessfully": "OG Live eliminat amb èxit",
|
||||
|
|
|
|||
|
|
@ -232,6 +232,8 @@
|
|||
"clientListPartition": "List of clients where partitioning will be performed",
|
||||
"clientLogs": "Client Logs",
|
||||
"diskLogs": "Disk Logs",
|
||||
"oglogLogs": "oglog Logs",
|
||||
"realTimeLogs": "Real-time log visualization",
|
||||
"diskLogsStartLive": "Enable real-time mode",
|
||||
"diskLogsStopLive": "Stop real-time mode",
|
||||
"clientMacOS": "MacOS client",
|
||||
|
|
@ -1034,6 +1036,7 @@
|
|||
"ogbootServers": "OgBoot Servers",
|
||||
"ogBootServerStatus": "OgBoot Server Status",
|
||||
"ogcoreLogs": "OgCore Logs",
|
||||
"ogrepositoryLogs": "OgRepository Logs",
|
||||
"ogCoreServer": "OgCore Server",
|
||||
"ogLive": "ogLive",
|
||||
"ogLiveDeletedSuccessfully": "OG Live deleted successfully",
|
||||
|
|
|
|||
|
|
@ -232,6 +232,8 @@
|
|||
"clientListPartition": "Listado de clientes donde se realizará el particionado",
|
||||
"clientLogs": "Logs de cliente",
|
||||
"diskLogs": "Logs de disco",
|
||||
"oglogLogs": "Logs de oglog",
|
||||
"realTimeLogs": "Visualización de logs en tiempo real",
|
||||
"diskLogsStartLive": "Activar modo en tiempo real",
|
||||
"diskLogsStopLive": "Detener modo en tiempo real",
|
||||
"clientMacOS": "Cliente MacOS",
|
||||
|
|
@ -1034,6 +1036,7 @@
|
|||
"ogbootServers": "Servidores OgBoot",
|
||||
"ogBootServerStatus": "Estado del servidor OgBoot",
|
||||
"ogcoreLogs": "Logs de OgCore",
|
||||
"ogrepositoryLogs": "Logs de OgRepository",
|
||||
"ogCoreServer": "Servidor OgCore",
|
||||
"ogLive": "ogLive",
|
||||
"ogLiveDeletedSuccessfully": "OG Live eliminado con éxito",
|
||||
|
|
|
|||
Loading…
Reference in New Issue