chore: import upstream snapshot with attribution
MCP Bash Server CI / Test MCP Bash Server (dev) (push) Has been cancelled
MCP Bash Server CI / Test MCP Bash Server (release) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:11:39 +08:00
commit c8cebdfeee
4654 changed files with 626756 additions and 0 deletions
+267
View File
@@ -0,0 +1,267 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Message } from '../pojo/Message';
import { LocalStorageService } from './local-storage.service';
export interface ChatMessage {
content: string;
role: 'user' | 'assistant' | 'system_push';
gmtCreate: Date;
securityForm: SecurityForm;
/** Flag indicating this message is a skill report that should be displayed directly */
isSkillReport?: boolean;
}
export interface SecurityForm {
show: Boolean;
param: string;
content: string;
complete: boolean;
}
export const DEFAULT_SECURITY_FORM: SecurityForm = {
show: false,
param: '',
content: '',
complete: false
};
export interface ChatConversation {
id: number;
title: string;
gmtCreated: Date;
gmtUpdate: Date;
messages: ChatMessage[];
}
export interface ChatRequestContext {
message: string;
conversationId?: number;
}
export interface SopSchedule {
id?: number;
conversationId: number;
sopName: string;
sopParams?: string;
cronExpression: string;
enabled: boolean;
lastRunTime?: Date;
nextRunTime?: Date;
gmtCreate?: Date;
gmtUpdate?: Date;
}
export interface SkillInfo {
name: string;
description: string;
}
const chat_uri = '/chat';
const schedule_uri = '/ai/schedule';
@Injectable({
providedIn: 'root'
})
export class AiChatService {
constructor(private http: HttpClient, private localStorageService: LocalStorageService) {}
/**
* Create a new conversation
*/
createConversation(): Observable<Message<ChatConversation>> {
return this.http.post<Message<ChatConversation>>(`${chat_uri}/conversations`, {});
}
/**
* Get all conversations
*/
getConversations(): Observable<Message<ChatConversation[]>> {
return this.http.get<Message<ChatConversation[]>>(`${chat_uri}/conversations`);
}
/**
* Get a specific conversation with its history
*/
getConversation(conversationId: number): Observable<Message<ChatConversation>> {
return this.http.get<Message<ChatConversation>>(`${chat_uri}/conversations/${conversationId}`);
}
/**
* Delete a conversation
*/
deleteConversation(conversationId: number): Observable<Message<void>> {
return this.http.delete<Message<void>>(`${chat_uri}/conversations/${conversationId}`);
}
/**
* Send a message and get streaming response
*/
streamChat(message: string, conversationId?: number): Observable<ChatMessage> {
const responseSubject = new Subject<ChatMessage>();
const requestBody: ChatRequestContext = { message };
if (conversationId) {
requestBody.conversationId = conversationId;
}
const token = this.localStorageService.getAuthorizationToken();
const headers: Record<string, string> = {
'Content-Type': 'application/json',
Accept: 'text/event-stream',
'Cache-Control': 'no-cache'
};
// Add Authorization header like the interceptor does
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
// Use fetch for SSE streaming (HttpClient doesn't support true streaming)
fetch(`/api${chat_uri}/stream`, {
method: 'POST',
headers,
body: JSON.stringify(requestBody)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body?.getReader();
if (!reader) {
throw new Error('No reader available');
}
const decoder = new TextDecoder();
let buffer = '';
const readStream = (): Promise<void> => {
if (!reader) {
return Promise.resolve();
}
return reader.read().then(({ value, done }) => {
if (done) {
responseSubject.complete();
return;
}
const chunk = decoder.decode(value, { stream: true });
buffer += chunk;
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.startsWith('data:')) {
const jsonStr = trimmedLine.substring(5).trim();
if (jsonStr && jsonStr !== '[DONE]') {
try {
const data = JSON.parse(jsonStr);
if (data.response !== undefined) {
responseSubject.next({
content: data.response || '',
role: 'assistant',
securityForm: DEFAULT_SECURITY_FORM,
gmtCreate: data.timestamp ? new Date(data.timestamp) : new Date()
});
}
} catch (parseError) {
console.error('Error parsing SSE data:', parseError, 'Raw data:', jsonStr);
if (jsonStr) {
responseSubject.next({
content: jsonStr,
role: 'assistant',
securityForm: DEFAULT_SECURITY_FORM,
gmtCreate: new Date()
});
}
}
}
}
}
return readStream();
});
};
return readStream();
})
.catch(error => {
console.error('Chat stream error:', error);
responseSubject.error(error);
});
return responseSubject.asObservable();
}
saveSecurityData(body: any): Observable<Message<any>> {
return this.http.post<Message<any>>(`${chat_uri}/security`, body);
}
// ===== Schedule API Methods =====
/**
* Get all schedules for a conversation
*/
getSchedules(conversationId: number): Observable<Message<SopSchedule[]>> {
return this.http.get<Message<SopSchedule[]>>(`${schedule_uri}/conversation/${conversationId}`);
}
/**
* Create a new schedule
*/
createSchedule(schedule: SopSchedule): Observable<Message<SopSchedule>> {
return this.http.post<Message<SopSchedule>>(schedule_uri, schedule);
}
/**
* Update a schedule
*/
updateSchedule(id: number, schedule: SopSchedule): Observable<Message<SopSchedule>> {
return this.http.put<Message<SopSchedule>>(`${schedule_uri}/${id}`, schedule);
}
/**
* Delete a schedule
*/
deleteSchedule(id: number): Observable<Message<void>> {
return this.http.delete<Message<void>>(`${schedule_uri}/${id}`);
}
/**
* Toggle schedule enabled status
*/
toggleSchedule(id: number, enabled: boolean): Observable<Message<SopSchedule>> {
return this.http.put<Message<SopSchedule>>(`${schedule_uri}/${id}/toggle?enabled=${enabled}`, {});
}
/**
* Get available SOP skills
*/
getAvailableSkills(): Observable<Message<SkillInfo[]>> {
return this.http.get<Message<SkillInfo[]>>(`${schedule_uri}/skills`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AlertDefineService } from './alert-define.service';
describe('AlertDefineService', () => {
let service: AlertDefineService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AlertDefineService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,114 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AlertDefine } from '../pojo/AlertDefine';
import { AlertDefineBind } from '../pojo/AlertDefineBind';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
const alert_define_uri = '/alert/define';
const alert_defines_uri = '/alert/defines';
const export_defines_uri = '/alert/defines/export';
@Injectable({
providedIn: 'root'
})
export class AlertDefineService {
constructor(private http: HttpClient) {}
public newAlertDefine(body: AlertDefine): Observable<Message<any>> {
return this.http.post<Message<any>>(alert_define_uri, body);
}
public editAlertDefine(body: AlertDefine): Observable<Message<any>> {
return this.http.put<Message<any>>(alert_define_uri, body);
}
public getAlertDefine(alertDefineId: number): Observable<Message<AlertDefine>> {
return this.http.get<Message<AlertDefine>>(`${alert_define_uri}/${alertDefineId}`);
}
public applyAlertDefineMonitorsBind(alertDefineId: number, binds: AlertDefineBind[]): Observable<Message<any>> {
return this.http.post<Message<any>>(`${alert_define_uri}/${alertDefineId}/monitors`, binds);
}
public getAlertDefineMonitorsBind(alertDefineId: number): Observable<Message<AlertDefineBind[]>> {
return this.http.get<Message<AlertDefineBind[]>>(`${alert_define_uri}/${alertDefineId}/monitors`);
}
public deleteAlertDefines(alertDefineIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
alertDefineIds.forEach(alertDefineId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', alertDefineId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(alert_defines_uri, options);
}
public getMonitorsDefinePreview(datasource: string, type: string, expr: string): Observable<Message<any>> {
let httpParams = new HttpParams();
if (type != null) httpParams = httpParams.set('type', type);
if (expr != null) httpParams = httpParams.set('expr', expr);
return this.http.get<Message<any>>(`${alert_define_uri}/preview/${datasource}`, { params: httpParams });
}
public getAlertDefines(search: string[] | undefined, pageIndex: number, pageSize: number): Observable<Message<Page<AlertDefine>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'id',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search.length > 0) {
const searchJson = JSON.stringify(search);
httpParams = httpParams.append('search', encodeURIComponent(searchJson));
}
const options = { params: httpParams };
return this.http.get<Message<Page<AlertDefine>>>(alert_defines_uri, options);
}
public exportAlertDefines(defineIds: Set<number>, type: string): Observable<HttpResponse<Blob>> {
let httpParams = new HttpParams();
defineIds.forEach(defineId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', defineId);
});
httpParams = httpParams.append('type', type);
return this.http.get(export_defines_uri, {
params: httpParams,
observe: 'response',
responseType: 'blob'
});
}
public getDatasourceStatus(): Observable<Message<any>> {
return this.http.get<Message<any>>(`${alert_define_uri}/datasource/status`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AlertGroupService } from './alert-group.service';
describe('AlertConvergeService', () => {
let service: AlertGroupService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AlertGroupService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AlertGroupConverge } from '../pojo/AlertGroupConverge';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
const alert_group_uri = '/alert/group';
const alert_groups_uri = '/alert/groups';
@Injectable({
providedIn: 'root'
})
export class AlertGroupService {
constructor(private http: HttpClient) {}
public newAlertGroupConverge(body: AlertGroupConverge): Observable<Message<any>> {
return this.http.post<Message<any>>(alert_group_uri, body);
}
public editAlertGroupConverge(body: AlertGroupConverge): Observable<Message<any>> {
return this.http.put<Message<any>>(alert_group_uri, body);
}
public getAlertGroupConverge(convergeId: number): Observable<Message<AlertGroupConverge>> {
return this.http.get<Message<AlertGroupConverge>>(`${alert_group_uri}/${convergeId}`);
}
public deleteAlertGroupConverges(convergeIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
convergeIds.forEach(convergeId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', convergeId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(alert_groups_uri, options);
}
public getAlertGroupConverges(search: string, pageIndex: number, pageSize: number): Observable<Message<Page<AlertGroupConverge>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'id',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<AlertGroupConverge>>>(alert_groups_uri, options);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AlertInhibitService } from './alert-inhibit.service';
describe('AlertInhibitService', () => {
let service: AlertInhibitService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AlertInhibitService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AlertInhibit } from '../pojo/AlertInhibit';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
const alert_inhibit_uri = '/alert/inhibit';
const alert_inhibits_uri = '/alert/inhibits';
@Injectable({
providedIn: 'root'
})
export class AlertInhibitService {
constructor(private http: HttpClient) {}
public newAlertInhibit(body: AlertInhibit): Observable<Message<any>> {
return this.http.post<Message<any>>(alert_inhibit_uri, body);
}
public editAlertInhibit(body: AlertInhibit): Observable<Message<any>> {
return this.http.put<Message<any>>(alert_inhibit_uri, body);
}
public getAlertInhibit(silenceId: number): Observable<Message<AlertInhibit>> {
return this.http.get<Message<AlertInhibit>>(`${alert_inhibit_uri}/${silenceId}`);
}
public deleteAlertInhibits(silenceIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
silenceIds.forEach(silenceId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', silenceId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(alert_inhibits_uri, options);
}
public getAlertInhibits(search: string, pageIndex: number, pageSize: number): Observable<Message<Page<AlertInhibit>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'id',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<AlertInhibit>>>(alert_inhibits_uri, options);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AlertSilenceService } from './alert-silence.service';
describe('AlertSilenceService', () => {
let service: AlertSilenceService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AlertSilenceService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AlertSilence } from '../pojo/AlertSilence';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
const alert_silence_uri = '/alert/silence';
const alert_silences_uri = '/alert/silences';
@Injectable({
providedIn: 'root'
})
export class AlertSilenceService {
constructor(private http: HttpClient) {}
public newAlertSilence(body: AlertSilence): Observable<Message<any>> {
return this.http.post<Message<any>>(alert_silence_uri, body);
}
public editAlertSilence(body: AlertSilence): Observable<Message<any>> {
return this.http.put<Message<any>>(alert_silence_uri, body);
}
public getAlertSilence(silenceId: number): Observable<Message<AlertSilence>> {
return this.http.get<Message<AlertSilence>>(`${alert_silence_uri}/${silenceId}`);
}
public deleteAlertSilences(silenceIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
silenceIds.forEach(silenceId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', silenceId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(alert_silences_uri, options);
}
public getAlertSilences(search: string, pageIndex: number, pageSize: number): Observable<Message<Page<AlertSilence>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'id',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<AlertSilence>>>(alert_silences_uri, options);
}
}
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AlertSoundService {
private audio: HTMLAudioElement;
constructor() {
this.audio = new Audio();
this.audio.src = '/assets/audio/default-alert-CN.mp3';
this.audio.load();
}
playAlertSound(lang: string): void {
if (lang === 'zh-CN' || lang === 'zh-TW') {
this.audio.src = '/assets/audio/default-alert-CN.mp3';
} else {
this.audio.src = '/assets/audio/default-alert-EN.mp3';
}
this.audio.load();
this.audio.play().catch(error => {
console.warn('Failed to play alert sound:', error);
});
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AlertService } from './alert.service';
describe('AlertService', () => {
let service: AlertService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AlertService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
+117
View File
@@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { GroupAlert } from '../pojo/GroupAlert';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
import { SingleAlert } from '../pojo/SingleAlert';
const alerts_summary_uri = '/alerts/summary';
const alerts_group_uri = '/alerts/group';
const alerts_group_status_uri = '/alerts/group/status';
const alerts_uri = '/alerts';
@Injectable({
providedIn: 'root'
})
export class AlertService {
constructor(private http: HttpClient) {}
public loadAlerts(
status: string | undefined,
search: string | undefined,
pageIndex: number,
pageSize: number
): Observable<Message<Page<SingleAlert>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'gmtUpdate',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
if (status != undefined) {
httpParams = httpParams.append('status', status);
}
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<SingleAlert>>>(alerts_uri, options);
}
public loadGroupAlerts(
status: string | undefined,
search: string | undefined,
pageIndex: number,
pageSize: number
): Observable<Message<Page<GroupAlert>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'gmtUpdate',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
if (status != undefined) {
httpParams = httpParams.append('status', status);
}
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<GroupAlert>>>(alerts_group_uri, options);
}
public deleteGroupAlerts(alertIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
alertIds.forEach(alertId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', alertId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(alerts_group_uri, options);
}
public applyGroupAlertsStatus(alertIds: Set<number>, status: string): Observable<Message<any>> {
let httpParams = new HttpParams();
alertIds.forEach(alertId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', alertId);
});
const options = { params: httpParams };
return this.http.put<Message<any>>(`${alerts_group_status_uri}/${status}`, null, options);
}
public getAlertsSummary(): Observable<Message<any>> {
return this.http.get<Message<any>>(alerts_summary_uri);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AppDefineService } from './app-define.service';
describe('AppDefineService', () => {
let service: AppDefineService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AppDefineService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,118 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { ParamDefine } from '../pojo/ParamDefine';
const app_hierarchy = '/apps/hierarchy';
@Injectable({
providedIn: 'root'
})
export class AppDefineService {
constructor(private http: HttpClient) {}
public getAppParamsDefine(app: string | undefined | null): Observable<Message<ParamDefine[]>> {
if (app === null || app === undefined) {
console.log('getAppParamsDefine app can not null');
}
const paramDefineUri = `/apps/${app}/params`;
return this.http.get<Message<ParamDefine[]>>(paramDefineUri);
}
public getPushDefine(monitorId: number | undefined | null): Observable<Message<any>> {
if (monitorId === null || monitorId === undefined) {
console.log('getPushDefine monitorId can not null');
}
return this.http.get<Message<any>>(`/apps/${monitorId}/pushdefine`);
}
public getAppDynamicDefine(monitorId: number | undefined | null): Observable<Message<any>> {
if (monitorId === null || monitorId === undefined) {
console.log('getAppDynamicDefine monitorId can not null');
}
return this.http.get<Message<any>>(`/apps/${monitorId}/define/dynamic`);
}
public getAppDefine(app: string | undefined | null): Observable<Message<any>> {
if (app === null || app === undefined) {
console.log('getAppDefine app can not null');
}
return this.http.get<Message<any>>(`/apps/${app}/define`);
}
public deleteAppDefine(app: string | undefined | null): Observable<Message<any>> {
if (app === null || app === undefined) {
console.log('deleteAppDefine app can not null');
}
return this.http.delete<Message<any>>(`/apps/${app}/define/yml`);
}
public getAppDefineYmlContent(app: string | undefined | null): Observable<Message<any>> {
if (app === null || app === undefined) {
console.log('getAppDefine app can not null');
}
return this.http.get<Message<any>>(`/apps/${app}/define/yml`);
}
public newAppDefineYmlContent(defineContent: string | undefined | null, isNew: boolean): Observable<Message<any>> {
if (defineContent === null || defineContent === undefined) {
console.log('defineContent can not null');
}
let body = {
define: defineContent
};
if (isNew) {
return this.http.post<Message<any>>(`/apps/define/yml`, body);
} else {
return this.http.put<Message<any>>(`/apps/define/yml`, body);
}
}
public getAppHierarchy(lang: string | undefined): Observable<Message<any>> {
if (lang == undefined) {
lang = 'en_US';
}
let httpParams = new HttpParams().append('lang', lang);
const options = { params: httpParams };
return this.http.get<Message<any>>(app_hierarchy, options);
}
public getAppHierarchyByName(lang: string | undefined, app: string): Observable<Message<any>> {
if (lang == undefined) {
lang = 'en_US';
}
let httpParams = new HttpParams().append('lang', lang);
const options = { params: httpParams };
return this.http.get<Message<any>>(`${app_hierarchy}/${app}`, options);
}
public getAppDefines(lang: string | undefined): Observable<Message<any>> {
if (lang == undefined) {
lang = 'en_US';
}
let httpParams = new HttpParams().append('lang', lang);
const options = { params: httpParams };
return this.http.get<Message<any>>(`/apps/defines`, options);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
+60
View File
@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
const account_auth_refresh_uri = '/account/auth/refresh';
const account_token = '/account/token';
@Injectable({
providedIn: 'root'
})
export class AuthService {
constructor(private http: HttpClient) {}
public refreshToken(refreshToken: string): Observable<Message<any>> {
let body = {
token: refreshToken
};
return this.http.post<Message<any>>(`${account_auth_refresh_uri}`, body);
}
public generateToken(name?: string, expireSeconds?: number): Observable<Message<any>> {
let params: any = {};
if (name) {
params.name = name;
}
if (expireSeconds != null) {
params.expireSeconds = expireSeconds;
}
return this.http.post<Message<any>>(`${account_token}/generate`, {}, { params });
}
public listTokens(): Observable<Message<any>> {
return this.http.get<Message<any>>(`${account_token}`);
}
public deleteToken(id: number): Observable<Message<any>> {
return this.http.delete<Message<any>>(`${account_token}/${id}`);
}
}
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { BulletinDefine } from '../pojo/BulletinDefine';
import { Message } from '../pojo/Message';
import { Monitor } from '../pojo/Monitor';
import { Page } from '../pojo/Page';
const bulletin_define_uri = '/bulletin';
@Injectable({
providedIn: 'root'
})
export class BulletinDefineService {
constructor(private http: HttpClient) {}
public newBulletinDefine(body: BulletinDefine) {
return this.http.post<Message<any>>(bulletin_define_uri, body);
}
public editBulletinDefine(body: BulletinDefine) {
return this.http.put<Message<any>>(bulletin_define_uri, body);
}
public deleteBulletinDefines(ids: number[]): Observable<Message<any>> {
let params = new HttpParams();
ids.forEach(name => {
params = params.append('ids', name);
});
return this.http.delete<Message<any>>(bulletin_define_uri, { params });
}
public getMonitorMetricsData(id: number): Observable<Message<Page<Monitor>>> {
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
id: id
});
const options = { params: httpParams };
return this.http.get<Message<any>>(`${bulletin_define_uri}/metrics`, options);
}
public queryBulletins(): Observable<Message<any>> {
return this.http.get<Message<string[]>>(`${bulletin_define_uri}`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { CollectorService } from './collector.service';
describe('CollectorService', () => {
let service: CollectorService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(CollectorService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { CollectorSummary } from '../pojo/CollectorSummary';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
const collector_uri = '/collector';
@Injectable({
providedIn: 'root'
})
export class CollectorService {
constructor(private http: HttpClient) {}
public getCollectors(): Observable<Message<Page<CollectorSummary>>> {
return this.http.get<Message<Page<CollectorSummary>>>(collector_uri);
}
public queryCollectors(search: string | undefined, pageIndex: number, pageSize: number): Observable<Message<Page<CollectorSummary>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('name', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<CollectorSummary>>>(collector_uri, options);
}
public goOnlineCollector(collectors: Set<string>): Observable<Message<any>> {
let httpParams = new HttpParams();
collectors.forEach(collector => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('collectors', collector);
});
const options = { params: httpParams };
return this.http.put<Message<any>>(`${collector_uri}/online`, null, options);
}
public goOfflineCollector(collectors: Set<string>): Observable<Message<any>> {
let httpParams = new HttpParams();
collectors.forEach(collector => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('collectors', collector);
});
const options = { params: httpParams };
return this.http.put<Message<any>>(`${collector_uri}/offline`, null, options);
}
public deleteCollector(collectors: Set<string>): Observable<Message<any>> {
let httpParams = new HttpParams();
collectors.forEach(collector => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('collectors', collector);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(`${collector_uri}`, options);
}
public generateCollectorIdentity(collector: string): Observable<Message<any>> {
return this.http.post<Message<any>>(`${collector_uri}/generate/${collector}`, null);
}
}
@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
interface LayoutItem {
id: number;
metrics: string;
position: { x: number; y: number };
}
@Injectable({
providedIn: 'root'
})
export class DashboardLayoutService {
private layoutKey = 'dashboard_layout';
private layoutSubject = new BehaviorSubject<LayoutItem[]>([]);
constructor() {
this.loadLayout();
}
private loadLayout() {
const savedLayout = localStorage.getItem(this.layoutKey);
if (savedLayout) {
this.layoutSubject.next(JSON.parse(savedLayout));
}
}
saveLayout(items: LayoutItem[]) {
localStorage.setItem(this.layoutKey, JSON.stringify(items));
this.layoutSubject.next(items);
}
updateItemPosition(id: number, metrics: string, position: { x: number; y: number }) {
const currentLayout = this.layoutSubject.value;
const itemIndex = currentLayout.findIndex(item => item.id === id && item.metrics === metrics);
if (itemIndex > -1) {
currentLayout[itemIndex].position = position;
} else {
currentLayout.push({ id, metrics, position });
}
this.saveLayout(currentLayout);
}
getLayout() {
return this.layoutSubject.asObservable();
}
}
@@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { ModelProviderConfig } from '../pojo/ModelProviderConfig';
const general_config_uri = '/config';
@Injectable({
providedIn: 'root'
})
export class GeneralConfigService {
constructor(private http: HttpClient) {}
public saveGeneralConfig(body: any, type: string): Observable<Message<any>> {
return this.http.post<Message<any>>(`${general_config_uri}/${type}`, body);
}
public getGeneralConfig(type: string): Observable<Message<any>> {
return this.http.get<Message<any>>(`${general_config_uri}/${type}`);
}
public saveModelProviderConfig(body: ModelProviderConfig): Observable<Message<any>> {
return this.http.post<Message<any>>(`${general_config_uri}/provider`, body);
}
public getModelProviderConfig(): Observable<Message<ModelProviderConfig>> {
return this.http.get<Message<ModelProviderConfig>>(`${general_config_uri}/provider`);
}
public updateAppTemplateConfig(body: any, app: string): Observable<Message<void>> {
return this.http.put<Message<void>>(`${general_config_uri}/template/${app}`, body);
}
public getTimezones(): Observable<Message<any>> {
return this.http.get<Message<any>>(`${general_config_uri}/timezones`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { LabelService } from './label.service';
describe('LabelService', () => {
let service: LabelService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LabelService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
+78
View File
@@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Label } from '../pojo/Label';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
const label_uri = '/label';
@Injectable({
providedIn: 'root'
})
export class LabelService {
constructor(private http: HttpClient) {}
public loadLabels(
search: string | undefined,
type: number | undefined,
pageIndex: number,
pageSize: number
): Observable<Message<Page<Label>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pageIndex: pageIndex,
pageSize: pageSize
});
if (type != undefined) {
httpParams = httpParams.append('type', type);
}
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<Label>>>(label_uri, options);
}
public newLabel(body: Label): Observable<Message<any>> {
return this.http.post<Message<any>>(label_uri, body);
}
public editLabel(body: Label): Observable<Message<any>> {
return this.http.put<Message<any>>(label_uri, body);
}
public deleteLabels(ids: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
ids.forEach(id => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', id);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(label_uri, options);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { LocalStorageService } from './local-storage.service';
describe('LocalStorageService', () => {
let service: LocalStorageService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LocalStorageService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Injectable } from '@angular/core';
const AuthorizationConst = 'Authorization';
const RefreshTokenConst = 'refresh-token';
@Injectable({
providedIn: 'root'
})
export class LocalStorageService {
constructor() {}
public putData(key: string, value: string) {
localStorage.setItem(key, value);
}
public getData(key: string): string | null {
const data = localStorage.getItem(key);
return data === null ? null : data;
}
public getAuthorizationToken(): string | null {
return this.getData(AuthorizationConst);
}
public getRefreshToken(): string | null {
return this.getData(RefreshTokenConst);
}
public storageRefreshToken(token: string) {
return this.putData(RefreshTokenConst, token);
}
public storageAuthorizationToken(token: string) {
return this.putData(AuthorizationConst, token);
}
public hasAuthorizationToken() {
return localStorage.getItem(AuthorizationConst) != null;
}
public clearAuthorization() {
localStorage.removeItem(AuthorizationConst);
localStorage.removeItem(RefreshTokenConst);
}
}
+131
View File
@@ -0,0 +1,131 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { LogEntry } from '../pojo/LogEntry';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
// endpoints
const logs_list_uri = '/logs/list';
const logs_stats_overview_uri = '/logs/stats/overview';
const logs_stats_trend_uri = '/logs/stats/trend';
const logs_stats_trace_coverage_uri = '/logs/stats/trace-coverage';
const logs_batch_delete_uri = '/logs';
@Injectable({ providedIn: 'root' })
export class LogService {
constructor(private http: HttpClient) {}
public list(
start?: number,
end?: number,
traceId?: string,
spanId?: string,
severityNumber?: number,
severityText?: string,
search?: string,
pageIndex: number = 0,
pageSize: number = 20
): Observable<Message<Page<LogEntry>>> {
let params = new HttpParams();
if (start != null) params = params.set('start', start);
if (end != null) params = params.set('end', end);
if (traceId) params = params.set('traceId', traceId);
if (spanId) params = params.set('spanId', spanId);
if (severityNumber != null) params = params.set('severityNumber', severityNumber);
if (severityText) params = params.set('severityText', severityText);
if (search) params = params.set('search', search);
params = params.set('pageIndex', pageIndex);
params = params.set('pageSize', pageSize);
return this.http.get<Message<any>>(logs_list_uri, { params });
}
public overviewStats(
start?: number,
end?: number,
traceId?: string,
spanId?: string,
severityNumber?: number,
severityText?: string,
search?: string
): Observable<Message<any>> {
let params = new HttpParams();
if (start != null) params = params.set('start', start);
if (end != null) params = params.set('end', end);
if (traceId) params = params.set('traceId', traceId);
if (spanId) params = params.set('spanId', spanId);
if (severityNumber != null) params = params.set('severityNumber', severityNumber);
if (severityText) params = params.set('severityText', severityText);
if (search) params = params.set('search', search);
return this.http.get<Message<any>>(logs_stats_overview_uri, { params });
}
public trendStats(
start?: number,
end?: number,
traceId?: string,
spanId?: string,
severityNumber?: number,
severityText?: string,
search?: string
): Observable<Message<any>> {
let params = new HttpParams();
if (start != null) params = params.set('start', start);
if (end != null) params = params.set('end', end);
if (traceId) params = params.set('traceId', traceId);
if (spanId) params = params.set('spanId', spanId);
if (severityNumber != null) params = params.set('severityNumber', severityNumber);
if (severityText) params = params.set('severityText', severityText);
if (search) params = params.set('search', search);
return this.http.get<Message<any>>(logs_stats_trend_uri, { params });
}
public traceCoverageStats(
start?: number,
end?: number,
traceId?: string,
spanId?: string,
severityNumber?: number,
severityText?: string,
search?: string
): Observable<Message<any>> {
let params = new HttpParams();
if (start != null) params = params.set('start', start);
if (end != null) params = params.set('end', end);
if (traceId) params = params.set('traceId', traceId);
if (spanId) params = params.set('spanId', spanId);
if (severityNumber != null) params = params.set('severityNumber', severityNumber);
if (severityText) params = params.set('severityText', severityText);
if (search) params = params.set('search', search);
return this.http.get<Message<any>>(logs_stats_trace_coverage_uri, { params });
}
public batchDelete(timeUnixNanos: number[]): Observable<Message<string>> {
let httpParams = new HttpParams();
timeUnixNanos.forEach(timeUnixNano => {
httpParams = httpParams.append('timeUnixNanos', timeUnixNano);
});
const options = { params: httpParams };
return this.http.delete<Message<string>>(logs_batch_delete_uri, options);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { MemoryStorageService } from './memory-storage.service';
describe('MemoryStorageService', () => {
let service: MemoryStorageService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MemoryStorageService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MemoryStorageService {
data: Record<string, any>;
constructor() {
this.data = {};
}
public putData(key: string, value: any) {
this.data[key] = value;
}
public getData(key: string): any | undefined {
return this.data[key];
}
public clear() {
this.data = {};
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { MonitorService } from './monitor.service';
describe('MonitorService', () => {
let service: MonitorService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MonitorService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
+215
View File
@@ -0,0 +1,215 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { Monitor } from '../pojo/Monitor';
import { Page } from '../pojo/Page';
const monitor_uri = '/monitor';
const monitors_uri = '/monitors';
const detect_monitor_uri = '/monitor/detect';
const manage_monitors_uri = '/monitors/manage';
const export_monitors_uri = '/monitors/export';
const export_all_monitors_uri = '/monitors/export/all';
const summary_uri = '/summary';
const warehouse_storage_status_uri = '/warehouse/storage/status';
const grafana_dashboard_uri = '/grafana/dashboard';
const metrics_favorite_uri = '/metrics/favorite';
@Injectable({
providedIn: 'root'
})
export class MonitorService {
constructor(private http: HttpClient) {}
public newMonitor(body: any): Observable<Message<any>> {
return this.http.post<Message<any>>(monitor_uri, body);
}
public editMonitor(body: any): Observable<Message<any>> {
return this.http.put<Message<any>>(monitor_uri, body);
}
public deleteMonitors(monitorIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
monitorIds.forEach(monitorId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', monitorId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(monitors_uri, options);
}
public exportMonitors(monitorIds: Set<number>, type: string): Observable<HttpResponse<Blob>> {
let httpParams = new HttpParams();
monitorIds.forEach(monitorId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', monitorId);
});
httpParams = httpParams.append('type', type);
return this.http.get(export_monitors_uri, {
params: httpParams,
observe: 'response',
responseType: 'blob'
});
}
public exportAllMonitors(type: string): Observable<HttpResponse<Blob>> {
let httpParams = new HttpParams();
httpParams = httpParams.append('type', type);
return this.http.get(export_all_monitors_uri, {
params: httpParams,
observe: 'response',
responseType: 'blob'
});
}
public cancelManageMonitors(monitorIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
monitorIds.forEach(monitorId => {
// HttpParams is unmodifiable, so we need to save the return value of append/set
// Method append can append same key, set will replace the previous value
httpParams = httpParams.append('ids', monitorId);
httpParams = httpParams.append('type', 'JSON');
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(manage_monitors_uri, options);
}
public enableManageMonitors(monitorIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
monitorIds.forEach(monitorId => {
httpParams = httpParams.append('ids', monitorId);
});
const options = { params: httpParams };
return this.http.get<Message<any>>(manage_monitors_uri, options);
}
public detectMonitor(body: any): Observable<Message<any>> {
return this.http.post<Message<any>>(detect_monitor_uri, body);
}
public getMonitor(monitorId: number): Observable<Message<any>> {
return this.http.get<Message<any>>(`${monitor_uri}/${monitorId}`);
}
public getMonitorsByApp(app: string): Observable<Message<Monitor[]>> {
return this.http.get<Message<Monitor[]>>(`${monitors_uri}/${app}`);
}
public searchMonitors(
app: string | undefined,
labels: string | undefined,
search: string,
status: number,
pageIndex: number,
pageSize: number,
sortField?: string | null,
sortOrder?: string | null
): Observable<Message<Page<Monitor>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pageIndex: pageIndex,
pageSize: pageSize
});
if (labels != undefined) {
httpParams = httpParams.append('labels', labels);
}
if (status != undefined && status != 9) {
httpParams = httpParams.append('status', status);
}
if (app != undefined) {
httpParams = httpParams.append('app', app);
}
if (sortField != null && sortOrder != null) {
httpParams = httpParams.appendAll({
sort: sortField,
order: sortOrder == 'ascend' ? 'asc' : 'desc'
});
}
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('search', search);
}
const options = { params: httpParams };
return this.http.get<Message<Page<Monitor>>>(monitors_uri, options);
}
public getMonitorMetricsData(monitorId: number, metrics: string): Observable<Message<any>> {
return this.http.get<Message<any>>(`/monitor/${monitorId}/metrics/${metrics}`);
}
public getMonitorMetricHistoryData(
instance: string,
app: string,
metrics: string,
metric: string,
history: string,
interval: boolean
): Observable<Message<any>> {
let metricFull = `${app}.${metrics}.${metric}`;
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
history: history,
interval: interval
});
const options = { params: httpParams };
return this.http.get<Message<any>>(`${monitor_uri}/${instance}/metric/${metricFull}`, options);
}
public getAppsMonitorSummary(): Observable<Message<any>> {
return this.http.get<Message<any>>(summary_uri);
}
public getWarehouseStorageServerStatus(): Observable<Message<any>> {
return this.http.get<Message<any>>(warehouse_storage_status_uri);
}
public getGrafanaDashboard(monitorId: number): Observable<Message<any>> {
return this.http.get<Message<any>>(`${grafana_dashboard_uri}?monitorId=${monitorId}`);
}
public deleteGrafanaDashboard(monitorId: number): Observable<Message<any>> {
return this.http.delete<Message<any>>(`${grafana_dashboard_uri}?monitorId=${monitorId}`);
}
copyMonitor(id: number): Observable<any> {
return this.http.post<Message<any>>(`${monitor_uri}/copy/${id}`, null);
}
public addMetricsFavorite(monitorId: number, metricsName: string): Observable<Message<any>> {
return this.http.post<Message<any>>(`${metrics_favorite_uri}/${monitorId}/${metricsName}`, null);
}
public removeMetricsFavorite(monitorId: number, metricsName: string): Observable<Message<any>> {
return this.http.delete<Message<any>>(`${metrics_favorite_uri}/${monitorId}/${metricsName}`);
}
public getUserFavoritedMetrics(monitorId: number): Observable<Message<Set<string>>> {
return this.http.get<Message<Set<string>>>(`${metrics_favorite_uri}/${monitorId}`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { NoticeReceiverMailService } from './notice-receiver.service';
describe('NoticeReceiverService', () => {
let service: NoticeReceiverMailService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(NoticeReceiverMailService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { NoticeReceiver } from '../pojo/NoticeReceiver';
import { Page } from '../pojo/Page';
const notice_receiver_uri = '/notice/receiver';
const notice_receivers_uri = '/notice/receivers';
const notice_receivers_all_uri = '/notice/receivers/all';
const notice_receiver_send_test_msg_uri = '/notice/receiver/send-test-msg';
@Injectable({
providedIn: 'root'
})
export class NoticeReceiverService {
constructor(private http: HttpClient) {}
public newReceiver(body: NoticeReceiver): Observable<Message<any>> {
return this.http.post<Message<any>>(notice_receiver_uri, body);
}
public editReceiver(body: NoticeReceiver): Observable<Message<any>> {
return this.http.put<Message<any>>(notice_receiver_uri, body);
}
public deleteReceiver(receiverId: number): Observable<Message<any>> {
return this.http.delete<Message<any>>(`${notice_receiver_uri}/${receiverId}`);
}
public getReceivers(name: string, pageIndex: number, pageSize: number): Observable<Message<Page<NoticeReceiver>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
let httpParams = new HttpParams();
httpParams = httpParams.append('pageIndex', pageIndex);
httpParams = httpParams.append('pageSize', pageSize);
if (name != undefined && name != null && name != '') {
httpParams = httpParams.append('name', name);
}
const options = { params: httpParams };
return this.http.get<Message<Page<NoticeReceiver>>>(notice_receivers_uri, options);
}
public getAllReceivers(): Observable<Message<NoticeReceiver[]>> {
return this.http.get<Message<NoticeReceiver[]>>(notice_receivers_all_uri);
}
public getReceiver(receiverId: number): Observable<Message<NoticeReceiver>> {
return this.http.get<Message<NoticeReceiver>>(`${notice_receiver_uri}/${receiverId}`);
}
public sendAlertMsgToReceiver(body: NoticeReceiver): Observable<Message<any>> {
return this.http.post<Message<any>>(notice_receiver_send_test_msg_uri, body);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { NoticeRuleService } from './notice-rule.service';
describe('NoticeRuleService', () => {
let service: NoticeRuleService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(NoticeRuleService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { NoticeRule } from '../pojo/NoticeRule';
import { Page } from '../pojo/Page';
const notice_rule_uri = '/notice/rule';
const notice_rules_uri = '/notice/rules';
@Injectable({
providedIn: 'root'
})
export class NoticeRuleService {
constructor(private http: HttpClient) {}
public newNoticeRule(body: NoticeRule): Observable<Message<any>> {
return this.http.post<Message<any>>(notice_rule_uri, body);
}
public editNoticeRule(body: NoticeRule): Observable<Message<any>> {
return this.http.put<Message<any>>(notice_rule_uri, body);
}
public deleteNoticeRule(ruleId: number): Observable<Message<any>> {
return this.http.delete<Message<any>>(`${notice_rule_uri}/${ruleId}`);
}
public getNoticeRules(name: string, pageIndex: number, pageSize: number): Observable<Message<Page<NoticeRule>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
let httpParams = new HttpParams();
httpParams = httpParams.append('pageIndex', pageIndex);
httpParams = httpParams.append('pageSize', pageSize);
if (name != undefined && name != null && name != '') {
httpParams = httpParams.append('name', name);
}
const options = { params: httpParams };
return this.http.get<Message<Page<NoticeRule>>>(notice_rules_uri, options);
}
public getNoticeRuleById(ruleId: number): Observable<Message<NoticeRule>> {
return this.http.get<Message<NoticeRule>>(`${notice_rule_uri}/${ruleId}`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { NoticeTemplateService } from './notice-template.service';
describe('NoticeTemplateService', () => {
let service: NoticeTemplateService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(NoticeTemplateService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { NoticeTemplate } from '../pojo/NoticeTemplate';
import { Page } from '../pojo/Page';
const notice_template_uri = '/notice/template';
const notice_templates_uri = '/notice/templates';
const notice_templates_all_uri = '/notice/templates/all';
const default_notice_templates_uri = '/notice/default_templates';
@Injectable({
providedIn: 'root'
})
export class NoticeTemplateService {
constructor(private http: HttpClient) {}
public newNoticeTemplate(body: NoticeTemplate): Observable<Message<any>> {
return this.http.post<Message<any>>(notice_template_uri, body);
}
public editNoticeTemplate(body: NoticeTemplate): Observable<Message<any>> {
return this.http.put<Message<any>>(notice_template_uri, body);
}
public deleteNoticeTemplate(templateId: number): Observable<Message<any>> {
return this.http.delete<Message<any>>(`${notice_template_uri}/${templateId}`);
}
public getNoticeTemplates(name: string, preset: boolean, pageIndex: number, pageSize: number): Observable<Message<Page<NoticeTemplate>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
let httpParams = new HttpParams();
httpParams = httpParams.append('pageIndex', pageIndex);
httpParams = httpParams.append('pageSize', pageSize);
httpParams = httpParams.append('preset', preset);
if (name != undefined && name != null && name != '') {
httpParams = httpParams.append('name', name);
}
const options = { params: httpParams };
return this.http.get<Message<Page<NoticeTemplate>>>(notice_templates_uri, options);
}
public getAllNoticeTemplates(): Observable<Message<NoticeTemplate[]>> {
return this.http.get<Message<NoticeTemplate[]>>(notice_templates_all_uri);
}
public getDefaultNoticeTemplates(): Observable<Message<NoticeTemplate[]>> {
return this.http.get<Message<NoticeTemplate[]>>(default_notice_templates_uri);
}
public getNoticeTemplateById(templateId: number): Observable<Message<NoticeTemplate>> {
return this.http.get<Message<NoticeTemplate>>(`${notice_template_uri}/${templateId}`);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { PluginService } from './plugin.service';
describe('PluginService', () => {
let service: PluginService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(PluginService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
+87
View File
@@ -0,0 +1,87 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
import { Plugin } from '../pojo/Plugin';
const plugin_uri = '/plugin';
@Injectable({
providedIn: 'root'
})
export class PluginService {
constructor(private http: HttpClient) {}
public loadPlugins(
search: string | undefined,
type: number | undefined,
pageIndex: number,
pageSize: number
): Observable<Message<Page<Plugin>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('search', search.trim());
}
const options = { params: httpParams };
return this.http.get<Message<Page<Plugin>>>(plugin_uri, options);
}
public uploadPlugin(body: FormData): Observable<Message<any>> {
return this.http.post<Message<any>>(plugin_uri, body);
}
public updatePluginStatus(body: Plugin): Observable<Message<any>> {
body.enableStatus = !body.enableStatus;
return this.http.put<Message<any>>(plugin_uri, body);
}
public deletePlugins(pluginIds: Set<number>): Observable<Message<any>> {
let httpParams = new HttpParams();
pluginIds.forEach(pluginId => {
httpParams = httpParams.append('ids', pluginId);
});
const options = { params: httpParams };
return this.http.delete<Message<any>>(plugin_uri, options);
}
public getPluginParamDefine(pluginId: number): Observable<Message<any>> {
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pluginMetadataId: pluginId
});
const options = { params: httpParams };
return this.http.get<Message<any>>(`${plugin_uri}/params/define`, options);
}
public savePluginParamDefine(body: any): Observable<Message<any>> {
return this.http.post<Message<any>>(`${plugin_uri}/params`, body);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { StatusPagePublicService } from './status-page-public.service';
describe('StatusPagePublicService', () => {
let service: StatusPagePublicService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(StatusPagePublicService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
import { StatusPageComponentStatus } from '../pojo/StatusPageComponentStatus';
import { StatusPageIncident } from '../pojo/StatusPageIncident';
import { StatusPageOrg } from '../pojo/StatusPageOrg';
const status_page_org_public_uri = '/status/page/public/org';
const status_page_component_public_uri = '/status/page/public/component';
const status_page_incident_public_uri = '/status/page/public/incident';
@Injectable({
providedIn: 'root'
})
export class StatusPagePublicService {
constructor(private http: HttpClient) {}
public getStatusPageOrg(): Observable<Message<StatusPageOrg>> {
return this.http.get<Message<StatusPageOrg>>(status_page_org_public_uri);
}
public getStatusPageComponents(): Observable<Message<StatusPageComponentStatus[]>> {
return this.http.get<Message<StatusPageComponentStatus[]>>(status_page_component_public_uri);
}
public getStatusPageComponent(componentId: number): Observable<Message<StatusPageComponentStatus>> {
return this.http.get<Message<StatusPageComponentStatus>>(`${status_page_component_public_uri}/${componentId}`);
}
public getStatusPageIncidents(
startTime: number,
endTime: number,
pageIndex: number,
pageSize: number
): Observable<Message<Page<StatusPageIncident>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pageIndex: pageIndex,
pageSize: pageSize,
startTime: startTime
});
if (endTime != undefined && endTime > 0) {
httpParams = httpParams.append('endTime', endTime);
}
const options = { params: httpParams };
return this.http.get<Message<Page<StatusPageIncident>>>(status_page_incident_public_uri, options);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { TestBed } from '@angular/core/testing';
import { StatusPageService } from './status-page.service';
describe('StatusPageService', () => {
let service: StatusPageService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(StatusPageService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
@@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Message } from '../pojo/Message';
import { Page } from '../pojo/Page';
import { StatusPageComponent } from '../pojo/StatusPageComponent';
import { StatusPageIncident } from '../pojo/StatusPageIncident';
import { StatusPageOrg } from '../pojo/StatusPageOrg';
const status_page_org_uri = '/status/page/org';
const status_page_component_uri = '/status/page/component';
const status_page_incident_uri = '/status/page/incident';
@Injectable({
providedIn: 'root'
})
export class StatusPageService {
constructor(private http: HttpClient) {}
public saveStatusPageOrg(body: StatusPageOrg): Observable<Message<StatusPageOrg>> {
return this.http.post<Message<StatusPageOrg>>(status_page_org_uri, body);
}
public getStatusPageOrg(): Observable<Message<StatusPageOrg>> {
return this.http.get<Message<StatusPageOrg>>(status_page_org_uri);
}
public newStatusPageComponent(body: StatusPageComponent): Observable<Message<void>> {
return this.http.post<Message<void>>(status_page_component_uri, body);
}
public editStatusPageComponent(body: StatusPageComponent): Observable<Message<void>> {
return this.http.put<Message<void>>(status_page_component_uri, body);
}
public deleteStatusPageComponent(componentId: number): Observable<Message<void>> {
return this.http.delete<Message<void>>(`${status_page_component_uri}/${componentId}`);
}
public getStatusPageComponents(): Observable<Message<StatusPageComponent[]>> {
return this.http.get<Message<StatusPageComponent[]>>(status_page_component_uri);
}
public getStatusPageComponent(componentId: number): Observable<Message<StatusPageComponent>> {
return this.http.get<Message<StatusPageComponent>>(`${status_page_component_uri}/${componentId}`);
}
public newStatusPageIncident(body: StatusPageIncident): Observable<Message<void>> {
return this.http.post<Message<void>>(status_page_incident_uri, body);
}
public editStatusPageIncident(body: StatusPageIncident): Observable<Message<void>> {
return this.http.put<Message<void>>(status_page_incident_uri, body);
}
public deleteStatusPageIncident(componentId: number): Observable<Message<void>> {
return this.http.delete<Message<void>>(`${status_page_incident_uri}/${componentId}`);
}
public getStatusPageIncidents(
search: string | undefined,
pageIndex: number,
pageSize: number
): Observable<Message<Page<StatusPageIncident>>> {
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// HttpParams is unmodifiable, so we need to save the return value of append/set
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
pageIndex: pageIndex,
pageSize: pageSize
});
if (search != undefined && search != '' && search.trim() != '') {
httpParams = httpParams.append('search', search);
}
const options = { params: httpParams };
return this.http.get<Message<Page<StatusPageIncident>>>(status_page_incident_uri, options);
}
public getStatusPageIncident(incidentId: number): Observable<Message<StatusPageIncident>> {
return this.http.get<Message<StatusPageIncident>>(`${status_page_incident_uri}/${incidentId}`);
}
}
+74
View File
@@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ThemeService {
private readonly themeKey = 'theme';
constructor(@Inject(DOCUMENT) private doc: any) {}
setTheme(theme: string): void {
localStorage.setItem(this.themeKey, theme);
}
getTheme(): string | null {
return localStorage.getItem(this.themeKey);
}
changeTheme(theme: string | null): void {
if (theme == null) {
theme = this.getTheme();
}
const style = this.doc.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
if (theme === 'dark') {
style.id = 'dark-theme';
style.href = 'assets/style.dark.css';
} else if (theme === 'compact') {
style.id = 'compact-theme';
style.href = 'assets/style.compact.css';
} else {
const darkDom = this.doc.getElementById('dark-theme');
if (darkDom) darkDom.remove();
const compactDom = this.doc.getElementById('compact-theme');
if (compactDom) compactDom.remove();
return;
}
this.setTheme(theme);
// remove old theme
const existingLink = this.doc.getElementById(style.id);
if (existingLink) {
existingLink.remove();
}
// add new theme
this.doc.body.appendChild(style);
this.doc.body.setAttribute('data-theme', theme);
}
}