Simple Managment webapp [LLM]

This commit is contained in:
2025-12-03 17:20:50 +01:00
parent b521f74951
commit e7f613b5dc
76 changed files with 20009 additions and 1 deletions

View File

@@ -0,0 +1,192 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../../environments/environment';
import {
User,
UserWithExtra,
Message,
MessageListParams,
MessageListResponse,
Channel,
ChannelWithSubscription,
ChannelSelector,
ChannelListResponse,
CreateChannelRequest,
UpdateChannelRequest,
Subscription,
SubscriptionFilter,
SubscriptionListResponse,
CreateSubscriptionRequest,
ConfirmSubscriptionRequest,
KeyToken,
KeyListResponse,
CreateKeyRequest,
UpdateKeyRequest,
Client,
ClientListResponse,
SenderNameStatistics,
SenderNameListResponse,
} from '../models';
@Injectable({
providedIn: 'root'
})
export class ApiService {
private http = inject(HttpClient);
private baseUrl = environment.apiUrl;
// User endpoints
getUser(userId: string): Observable<UserWithExtra> {
return this.http.get<UserWithExtra>(`${this.baseUrl}/users/${userId}`);
}
updateUser(userId: string, data: { username?: string; pro_token?: string }): Observable<User> {
return this.http.patch<User>(`${this.baseUrl}/users/${userId}`, data);
}
deleteUser(userId: string): Observable<User> {
return this.http.delete<User>(`${this.baseUrl}/users/${userId}`);
}
// Key endpoints
getKeys(userId: string): Observable<KeyListResponse> {
return this.http.get<KeyListResponse>(`${this.baseUrl}/users/${userId}/keys`);
}
getCurrentKey(userId: string): Observable<KeyToken> {
return this.http.get<KeyToken>(`${this.baseUrl}/users/${userId}/keys/current`);
}
getKey(userId: string, keyId: string): Observable<KeyToken> {
return this.http.get<KeyToken>(`${this.baseUrl}/users/${userId}/keys/${keyId}`);
}
createKey(userId: string, data: CreateKeyRequest): Observable<KeyToken> {
return this.http.post<KeyToken>(`${this.baseUrl}/users/${userId}/keys`, data);
}
updateKey(userId: string, keyId: string, data: UpdateKeyRequest): Observable<KeyToken> {
return this.http.patch<KeyToken>(`${this.baseUrl}/users/${userId}/keys/${keyId}`, data);
}
deleteKey(userId: string, keyId: string): Observable<KeyToken> {
return this.http.delete<KeyToken>(`${this.baseUrl}/users/${userId}/keys/${keyId}`);
}
// Client endpoints
getClients(userId: string): Observable<ClientListResponse> {
return this.http.get<ClientListResponse>(`${this.baseUrl}/users/${userId}/clients`);
}
getClient(userId: string, clientId: string): Observable<Client> {
return this.http.get<Client>(`${this.baseUrl}/users/${userId}/clients/${clientId}`);
}
deleteClient(userId: string, clientId: string): Observable<Client> {
return this.http.delete<Client>(`${this.baseUrl}/users/${userId}/clients/${clientId}`);
}
// Channel endpoints
getChannels(userId: string, selector?: ChannelSelector): Observable<ChannelListResponse> {
let params = new HttpParams();
if (selector) {
params = params.set('selector', selector);
}
return this.http.get<ChannelListResponse>(`${this.baseUrl}/users/${userId}/channels`, { params });
}
getChannel(userId: string, channelId: string): Observable<ChannelWithSubscription> {
return this.http.get<ChannelWithSubscription>(`${this.baseUrl}/users/${userId}/channels/${channelId}`);
}
createChannel(userId: string, data: CreateChannelRequest): Observable<ChannelWithSubscription> {
return this.http.post<ChannelWithSubscription>(`${this.baseUrl}/users/${userId}/channels`, data);
}
updateChannel(userId: string, channelId: string, data: UpdateChannelRequest): Observable<ChannelWithSubscription> {
return this.http.patch<ChannelWithSubscription>(`${this.baseUrl}/users/${userId}/channels/${channelId}`, data);
}
deleteChannel(userId: string, channelId: string): Observable<Channel> {
return this.http.delete<Channel>(`${this.baseUrl}/users/${userId}/channels/${channelId}`);
}
getChannelMessages(userId: string, channelId: string, params?: { page_size?: number; next_page_token?: string; trimmed?: boolean }): Observable<MessageListResponse> {
let httpParams = new HttpParams();
if (params?.page_size) httpParams = httpParams.set('page_size', params.page_size);
if (params?.next_page_token) httpParams = httpParams.set('next_page_token', params.next_page_token);
if (params?.trimmed !== undefined) httpParams = httpParams.set('trimmed', params.trimmed);
return this.http.get<MessageListResponse>(`${this.baseUrl}/users/${userId}/channels/${channelId}/messages`, { params: httpParams });
}
getChannelSubscriptions(userId: string, channelId: string): Observable<SubscriptionListResponse> {
return this.http.get<SubscriptionListResponse>(`${this.baseUrl}/users/${userId}/channels/${channelId}/subscriptions`);
}
// Message endpoints
getMessages(params?: MessageListParams): Observable<MessageListResponse> {
let httpParams = new HttpParams();
if (params) {
if (params.after) httpParams = httpParams.set('after', params.after);
if (params.before) httpParams = httpParams.set('before', params.before);
if (params.channel) httpParams = httpParams.set('channel', params.channel);
if (params.priority !== undefined) httpParams = httpParams.set('priority', params.priority);
if (params.search) httpParams = httpParams.set('search', params.search);
if (params.sender) httpParams = httpParams.set('sender', params.sender);
if (params.subscription_status) httpParams = httpParams.set('subscription_status', params.subscription_status);
if (params.trimmed !== undefined) httpParams = httpParams.set('trimmed', params.trimmed);
if (params.page_size) httpParams = httpParams.set('page_size', params.page_size);
if (params.next_page_token) httpParams = httpParams.set('next_page_token', params.next_page_token);
}
return this.http.get<MessageListResponse>(`${this.baseUrl}/messages`, { params: httpParams });
}
getMessage(messageId: string): Observable<Message> {
return this.http.get<Message>(`${this.baseUrl}/messages/${messageId}`);
}
deleteMessage(messageId: string): Observable<Message> {
return this.http.delete<Message>(`${this.baseUrl}/messages/${messageId}`);
}
// Subscription endpoints
getSubscriptions(userId: string, filter?: SubscriptionFilter): Observable<SubscriptionListResponse> {
let httpParams = new HttpParams();
if (filter) {
if (filter.direction) httpParams = httpParams.set('direction', filter.direction);
if (filter.confirmation) httpParams = httpParams.set('confirmation', filter.confirmation);
if (filter.external) httpParams = httpParams.set('external', filter.external);
if (filter.subscriber_user_id) httpParams = httpParams.set('subscriber_user_id', filter.subscriber_user_id);
if (filter.channel_owner_user_id) httpParams = httpParams.set('channel_owner_user_id', filter.channel_owner_user_id);
if (filter.page_size) httpParams = httpParams.set('page_size', filter.page_size);
if (filter.next_page_token) httpParams = httpParams.set('next_page_token', filter.next_page_token);
}
return this.http.get<SubscriptionListResponse>(`${this.baseUrl}/users/${userId}/subscriptions`, { params: httpParams });
}
getSubscription(userId: string, subscriptionId: string): Observable<Subscription> {
return this.http.get<Subscription>(`${this.baseUrl}/users/${userId}/subscriptions/${subscriptionId}`);
}
createSubscription(userId: string, data: CreateSubscriptionRequest): Observable<Subscription> {
return this.http.post<Subscription>(`${this.baseUrl}/users/${userId}/subscriptions`, data);
}
confirmSubscription(userId: string, subscriptionId: string, data: ConfirmSubscriptionRequest): Observable<Subscription> {
return this.http.patch<Subscription>(`${this.baseUrl}/users/${userId}/subscriptions/${subscriptionId}`, data);
}
deleteSubscription(userId: string, subscriptionId: string): Observable<Subscription> {
return this.http.delete<Subscription>(`${this.baseUrl}/users/${userId}/subscriptions/${subscriptionId}`);
}
// Sender names
getSenderNames(): Observable<SenderNameListResponse> {
return this.http.get<SenderNameListResponse>(`${this.baseUrl}/sender-names`);
}
getUserSenderNames(userId: string): Observable<SenderNameListResponse> {
return this.http.get<SenderNameListResponse>(`${this.baseUrl}/users/${userId}/sender-names`);
}
}

