feat: add setup/cache page
This commit is contained in:
parent
02f7c33b91
commit
b0b41fcdc5
69
src/pages/setup/cache/cache.component.ts
vendored
Normal file
69
src/pages/setup/cache/cache.component.ts
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {NavigationService} from "@service/navigation.service";
|
||||||
|
import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
|
||||||
|
import SetupService from "@api/v1/setup.service";
|
||||||
|
import {MatFormFieldModule} from "@angular/material/form-field";
|
||||||
|
import {MatSelectModule} from "@angular/material/select";
|
||||||
|
import {MatInput} from "@angular/material/input";
|
||||||
|
import {MatTooltip} from "@angular/material/tooltip";
|
||||||
|
import {MatIconButton} from "@angular/material/button";
|
||||||
|
import {MatIcon} from "@angular/material/icon";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cache',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatSelectModule,
|
||||||
|
MatInput,
|
||||||
|
MatTooltip,
|
||||||
|
MatIconButton,
|
||||||
|
MatIcon
|
||||||
|
],
|
||||||
|
templateUrl: './cache.component.html'
|
||||||
|
})
|
||||||
|
|
||||||
|
export class CacheComponent {
|
||||||
|
protected databaseForm!: FormGroup;
|
||||||
|
protected database = '';
|
||||||
|
protected hidePass = true;
|
||||||
|
|
||||||
|
constructor(private navigationService: NavigationService, private formBuilder: FormBuilder, private api: SetupService) {
|
||||||
|
this.databaseForm = this.formBuilder.group({
|
||||||
|
server: ['', Validators.pattern(/^([A-Za-z0-9]+\.)+[A-Za-z]{2,}$|^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$|^([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}$|^::1$/)],
|
||||||
|
port: ['', Validators.pattern(/^[1-9][0-9]{2,}$/)],
|
||||||
|
password: ['']
|
||||||
|
});
|
||||||
|
|
||||||
|
this.navigationService.setNextButtonState(false);
|
||||||
|
this.databaseForm.valueChanges.subscribe(() => {
|
||||||
|
this.navigationService.setNextButtonState(this.databaseForm.valid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDatabaseChange(selectedDatabase: string) {
|
||||||
|
this.database = selectedDatabase;
|
||||||
|
|
||||||
|
if (selectedDatabase === 'memcached') {
|
||||||
|
this.navigationService.nextButtonAction = () => {
|
||||||
|
return this.api.setMemcached();
|
||||||
|
};
|
||||||
|
this.navigationService.setNextButtonState(true);
|
||||||
|
} else {
|
||||||
|
this.navigationService.nextButtonAction = () => {
|
||||||
|
return this.api.setRedis({
|
||||||
|
"server": this.databaseForm.get('server')?.value,
|
||||||
|
"port": this.databaseForm.get('port')?.value,
|
||||||
|
"password": this.databaseForm.get('password')?.value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.navigationService.setNextButtonState(this.databaseForm.valid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected togglePassword(event: MouseEvent) {
|
||||||
|
this.hidePass = !this.hidePass;
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
65
src/services/cache.service.ts
Normal file
65
src/services/cache.service.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
interface CacheEntry<T> {
|
||||||
|
data: T;
|
||||||
|
expiry: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CacheService {
|
||||||
|
private handleQuotaExceeded(): void {
|
||||||
|
const keys: string[] = [];
|
||||||
|
const expiries: number[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i);
|
||||||
|
if (!key) continue;
|
||||||
|
|
||||||
|
const cacheEntry = JSON.parse(localStorage.getItem(key) as string) as CacheEntry<any>;
|
||||||
|
keys.push(key);
|
||||||
|
expiries.push(cacheEntry.expiry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем самый старый элемент
|
||||||
|
const oldestIndex = expiries.indexOf(Math.min(...expiries));
|
||||||
|
localStorage.removeItem(keys[oldestIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private isQuotaExceededError(e: unknown): e is DOMException {
|
||||||
|
return e instanceof DOMException && (
|
||||||
|
e.name === 'QuotaExceededError' ||
|
||||||
|
e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
set<T>(key: string, data: T, ttl: number): void {
|
||||||
|
const expiry = Date.now() + ttl;
|
||||||
|
const cacheEntry: CacheEntry<T> = {data, expiry};
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage.setItem(key, JSON.stringify(cacheEntry));
|
||||||
|
} catch (e) {
|
||||||
|
if (this.isQuotaExceededError(e)) {
|
||||||
|
this.handleQuotaExceeded();
|
||||||
|
localStorage.setItem(key, JSON.stringify(cacheEntry));
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get<T>(key: string): T | null {
|
||||||
|
const cached = localStorage.getItem(key);
|
||||||
|
if (!cached) return null;
|
||||||
|
|
||||||
|
const cacheEntry = JSON.parse(cached) as CacheEntry<T>;
|
||||||
|
if (Date.now() > cacheEntry.expiry) {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cacheEntry.data;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user