Accueil > [ancêtres de catégorie] > [titre API], ou Accueil > Parcourir > [titre API] si l'API n'a pas de catégorie. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
533 lines
22 KiB
TypeScript
533 lines
22 KiB
TypeScript
import {
|
|
Component,
|
|
signal,
|
|
inject,
|
|
OnInit,
|
|
OnDestroy,
|
|
ChangeDetectionStrategy,
|
|
} from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
|
import { ApiService } from '../../core/api.service';
|
|
import { CategoryService } from '../../core/category.service';
|
|
import { ApiEntry, Category, ApiConvention } from '@datacat/shared';
|
|
|
|
@Component({
|
|
selector: 'app-api-detail',
|
|
standalone: true,
|
|
imports: [CommonModule, RouterLink],
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
template: `
|
|
<div class="fr-container fr-mt-4w fr-mb-4w">
|
|
<!-- Fil d'Ariane -->
|
|
<nav class="fr-breadcrumb fr-mb-3w" aria-label="vous êtes ici">
|
|
<ol class="fr-breadcrumb__list">
|
|
<li>
|
|
<a class="fr-breadcrumb__link" routerLink="/">Accueil</a>
|
|
</li>
|
|
@if (categoryBreadcrumb().length === 0) {
|
|
<li><a class="fr-breadcrumb__link" routerLink="/browse">Parcourir</a></li>
|
|
}
|
|
@for (crumb of categoryBreadcrumb(); track crumb.id) {
|
|
<li><a class="fr-breadcrumb__link" [routerLink]="['/browse', crumb.id]">{{ crumb.name }}</a></li>
|
|
}
|
|
<li>
|
|
<a class="fr-breadcrumb__link" aria-current="page">
|
|
{{ api()?.title ?? 'Chargement...' }}
|
|
</a>
|
|
</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
@if (loading()) {
|
|
<div class="fr-callout fr-mb-4w">
|
|
<p class="fr-callout__text">Chargement...</p>
|
|
</div>
|
|
}
|
|
|
|
@if (error()) {
|
|
<div class="fr-alert fr-alert--error fr-mb-4w">
|
|
<p class="fr-alert__title">Erreur</p>
|
|
<p>{{ error() }}</p>
|
|
</div>
|
|
}
|
|
|
|
@if (api(); as entry) {
|
|
<!-- En-tête -->
|
|
<div class="fr-grid-row fr-grid-row--middle fr-mb-3w">
|
|
<div class="fr-col">
|
|
<h1 class="fr-h2 fr-mb-1w">{{ entry.title }}</h1>
|
|
<div class="fr-tags-group">
|
|
<span class="fr-tag">{{ entry.type }}</span>
|
|
<span class="fr-tag">v{{ entry.version }}</span>
|
|
<span [class]="badgeClass(entry.status)">{{ entry.status }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Alerte statut PENDING -->
|
|
@if (entry.status === 'PENDING') {
|
|
<div class="fr-alert fr-alert--info fr-mb-3w">
|
|
<p class="fr-alert__title">Génération en cours</p>
|
|
<p>La documentation est en cours de génération. Cette page se rafraîchit automatiquement.</p>
|
|
</div>
|
|
}
|
|
|
|
<!-- Alerte statut ERROR -->
|
|
@if (entry.status === 'ERROR') {
|
|
<div class="fr-alert fr-alert--error fr-mb-3w">
|
|
<p class="fr-alert__title">Erreur de génération</p>
|
|
<p>{{ entry.errorMessage }}</p>
|
|
</div>
|
|
}
|
|
|
|
<!-- Métadonnées -->
|
|
<div class="fr-card fr-mb-4w">
|
|
<div class="fr-card__body">
|
|
<div class="fr-card__content">
|
|
<h2 class="fr-h5 fr-mb-2w">Informations</h2>
|
|
<dl class="fr-grid-row fr-grid-row--gutters">
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<dt class="fr-text--bold">Version</dt>
|
|
<dd>{{ entry.version }}</dd>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<dt class="fr-text--bold">Type</dt>
|
|
<dd>{{ entry.type }}</dd>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<dt class="fr-text--bold">Fournisseur</dt>
|
|
<dd>{{ entry.provider }}</dd>
|
|
</div>
|
|
@if (entry.description) {
|
|
<div class="fr-col-12">
|
|
<dt class="fr-text--bold">Description</dt>
|
|
<dd>{{ entry.description }}</dd>
|
|
</div>
|
|
}
|
|
<div class="fr-col-12 fr-col-md-6">
|
|
<dt class="fr-text--bold">Créé le</dt>
|
|
<dd>{{ entry.createdAt | date:'dd/MM/yyyy HH:mm' }}</dd>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-6">
|
|
<dt class="fr-text--bold">Mis à jour le</dt>
|
|
<dd>{{ entry.updatedAt | date:'dd/MM/yyyy HH:mm' }}</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Contacts -->
|
|
<div class="fr-card fr-mb-4w">
|
|
<div class="fr-card__body">
|
|
<div class="fr-card__content">
|
|
<h2 class="fr-h5 fr-mb-2w">Contacts</h2>
|
|
<div class="fr-grid-row fr-grid-row--gutters">
|
|
<div class="fr-col-12 fr-col-md-6">
|
|
<p class="fr-text--bold fr-mb-1w">Contact métier</p>
|
|
<p class="fr-mb-0">{{ entry.contactFunctionalName }}</p>
|
|
<p class="fr-mb-0 fr-text--sm">{{ entry.contactFunctionalEntity }}</p>
|
|
<p class="fr-mb-0 fr-text--sm">{{ entry.contactFunctionalEmail }}</p>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-6">
|
|
<p class="fr-text--bold fr-mb-1w">Contact technique</p>
|
|
<p class="fr-mb-0">{{ entry.contactTechnicalName }}</p>
|
|
<p class="fr-mb-0 fr-text--sm">{{ entry.contactTechnicalEntity }}</p>
|
|
<p class="fr-mb-0 fr-text--sm">{{ entry.contactTechnicalEmail }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="fr-btns-group fr-btns-group--inline-sm">
|
|
<a
|
|
[routerLink]="['/catalog', entry.id, 'docs']"
|
|
class="fr-btn"
|
|
[class.fr-btn--disabled]="entry.status !== 'GENERATED'"
|
|
[attr.aria-disabled]="entry.status !== 'GENERATED' ? 'true' : null"
|
|
>
|
|
Voir la documentation
|
|
</a>
|
|
<button class="fr-btn fr-btn--secondary" (click)="openEdit()">
|
|
Modifier
|
|
</button>
|
|
<a
|
|
[href]="'/api/apis/' + entry.id + '/yaml'"
|
|
class="fr-btn fr-btn--secondary"
|
|
download
|
|
>
|
|
Télécharger YAML
|
|
</a>
|
|
<button
|
|
class="fr-btn fr-btn--secondary"
|
|
(click)="onRegenerate()"
|
|
[disabled]="regenerating()"
|
|
>
|
|
{{ regenerating() ? 'Régénération...' : 'Régénérer' }}
|
|
</button>
|
|
<button
|
|
class="fr-btn fr-btn--secondary"
|
|
(click)="onDelete()"
|
|
[disabled]="deleting()"
|
|
>
|
|
{{ deleting() ? 'Suppression...' : 'Supprimer' }}
|
|
</button>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<!-- Modale édition -->
|
|
@if (showEditModal()) {
|
|
<div style="position:fixed;inset:0;z-index:9999;background:rgba(22,22,22,.64);display:flex;align-items:flex-start;justify-content:center;padding-top:5vh;overflow-y:auto"
|
|
role="dialog" aria-modal="true" aria-labelledby="edit-modal-title">
|
|
<div style="background:white;width:calc(100% - 2rem);max-width:640px;margin:0 1rem 2rem">
|
|
<div class="fr-p-4w">
|
|
<div class="fr-grid-row fr-grid-row--middle fr-mb-3w">
|
|
<div class="fr-col">
|
|
<h2 id="edit-modal-title" class="fr-h3 fr-mb-0">Modifier l'API</h2>
|
|
</div>
|
|
<div class="fr-col-auto">
|
|
<button class="fr-btn fr-btn--tertiary-no-outline fr-btn--sm" (click)="closeEdit()">✕</button>
|
|
</div>
|
|
</div>
|
|
@if (editError()) {
|
|
<div class="fr-alert fr-alert--error fr-mb-2w"><p>{{ editError() }}</p></div>
|
|
}
|
|
|
|
<!-- Convention + Nom -->
|
|
<p class="fr-label fr-mb-1w">Titre <span style="color:var(--text-default-error)">*</span></p>
|
|
<div class="fr-grid-row fr-grid-row--gutters fr-mb-1w">
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-select-group">
|
|
<label class="fr-label" for="edit-convention">Convention</label>
|
|
<select id="edit-convention" class="fr-select" [value]="editConvention()"
|
|
(change)="editConvention.set($any($event.target).value)">
|
|
<option value="CONSULTER">Consulter</option>
|
|
<option value="ENREGISTRER">Enregistrer</option>
|
|
<option value="ETRE_NOTIFIE">Être notifié</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-8">
|
|
<div class="fr-input-group" [class.fr-input-group--error]="editNameError()">
|
|
<label class="fr-label" for="edit-name">Nom de l'API</label>
|
|
<input id="edit-name" class="fr-input" [class.fr-input--error]="editNameError()" type="text"
|
|
[value]="editName()"
|
|
(input)="editName.set($any($event.target).value); editNameError.set(false)"
|
|
(blur)="editNameError.set(!editName().trim())" />
|
|
@if (editNameError()) { <p class="fr-error-text">Le nom est obligatoire.</p> }
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p class="fr-hint-text fr-mb-2w">Titre : <strong>{{ editPreviewTitle() }}</strong></p>
|
|
|
|
<!-- Catégorie -->
|
|
<div class="fr-select-group fr-mb-2w">
|
|
<label class="fr-label" for="edit-category">Catégorie</label>
|
|
<select id="edit-category" class="fr-select" [value]="editCategoryId()"
|
|
(change)="editCategoryId.set($any($event.target).value || null)">
|
|
<option value="">— Sans catégorie —</option>
|
|
@for (cat of categories(); track cat.id) {
|
|
<option [value]="cat.id">{{ cat.name }}</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Fournisseur -->
|
|
<div class="fr-input-group fr-mb-2w" [class.fr-input-group--error]="editProviderError()">
|
|
<label class="fr-label" for="edit-provider">Fournisseur <span style="color:var(--text-default-error)">*</span></label>
|
|
<input id="edit-provider" class="fr-input" [class.fr-input--error]="editProviderError()" type="text"
|
|
[value]="editProvider()"
|
|
(input)="editProvider.set($any($event.target).value); editProviderError.set(false)"
|
|
(blur)="editProviderError.set(!editProvider().trim())" />
|
|
@if (editProviderError()) { <p class="fr-error-text">Le fournisseur est obligatoire.</p> }
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<div class="fr-input-group fr-mb-2w">
|
|
<label class="fr-label" for="edit-description">Description</label>
|
|
<textarea id="edit-description" class="fr-input" rows="3" [value]="editDescription()"
|
|
(input)="editDescription.set($any($event.target).value)"></textarea>
|
|
</div>
|
|
|
|
<!-- Version -->
|
|
<p class="fr-label fr-mb-1w">Version <span style="color:var(--text-default-error)">*</span></p>
|
|
<div class="fr-grid-row fr-grid-row--gutters fr-mb-2w">
|
|
<div class="fr-col-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-v-major">Majeure (X)</label>
|
|
<input id="edit-v-major" class="fr-input" type="number" min="0"
|
|
[value]="editVersionMajor()"
|
|
(input)="editVersionMajor.set(+$any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-v-minor">Mineure (Y)</label>
|
|
<input id="edit-v-minor" class="fr-input" type="number" min="0"
|
|
[value]="editVersionMinor()"
|
|
(input)="editVersionMinor.set(+$any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-v-patch">Correctif (Z)</label>
|
|
<input id="edit-v-patch" class="fr-input" type="number" min="0"
|
|
[value]="editVersionPatch()"
|
|
(input)="editVersionPatch.set(+$any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Contact métier -->
|
|
<p class="fr-label fr-mb-1w">Contact métier <span style="color:var(--text-default-error)">*</span></p>
|
|
<div class="fr-grid-row fr-grid-row--gutters fr-mb-2w">
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-cf-name">Nom et prénom</label>
|
|
<input id="edit-cf-name" class="fr-input" type="text" [value]="editContactFunctionalName()"
|
|
(input)="editContactFunctionalName.set($any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-cf-entity">Entité</label>
|
|
<input id="edit-cf-entity" class="fr-input" type="text" [value]="editContactFunctionalEntity()"
|
|
(input)="editContactFunctionalEntity.set($any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-cf-email">Email</label>
|
|
<input id="edit-cf-email" class="fr-input" type="email" [value]="editContactFunctionalEmail()"
|
|
(input)="editContactFunctionalEmail.set($any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Contact technique -->
|
|
<p class="fr-label fr-mb-1w">Contact technique <span style="color:var(--text-default-error)">*</span></p>
|
|
<div class="fr-grid-row fr-grid-row--gutters fr-mb-3w">
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-ct-name">Nom et prénom</label>
|
|
<input id="edit-ct-name" class="fr-input" type="text" [value]="editContactTechnicalName()"
|
|
(input)="editContactTechnicalName.set($any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-ct-entity">Entité</label>
|
|
<input id="edit-ct-entity" class="fr-input" type="text" [value]="editContactTechnicalEntity()"
|
|
(input)="editContactTechnicalEntity.set($any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
<div class="fr-col-12 fr-col-md-4">
|
|
<div class="fr-input-group">
|
|
<label class="fr-label" for="edit-ct-email">Email</label>
|
|
<input id="edit-ct-email" class="fr-input" type="email" [value]="editContactTechnicalEmail()"
|
|
(input)="editContactTechnicalEmail.set($any($event.target).value)" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="fr-btns-group fr-btns-group--right fr-btns-group--inline">
|
|
<button class="fr-btn fr-btn--secondary" (click)="closeEdit()">Annuler</button>
|
|
<button class="fr-btn" (click)="submitEdit()" [disabled]="editLoading()">
|
|
{{ editLoading() ? 'Enregistrement...' : 'Enregistrer' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
`,
|
|
})
|
|
export class ApiDetailComponent implements OnInit, OnDestroy {
|
|
private route = inject(ActivatedRoute);
|
|
private router = inject(Router);
|
|
private apiService = inject(ApiService);
|
|
private categoryService = inject(CategoryService);
|
|
|
|
api = signal<ApiEntry | null>(null);
|
|
categoryBreadcrumb = signal<Category[]>([]);
|
|
loading = signal(false);
|
|
error = signal<string | null>(null);
|
|
regenerating = signal(false);
|
|
deleting = signal(false);
|
|
|
|
/* Modale édition */
|
|
showEditModal = signal(false);
|
|
editLoading = signal(false);
|
|
editError = signal<string | null>(null);
|
|
editNameError = signal(false);
|
|
editProviderError = signal(false);
|
|
categories = signal<Category[]>([]);
|
|
editConvention = signal<ApiConvention>('CONSULTER');
|
|
editName = signal('');
|
|
editProvider = signal('');
|
|
editVersionMajor = signal(0);
|
|
editVersionMinor = signal(0);
|
|
editVersionPatch = signal(0);
|
|
editCategoryId = signal<string | null>(null);
|
|
editDescription = signal('');
|
|
editContactFunctionalName = signal('');
|
|
editContactFunctionalEntity = signal('');
|
|
editContactFunctionalEmail = signal('');
|
|
editContactTechnicalName = signal('');
|
|
editContactTechnicalEntity = signal('');
|
|
editContactTechnicalEmail = signal('');
|
|
|
|
editPreviewTitle() {
|
|
const labels: Record<ApiConvention, string> = { CONSULTER: 'Consulter', ENREGISTRER: 'Enregistrer', ETRE_NOTIFIE: 'Être notifié' };
|
|
return `${labels[this.editConvention()]} ${this.editName()}`.trim();
|
|
}
|
|
|
|
private pollInterval: ReturnType<typeof setInterval> | null = null;
|
|
private id = '';
|
|
|
|
ngOnInit() {
|
|
this.id = this.route.snapshot.paramMap.get('id') ?? '';
|
|
this.loadApi();
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.clearPoll();
|
|
}
|
|
|
|
onRegenerate() {
|
|
this.regenerating.set(true);
|
|
this.apiService.regenerate(this.id).subscribe({
|
|
next: (entry) => {
|
|
this.api.set(entry);
|
|
this.regenerating.set(false);
|
|
this.startPollIfPending();
|
|
},
|
|
error: () => this.regenerating.set(false),
|
|
});
|
|
}
|
|
|
|
openEdit() {
|
|
const entry = this.api();
|
|
if (!entry) return;
|
|
this.editConvention.set(entry.convention);
|
|
this.editName.set(entry.name);
|
|
this.editProvider.set(entry.provider);
|
|
this.editVersionMajor.set(entry.versionMajor);
|
|
this.editVersionMinor.set(entry.versionMinor);
|
|
this.editVersionPatch.set(entry.versionPatch);
|
|
this.editCategoryId.set(entry.categoryId ?? null);
|
|
this.editDescription.set(entry.description ?? '');
|
|
this.editContactFunctionalName.set(entry.contactFunctionalName);
|
|
this.editContactFunctionalEntity.set(entry.contactFunctionalEntity);
|
|
this.editContactFunctionalEmail.set(entry.contactFunctionalEmail);
|
|
this.editContactTechnicalName.set(entry.contactTechnicalName);
|
|
this.editContactTechnicalEntity.set(entry.contactTechnicalEntity);
|
|
this.editContactTechnicalEmail.set(entry.contactTechnicalEmail);
|
|
this.editError.set(null);
|
|
this.editNameError.set(false);
|
|
this.editProviderError.set(false);
|
|
this.categoryService.list().subscribe((res) => this.categories.set(res.items));
|
|
this.showEditModal.set(true);
|
|
}
|
|
|
|
closeEdit() {
|
|
this.showEditModal.set(false);
|
|
}
|
|
|
|
submitEdit() {
|
|
this.editNameError.set(!this.editName().trim());
|
|
this.editProviderError.set(!this.editProvider().trim());
|
|
if (!this.editName().trim() || !this.editProvider().trim()) return;
|
|
this.editLoading.set(true);
|
|
this.apiService.update(this.id, {
|
|
convention: this.editConvention(),
|
|
name: this.editName().trim(),
|
|
provider: this.editProvider().trim(),
|
|
versionMajor: this.editVersionMajor(),
|
|
versionMinor: this.editVersionMinor(),
|
|
versionPatch: this.editVersionPatch(),
|
|
categoryId: this.editCategoryId() || null,
|
|
description: this.editDescription().trim() || null,
|
|
contactFunctionalName: this.editContactFunctionalName().trim(),
|
|
contactFunctionalEntity: this.editContactFunctionalEntity().trim(),
|
|
contactFunctionalEmail: this.editContactFunctionalEmail().trim(),
|
|
contactTechnicalName: this.editContactTechnicalName().trim(),
|
|
contactTechnicalEntity: this.editContactTechnicalEntity().trim(),
|
|
contactTechnicalEmail: this.editContactTechnicalEmail().trim(),
|
|
}).subscribe({
|
|
next: (entry) => {
|
|
this.api.set(entry);
|
|
this.editLoading.set(false);
|
|
this.showEditModal.set(false);
|
|
},
|
|
error: (err: { error?: { message?: string } }) => {
|
|
this.editLoading.set(false);
|
|
this.editError.set(err?.error?.message ?? 'Une erreur est survenue.');
|
|
},
|
|
});
|
|
}
|
|
|
|
onDelete() {
|
|
if (!confirm('Supprimer cette API ?')) return;
|
|
this.deleting.set(true);
|
|
this.apiService.delete(this.id).subscribe({
|
|
next: () => this.router.navigate(['/catalog']),
|
|
error: () => this.deleting.set(false),
|
|
});
|
|
}
|
|
|
|
badgeClass(status: string): string {
|
|
if (status === 'GENERATED') return 'fr-badge fr-badge--success';
|
|
if (status === 'ERROR') return 'fr-badge fr-badge--error';
|
|
return 'fr-badge fr-badge--info';
|
|
}
|
|
|
|
private loadApi() {
|
|
this.loading.set(true);
|
|
this.apiService.get(this.id).subscribe({
|
|
next: (entry) => {
|
|
this.api.set(entry);
|
|
this.loading.set(false);
|
|
this.startPollIfPending();
|
|
if (entry.categoryId) {
|
|
this.categoryService.browse(entry.categoryId).subscribe({
|
|
next: (data) => this.categoryBreadcrumb.set(data.breadcrumb),
|
|
error: () => {},
|
|
});
|
|
}
|
|
},
|
|
error: (err) => {
|
|
this.error.set(err.message ?? 'Erreur lors du chargement');
|
|
this.loading.set(false);
|
|
},
|
|
});
|
|
}
|
|
|
|
private startPollIfPending() {
|
|
this.clearPoll();
|
|
if (this.api()?.status === 'PENDING') {
|
|
this.pollInterval = setInterval(() => this.pollStatus(), 3000);
|
|
}
|
|
}
|
|
|
|
private pollStatus() {
|
|
this.apiService.get(this.id).subscribe({
|
|
next: (entry) => {
|
|
this.api.set(entry);
|
|
if (entry.status !== 'PENDING') this.clearPoll();
|
|
},
|
|
});
|
|
}
|
|
|
|
private clearPoll() {
|
|
if (this.pollInterval) {
|
|
clearInterval(this.pollInterval);
|
|
this.pollInterval = null;
|
|
}
|
|
}
|
|
}
|