frontend: add loading state handling in DevelopersComponent
This commit is contained in:
parent
e1bf07532c
commit
a3560ee845
@ -7,48 +7,65 @@
|
||||
<p class="subtitle">Everyting you need to embed OpenVidu Meet in your applications.</p>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<!-- API KEY Section -->
|
||||
<mat-card class="section-card api-key-section">
|
||||
<mat-card-header>
|
||||
<div mat-card-avatar>
|
||||
<mat-icon class="section-icon">vpn_key</mat-icon>
|
||||
</div>
|
||||
<mat-card-title>API KEY</mat-card-title>
|
||||
<mat-card-subtitle>Generate and manage your API key for REST API access</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content>
|
||||
@if (apiKeyData()) {
|
||||
<div class="api-key-display">
|
||||
<mat-form-field subscriptSizing="dynamic" appearance="outline" class="api-key-field">
|
||||
<mat-label>API Key</mat-label>
|
||||
<input
|
||||
matInput
|
||||
readonly
|
||||
[type]="showApiKey() ? 'text' : 'password'"
|
||||
[value]="apiKeyData()!.key"
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
matSuffix
|
||||
(click)="toggleApiKeyVisibility()"
|
||||
matTooltip="Toggle visibility"
|
||||
class="toggle-visibility-button"
|
||||
>
|
||||
<mat-icon>{{ showApiKey() ? 'visibility_off' : 'visibility' }}</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="api-key-actions">
|
||||
<button mat-button (click)="copyApiKey()" class="copy-button">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
@if (isLoading()) {
|
||||
<div class="ov-page-loading">
|
||||
<div class="loading-content">
|
||||
<div class="loading-header">
|
||||
<div class="loading-title">
|
||||
<mat-icon class="ov-settings-icon loading-icon">settings</mat-icon>
|
||||
<h1>Loading Settings</h1>
|
||||
</div>
|
||||
<p class="loading-subtitle">Please wait while we fetch your settings...</p>
|
||||
</div>
|
||||
|
||||
<!-- <div class="api-key-info">
|
||||
<div class="loading-spinner-container">
|
||||
<mat-spinner diameter="48"></mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="page-content">
|
||||
<!-- API KEY Section -->
|
||||
<mat-card class="section-card api-key-section">
|
||||
<mat-card-header>
|
||||
<div mat-card-avatar>
|
||||
<mat-icon class="section-icon">vpn_key</mat-icon>
|
||||
</div>
|
||||
<mat-card-title>API KEY</mat-card-title>
|
||||
<mat-card-subtitle>Generate and manage your API key for REST API access</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content>
|
||||
@if (apiKeyData()) {
|
||||
<div class="api-key-display">
|
||||
<mat-form-field subscriptSizing="dynamic" appearance="outline" class="api-key-field">
|
||||
<mat-label>API Key</mat-label>
|
||||
<input
|
||||
matInput
|
||||
readonly
|
||||
[type]="showApiKey() ? 'text' : 'password'"
|
||||
[value]="apiKeyData()!.key"
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
matSuffix
|
||||
(click)="toggleApiKeyVisibility()"
|
||||
matTooltip="Toggle visibility"
|
||||
class="toggle-visibility-button"
|
||||
>
|
||||
<mat-icon>{{ showApiKey() ? 'visibility_off' : 'visibility' }}</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="api-key-actions">
|
||||
<button mat-button (click)="copyApiKey()" class="copy-button">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="api-key-info">
|
||||
<p class="info-text">
|
||||
<mat-icon class="info-icon">info</mat-icon>
|
||||
Generated on: {{ apiKeyData()!.creationDate | date: 'medium' }}
|
||||
@ -58,71 +75,70 @@
|
||||
Keep your API key secure. Do not share it publicly or expose it in client-side code.
|
||||
</p>
|
||||
</div> -->
|
||||
} @else {
|
||||
<div class="no-api-key">
|
||||
<h3>No API Key Generated</h3>
|
||||
<p>Generate an API key to access OpenVidu Meet REST API endpoints.</p>
|
||||
<button mat-raised-button class (click)="generateApiKey()">
|
||||
<mat-icon>vpn_key</mat-icon>
|
||||
Generate API Key
|
||||
} @else {
|
||||
<div class="no-api-key">
|
||||
<h3>No API Key Generated</h3>
|
||||
<p>Generate an API key to access OpenVidu Meet REST API endpoints.</p>
|
||||
<button mat-raised-button class (click)="generateApiKey()">
|
||||
<mat-icon>vpn_key</mat-icon>
|
||||
Generate API Key
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
|
||||
@if (apiKeyData()) {
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="primary" (click)="regenerateApiKey()">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
Regenerate Key
|
||||
</button>
|
||||
</div>
|
||||
<button mat-stroked-button id="revoke-key-btn" (click)="revokeApiKey()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
Revoke Key
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
@if (apiKeyData()) {
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="primary" (click)="regenerateApiKey()">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
Regenerate Key
|
||||
</button>
|
||||
<button mat-stroked-button id="revoke-key-btn" (click)="revokeApiKey()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
Revoke Key
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
}
|
||||
</mat-card>
|
||||
|
||||
<!-- WEBHOOKS Section -->
|
||||
<mat-card class="section-card webhooks-section">
|
||||
<mat-card-header>
|
||||
<div mat-card-avatar>
|
||||
<mat-icon class="section-icon">webhook</mat-icon>
|
||||
</div>
|
||||
<mat-card-title>WEBHOOKS</mat-card-title>
|
||||
<mat-card-subtitle>Configure webhook notifications for real-time event updates</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content class="ov-mt-sm">
|
||||
<form [formGroup]="webhookForm" class="webhook-form">
|
||||
<!-- Enable/Disable Toggle -->
|
||||
<h4 class="webhook-section-title">Webhook Notifications</h4>
|
||||
<div class="webhook-toggle ov-mt-xs">
|
||||
<span>Enable webhook notifications</span>
|
||||
<mat-slide-toggle formControlName="isEnabled"></mat-slide-toggle>
|
||||
<!-- WEBHOOKS Section -->
|
||||
<mat-card class="section-card webhooks-section">
|
||||
<mat-card-header>
|
||||
<div mat-card-avatar>
|
||||
<mat-icon class="section-icon">webhook</mat-icon>
|
||||
</div>
|
||||
<mat-card-title>WEBHOOKS</mat-card-title>
|
||||
<mat-card-subtitle>Configure webhook notifications for real-time event updates</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
|
||||
<!-- Webhook URL -->
|
||||
<h4 class="webhook-section-title">Webhook URL</h4>
|
||||
<p class="webhook-description ov-mt-xs">
|
||||
Enter the URL where you want to receive webhook notifications.
|
||||
</p>
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Webhook URL</mat-label>
|
||||
<input matInput formControlName="url" placeholder="https://your-server.com/webhook" />
|
||||
<mat-icon matSuffix>link</mat-icon>
|
||||
@if (webhookForm.get('url')?.hasError('required')) {
|
||||
<mat-error>Webhook URL is required</mat-error>
|
||||
}
|
||||
@if (webhookForm.get('url')?.hasError('pattern')) {
|
||||
<mat-error>Please enter a valid HTTP(S) URL</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-card-content class="ov-mt-sm">
|
||||
<form [formGroup]="webhookForm" class="webhook-form">
|
||||
<!-- Enable/Disable Toggle -->
|
||||
<h4 class="webhook-section-title">Webhook Notifications</h4>
|
||||
<div class="webhook-toggle ov-mt-xs">
|
||||
<span>Enable webhook notifications</span>
|
||||
<mat-slide-toggle formControlName="isEnabled"></mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<!-- Webhook URL -->
|
||||
<h4 class="webhook-section-title">Webhook URL</h4>
|
||||
<p class="webhook-description ov-mt-xs">
|
||||
Enter the URL where you want to receive webhook notifications.
|
||||
</p>
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Webhook URL</mat-label>
|
||||
<input matInput formControlName="url" placeholder="https://your-server.com/webhook" />
|
||||
<mat-icon matSuffix>link</mat-icon>
|
||||
@if (webhookForm.get('url')?.hasError('required')) {
|
||||
<mat-error>Webhook URL is required</mat-error>
|
||||
}
|
||||
@if (webhookForm.get('url')?.hasError('pattern')) {
|
||||
<mat-error>Please enter a valid HTTP(S) URL</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Event Configuration -->
|
||||
<!-- <div class="events-section">
|
||||
<!-- Event Configuration -->
|
||||
<!-- <div class="events-section">
|
||||
<h4>Event Types</h4>
|
||||
<p class="events-description">Choose which events should trigger webhook notifications</p>
|
||||
|
||||
@ -158,24 +174,29 @@
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</form>
|
||||
</mat-card-content>
|
||||
</form>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="saveWebhookConfig()"
|
||||
[disabled]="webhookForm.invalid"
|
||||
>
|
||||
<mat-icon>save</mat-icon>
|
||||
Save Configuration
|
||||
</button>
|
||||
<button mat-stroked-button (click)="testWebhook()" [disabled]="!webhookForm.get('url')?.value">
|
||||
<mat-icon>send</mat-icon>
|
||||
Test Webhook
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
<mat-card-actions>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="saveWebhookConfig()"
|
||||
[disabled]="webhookForm.invalid"
|
||||
>
|
||||
<mat-icon>save</mat-icon>
|
||||
Save Configuration
|
||||
</button>
|
||||
<button
|
||||
mat-stroked-button
|
||||
(click)="testWebhook()"
|
||||
[disabled]="webhookForm.get('url')?.disabled || webhookForm.get('url')?.invalid"
|
||||
>
|
||||
<mat-icon>send</mat-icon>
|
||||
Test Webhook
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import { Clipboard } from '@angular/cdk/clipboard';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, OnInit, signal } from '@angular/core';
|
||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { AuthService, GlobalPreferencesService, NotificationService } from '@lib/services';
|
||||
import { MeetApiKey } from '@lib/typings/ce';
|
||||
@ -18,22 +16,22 @@ import { MeetApiKey } from '@lib/typings/ce';
|
||||
selector: 'ov-developers-settings',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatSlideToggleModule,
|
||||
MatSnackBarModule,
|
||||
MatTooltipModule,
|
||||
MatDividerModule,
|
||||
ReactiveFormsModule
|
||||
ReactiveFormsModule,
|
||||
MatProgressSpinnerModule
|
||||
],
|
||||
templateUrl: './developers.component.html',
|
||||
styleUrl: './developers.component.scss'
|
||||
})
|
||||
export class DevelopersSettingsComponent implements OnInit {
|
||||
isLoading = signal(true);
|
||||
|
||||
apiKeyData = signal<MeetApiKey | undefined>(undefined);
|
||||
showApiKey = signal(false);
|
||||
|
||||
@ -66,8 +64,10 @@ export class DevelopersSettingsComponent implements OnInit {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.isLoading.set(true);
|
||||
await this.loadApiKeyData();
|
||||
await this.loadWebhookConfig();
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
|
||||
// ===== API KEY METHODS =====
|
||||
|
||||
@ -31,7 +31,7 @@ import { AuthMode } from '@lib/typings/ce';
|
||||
styleUrl: './users-permissions.component.scss'
|
||||
})
|
||||
export class UsersPermissionsComponent implements OnInit {
|
||||
isLoading = signal(false);
|
||||
isLoading = signal(true);
|
||||
|
||||
adminCredentialsForm = new FormGroup({
|
||||
adminUsername: new FormControl({ value: '', disabled: true }, [Validators.required]),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user