new service for all skill add/remove logic

pull/9/head
Chris Veilleux 2018-10-22 21:44:21 -05:00
parent 8f55e4e2c2
commit a160c5331a
1 changed files with 140 additions and 0 deletions

View File

@ -0,0 +1,140 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, Subject } from "rxjs";
import { AvailableSkill, SkillDetail } from "./skills.service";
type InstallStatus = 'failed' | 'installed' | 'installing' | 'uninstalling';
export interface SkillInstallStatus {
[key: string]: InstallStatus;
}
export interface FailureReason {
[key: string]: string;
}
export interface Installations {
failureReasons: FailureReason;
installStatuses: SkillInstallStatus;
}
// const inProgressStatuses = ['installing', 'uninstalling', 'failed'];
const inProgressStatuses = ['installing', 'uninstalling'];
const installStatusUrl = '/api/skill/installations';
const installUrl = '/api/skill/install';
const uninstallUrl = '/api/skill/uninstall';
@Injectable({
providedIn: 'root'
})
export class InstallService {
public failureReasons: FailureReason;
public installStatuses = new Subject<SkillInstallStatus>();
public newInstallStatuses: SkillInstallStatus;
private prevInstallStatuses: SkillInstallStatus;
public statusNotifications = new Subject<SkillInstallStatus>();
constructor(private http: HttpClient) { }
getSkillInstallations() {
this.http.get<Installations>(installStatusUrl).subscribe(
(installations) => {
this.newInstallStatuses = installations.installStatuses;
this.failureReasons = installations.failureReasons;
this.applyInstallStatusChanges();
this.checkInstallationsInProgress();
}
)
}
applyInstallStatusChanges() {
if (this.prevInstallStatuses) {
Object.keys(this.newInstallStatuses).forEach(
() => this.compareStatuses
);
}
this.prevInstallStatuses = this.newInstallStatuses;
this.installStatuses.next(this.newInstallStatuses);
}
compareStatuses(skillName: string) {
let prevSkillStatus = this.prevInstallStatuses[skillName];
let newSkillStatus = this.newInstallStatuses[skillName];
let statusNotifications: SkillInstallStatus = {};
switch (prevSkillStatus) {
case ('installing'): {
if (['installed', 'failed'].includes(newSkillStatus)) {
statusNotifications[skillName] = newSkillStatus;
} else {
this.newInstallStatuses[skillName] = prevSkillStatus;
}
break;
}
case ('uninstalling'): {
if (!newSkillStatus || newSkillStatus === 'failed') {
statusNotifications[skillName] = newSkillStatus;
} else {
this.newInstallStatuses[skillName] = prevSkillStatus;
}
break;
}
case ('failed'): {
if (!newSkillStatus || newSkillStatus != 'installed') {
statusNotifications[skillName] = newSkillStatus;
} else {
this.newInstallStatuses[skillName] = prevSkillStatus;
}
break;
}
}
if (statusNotifications) {
this.statusNotifications.next(statusNotifications)
}
}
getSkillInstallStatus(
skill: AvailableSkill | SkillDetail,
installStatuses: SkillInstallStatus
) {
let installStatus: string;
if (skill.isSystemSkill) {
installStatus = 'system';
} else {
installStatus = installStatuses[skill.name];
}
return installStatus;
}
/** Poll at an interval to check the status of install/uninstall requests
*
* We want to avoid polling if we don't need it. Only poll if waiting for
* the result of a requested install/uninstall.
*/
checkInstallationsInProgress() {
let inProgress = Object.values(this.installStatuses).filter(
(installStatus) => inProgressStatuses.includes(installStatus)
);
if (inProgress.length > 0) {
setTimeout(() => {this.getSkillInstallations();}, 10000);
}
}
installSkill(skill: AvailableSkill): Observable<Object> {
return this.http.put<Object>(
installUrl,
{skill_name: skill.name}
)
}
uninstallSkill(skill: AvailableSkill): Observable<Object> {
return this.http.put<Object>(
uninstallUrl,
{skill_name: skill.name}
)
}
}