View File

@@ -0,0 +1,54 @@
import { Injectable, signal, computed } from '@angular/core';
const USER_ID_KEY = 'scn_user_id';
const ADMIN_KEY_KEY = 'scn_admin_key';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private userId = signal<string | null>(null);
private adminKey = signal<string | null>(null);
isAuthenticated = computed(() => !!this.userId() && !!this.adminKey());
constructor() {
this.loadFromStorage();
}
private loadFromStorage(): void {
const userId = sessionStorage.getItem(USER_ID_KEY);
const adminKey = sessionStorage.getItem(ADMIN_KEY_KEY);
if (userId && adminKey) {
this.userId.set(userId);
this.adminKey.set(adminKey);
}
}
login(userId: string, adminKey: string): void {
sessionStorage.setItem(USER_ID_KEY, userId);
sessionStorage.setItem(ADMIN_KEY_KEY, adminKey);
this.userId.set(userId);
this.adminKey.set(adminKey);
}
logout(): void {
sessionStorage.removeItem(USER_ID_KEY);
sessionStorage.removeItem(ADMIN_KEY_KEY);
this.userId.set(null);
this.adminKey.set(null);
}
getUserId(): string | null {
return this.userId();
}
getAdminKey(): string | null {
return this.adminKey();
}
getAuthHeader(): string | null {
const key = this.adminKey();
return key ? `SCN ${key}` : null;
}
}

View File

@@ -0,0 +1,3 @@
export * from './auth.service';
export * from './api.service';
export * from './notification.service';

View File

@@ -0,0 +1,33 @@
import { Injectable, inject } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message';
@Injectable({
providedIn: 'root'
})
export class NotificationService {
private message = inject(NzMessageService);
success(content: string): void {
this.message.success(content);
}
error(content: string): void {
this.message.error(content);
}
warning(content: string): void {
this.message.warning(content);
}
info(content: string): void {
this.message.info(content);
}
loading(content: string): string {
return this.message.loading(content, { nzDuration: 0 }).messageId;
}
remove(id: string): void {
this.message.remove(id);
}
}