abstract out the install button functionality as there is a lot of it and it is used in multiple components

pull/9/head
Chris Veilleux 2018-10-22 21:40:22 -05:00
parent 96dee79905
commit 39244314a9
3 changed files with 292 additions and 0 deletions

View File

@ -0,0 +1,71 @@
<ng-container [ngSwitch]="installStatus">
<!-- Give the user the ability to remove an installed skill -->
<button
*ngSwitchCase="'installed'"
fxLayout="row"
fxLayoutAlign="center center"
mat-flat-button
class="uninstall-button"
(click)="uninstallSkill()"
[ngStyle]="installButtonStyle"
>
<fa-icon [icon]="removeIcon"></fa-icon>
<span>REMOVE</span>
</button>
<!-- System skills cannot be removed so show a lock icon and disable -->
<button
*ngSwitchCase="'system'"
fxLayout="row"
fxLayoutAlign="center center"
mat-flat-button
class="installed-button"
[disabled]="true"
[ngStyle]="installButtonStyle"
>
<fa-icon [icon]="skillLocked"></fa-icon>
<span>ADDED</span>
</button>
<!-- Use the button to indicate to the user that the install is in progress -->
<button
*ngSwitchCase="'installing'"
fxLayout="row"
fxLayoutAlign="center center"
mat-flat-button
class="installing-button"
[ngStyle]="installButtonStyle"
>
<div class="installing-spinner"></div>
ADDING...
</button>
<!-- Use the button to indicate to the user that an uninstall is in progress -->
<button
*ngSwitchCase="'uninstalling'"
fxLayout="row"
fxLayoutAlign="center center"
mat-flat-button
class="uninstalling-button"
[ngStyle]="installButtonStyle"
>
<div class="uninstalling-spinner"></div>
REMOVING...
</button>
<!-- Allow the user to add a skill to their devices -->
<button
*ngSwitchDefault
fxLayout="row"
fxLayoutAlign="center center"
class="install-button"
mat-flat-button
(click)="install_skill()"
[ngStyle]="installButtonStyle"
>
<fa-icon [icon]="addIcon"></fa-icon>
<span>ADD</span>
</button>
</ng-container>

View File

@ -0,0 +1,78 @@
@import '../../../../stylesheets/global.scss';
@mixin install-status {
border-radius: 4px;
letter-spacing: 0.5px;
}
// The angular material spinner was limiting in color choices we built our own
@mixin spinner-common {
animation: spin 1s ease-in-out infinite;
border: 2px solid rgba(255,255,255,.3);
border-radius: 50%;
display: inline-block;
height: 15px;
margin-right: 10px;
width: 15px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
fa-icon {
margin-right: 10px;
}
.install-button {
@include install-status;
color: $mycroft-white;
}
.install-button:hover {
@include install-status;
background-color: $mycroft-tertiary-green;
color: $mycroft-secondary;
}
.installed-button {
@include install-status;
}
.installing-button {
@include install-status;
background-color: $mycroft-tertiary-green;
color: $mycroft-secondary;
mat-spinner {
float: left;
margin-right: 10px;
margin-top: 7px;
}
}
.installing-spinner {
@include spinner-common;
border-right-color: $mycroft-secondary;
border-top-color: $mycroft-secondary;
}
.uninstall-button {
@include install-status;
background-color: $mycroft-dark-grey;
color: $mycroft-white;
}
.uninstall-button:hover {
@include install-status;
border: none;
background-color: #eb5757;
color: $mycroft-white;
}
.uninstalling-button {
@include install-status;
background-color: #eb5757;
color: $mycroft-white;
}
.uninstalling-spinner {
@include spinner-common;
border-right-color: $mycroft-white;
border-top-color: $mycroft-white;
}

View File

@ -0,0 +1,143 @@
/**
* This component does all things install button, which is a lot of things.
*/
import { Component, Input, OnInit } from '@angular/core';
import { AvailableSkill } from "../../skills.service";
import { InstallService } from "../../install.service";
import { faPlusCircle } from "@fortawesome/free-solid-svg-icons/faPlusCircle";
import { faTrash } from "@fortawesome/free-solid-svg-icons/faTrash";
import { faLock } from "@fortawesome/free-solid-svg-icons/faLock";
import { MatSnackBar } from "@angular/material";
const fiveSeconds = 5000;
const twentySeconds = 20000;
@Component({
selector: 'skill-install-button',
templateUrl: './install-button.component.html',
styleUrls: ['./install-button.component.scss']
})
export class InstallButtonComponent implements OnInit {
public addIcon = faPlusCircle;
@Input() private component: string;
public installButtonStyle: object;
public installStatus: string;
public removeIcon = faTrash;
@Input() public skill: AvailableSkill;
public skillLocked = faLock;
constructor(private installSnackbar: MatSnackBar, private installService: InstallService) { }
ngOnInit() {
this.installService.installStatuses.subscribe(
(installStatuses) => {
this.installStatus = this.installService.getSkillInstallStatus(
this.skill,
installStatuses
)
}
);
this.applyInstallButtonStyle();
}
/**
* Some of the install button style elements are different depending on
* which component it is displayed within. Use the ngStyle directive
* to specify these styles.
*/
applyInstallButtonStyle() {
if (this.component === 'skillDetail') {
this.installButtonStyle = {'width': '140px'}
} else if (this.component === 'skillSummary') {
this.installButtonStyle = {'width': '320px', 'margin-bottom': '15px'}
}
}
/**
* Install a skill onto one or many devices
*/
install_skill() : void {
this.installService.installSkill(this.skill).subscribe(
(response) => {
this.onInstallSuccess(response)
},
(response) => {
this.onInstallFailure(response)
}
);
}
/**
* Handle the successful install request
*
* This does not indicate that the install of the skill completed, only
* that the request to install a skill succeeded. Change the install
* button to an "installing" state.
*
* @param response
*/
onInstallSuccess(response) : void {
this.installService.newInstallStatuses[this.skill.name] = 'installing';
this.installService.applyInstallStatusChanges();
this.installSnackbar.open(
'The ' + this.skill.title + ' skill is being added ' +
'to your devices. Please allow up to two minutes for ' +
'installation to complete before using the skill.',
null,
{panelClass: 'mycroft-snackbar', duration: twentySeconds}
);
}
/**
* Handle the failure to install a skill.
*
* If a user attempts to install a skill without being logged in, show a
* snackbar to notify the user and give them the ability to log in.
*
* @param response - object representing the response from the API call
*/
onInstallFailure(response) : void {
if (response.status === 401) {
this.installSnackbar.open(
'To install a skill, log in to your account.',
'LOG IN',
{panelClass: 'mycroft-snackbar', duration: fiveSeconds}
);
}
}
/**
* Remove a skill from one or many devices
*/
uninstallSkill() : void {
this.installService.uninstallSkill(this.skill).subscribe(
(response) => {
this.onUninstallSuccess(response)
},
);
}
/**
* Handle the successful install request
*
* This does not indicate that the install of the skill completed, only
* that the request to install a skill succeeded. Change the install
* button to an "installing" state.
*
* @param response
*/
onUninstallSuccess(response) : void {
this.installService.newInstallStatuses[this.skill.name] = 'uninstalling';
this.installService.applyInstallStatusChanges();
this.installSnackbar.open(
'The ' + this.skill.title + ' skill is ' +
'uninstalling. Please allow up to a minute for the skill to be ' +
'removed from devices.',
null,
{panelClass: 'mycroft-snackbar', duration: twentySeconds}
);
}
}