added snackbar for a failed install due to authorization and a mycroft logo for skills developed in-house.

pull/1/head
Chris Veilleux 2018-08-17 13:58:03 -05:00
parent eb7b75e9ba
commit fceb5b5682
15 changed files with 143 additions and 58 deletions

View File

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { LoginService } from './login/login.service';
import { LoginService } from './header/login/login.service';
@Injectable()
export class AuthGuard implements CanActivate {

View File

@ -8,6 +8,7 @@ import { MatMenuModule } from "@angular/material";
import { MatSelectModule } from "@angular/material/select";
import { MatSnackBarModule } from "@angular/material/snack-bar";
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from "@angular/material/tooltip";
@NgModule(
{
@ -21,6 +22,7 @@ import { MatToolbarModule } from '@angular/material/toolbar';
MatSelectModule,
MatSnackBarModule,
MatToolbarModule,
MatTooltipModule
],
exports: [
MatButtonModule,
@ -32,6 +34,7 @@ import { MatToolbarModule } from '@angular/material/toolbar';
MatSelectModule,
MatSnackBarModule,
MatToolbarModule,
MatTooltipModule
]
}
)

View File

@ -1,13 +0,0 @@
import { SharedModule } from './shared.module';
describe('SharedModule', () => {
let sharedModule: SharedModule;
beforeEach(() => {
sharedModule = new SharedModule();
});
it('should create an instance', () => {
expect(sharedModule).toBeTruthy();
});
});

View File

@ -1,12 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LoginService } from "./login.service";
import { MaterialModule } from "./material.module";
@NgModule({
imports: [ CommonModule ],
exports: [ MaterialModule ],
providers: [ LoginService ]
})
export class SharedModule { }

View File

@ -0,0 +1,8 @@
<mat-card-header>
<div class="mycroft-icon">
<img src="../../../../assets/mycroft-logo.svg" *ngIf="isMycroftMade" matTooltip="Mycroft Made">
</div>
<div class="skill-icon">
<fa-icon [icon]="skillIcon"></fa-icon>
</div>
</mat-card-header>

View File

@ -0,0 +1,22 @@
@import '../../../../stylesheets/global.scss';
mat-card-header {
justify-content: center;
margin-bottom: 15px;
.mycroft-icon {
left: 15px;
position: absolute;
top: 15px;
img {
height: 20px;
width: 20px;
}
}
.skill-icon {
position: relative;
fa-icon {
color: $mycroft-tertiary-green;
font-size: 28px;
}
}
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SkillCardHeaderComponent } from './skill-card-header.component';
describe('SkillCardHeaderComponent', () => {
let component: SkillCardHeaderComponent;
let fixture: ComponentFixture<SkillCardHeaderComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SkillCardHeaderComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SkillCardHeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,21 @@
import { Component, Input, OnInit } from '@angular/core';
import { Skill } from "../../skills.service";
import { faMicrophoneAlt } from "@fortawesome/free-solid-svg-icons";
@Component({
selector: 'market-skill-card-header',
templateUrl: './skill-card-header.component.html',
styleUrls: ['./skill-card-header.component.scss']
})
export class SkillCardHeaderComponent implements OnInit {
public skillIcon = faMicrophoneAlt;
@Input() public skill: Skill;
public isMycroftMade: boolean;
constructor() { }
ngOnInit() {
this.isMycroftMade = this.skill.author.toLowerCase().includes('mycroft')
}
}

View File

@ -1,9 +1,7 @@
<div fxLayout="row wrap">
<mat-card *ngFor="let skill of skills" align="center">
<mat-card *ngFor="let skill of skills; let i = index" align="center">
<div [routerLink]="['/skill', skill.id]">
<mat-card-header align="center">
<fa-icon [icon]="skillIcon"></fa-icon>
</mat-card-header>
<market-skill-card-header [skill]="skills[i]"></market-skill-card-header>
<mat-card-title>{{skill.title}}</mat-card-title>
<mat-card-subtitle align="center">
<button mat-flat-button [disabled]="true">

View File

@ -9,14 +9,6 @@ mat-card {
border-radius: 10px;
margin: 15px;
padding: 15px;
mat-card-header {
justify-content: center;
margin-bottom: 15px;
fa-icon {
color: $mycroft-tertiary-green;
font-size: 28px;
}
}
mat-card-title {
@include ellipsis-overflow;
color: $mycroft-secondary;

View File

@ -1,34 +1,46 @@
import { Component, Input, OnInit } from '@angular/core';
import { MatSnackBar } from "@angular/material";
import { faComment, faMicrophoneAlt } from '@fortawesome/free-solid-svg-icons';
import { SkillsService } from "../skills.service";
import { faComment } from '@fortawesome/free-solid-svg-icons';
import { SkillsService, Skill } from "../skills.service";
@Component({
selector: 'market-skill-summary',
templateUrl: './skill-summary.component.html',
styleUrls: ['./skill-summary.component.scss']
selector: 'market-skill-summary',
templateUrl: './skill-summary.component.html',
styleUrls: ['./skill-summary.component.scss'],
})
export class SkillSummaryComponent implements OnInit {
public skillIcon = faMicrophoneAlt;
@Input() public skills;
@Input() public skills: Skill[];
public voiceIcon = faComment;
constructor(private skillsService: SkillsService) { }
constructor(public loginSnackbar: MatSnackBar, private skillsService: SkillsService) { }
ngOnInit() { }
install_skill(skill) {
this.skillsService.installSkill().subscribe(
(response) => {this.onInstallSuccess(response)},
(response) => {this.onInstallFailure(response)}
install_skill(skill: Skill) : void {
this.skillsService.installSkill(skill).subscribe(
(response) => {
this.onInstallSuccess(response)
},
(response) => {
this.onInstallFailure(response)
}
);
}
onInstallSuccess(response) {
onInstallSuccess(response) : void {
console.log('success!')
}
onInstallFailure(response) {
window.location.assign('http://login.mycroft.test');
onInstallFailure(response) : void {
if (response.status === 401) {
this.loginSnackbar.open(
'To install a skill, log in to your account.',
'LOG IN',
{panelClass: 'mycroft-snackbar', duration: 5000}
);
}
}
}

View File

@ -12,6 +12,7 @@ import { SkillsRoutingModule } from "./skills-routing.module";
import { SkillToolbarComponent } from "./skill-toolbar/skill-toolbar.component";
import { SkillsService } from "./skills.service";
import { SkillSummaryComponent } from "./skill-summary/skill-summary.component";
import { SkillCardHeaderComponent } from './skill-summary/skill-card-header/skill-card-header.component';
@NgModule(
{
@ -27,7 +28,8 @@ import { SkillSummaryComponent } from "./skill-summary/skill-summary.component";
SkillDetailComponent,
SkillsComponent,
SkillToolbarComponent,
SkillSummaryComponent
SkillSummaryComponent,
SkillCardHeaderComponent
],
exports: [ SkillsComponent, SkillDetailComponent ],
entryComponents: [ SkillDetailComponent ],

View File

@ -1,10 +1,11 @@
import { HttpClient } from '@angular/common/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
export class Skill {
id: number;
author: string;
category: string;
skill_name: string;
title: string;
@ -12,11 +13,12 @@ export class Skill {
description: string;
repository_url: string;
triggers: string;
isMycroft: boolean = true;
}
@Injectable()
export class SkillsService {
private installUrl = '/api/install';
private installUrl = '/api/install-skill';
private skillUrl = '/api/skill/';
private skillsUrl = '/api/skills';
private searchQuery = '?search=';
@ -35,7 +37,11 @@ export class SkillsService {
return this.http.get<Skill[]>(this.skillsUrl + this.searchQuery + searchTerm)
}
installSkill(): Observable<Object> {
return this.http.get<Object>(this.installUrl)
installSkill(skill: Skill): Observable<Object> {
return this.http.put<Object>(
this.installUrl,
{skill_url: skill.repository_url}
)
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1800 1800" enable-background="new 0 0 1800 1800" xml:space="preserve">
<g>
<path fill="#22A7F0" d="M493.3,195.6C305.9,303.8,120.6,450,120.6,450v0h0c0,0-33.9,233.6-33.9,450c0,216.4,33.9,450,33.9,450
s185.3,146.2,372.7,254.4C680.8,1712.6,900,1800,900,1800l0,0c0.1,0,219.3-87.4,406.7-195.6c187.4-108.2,372.7-254.4,372.7-254.4
s33.9-233.6,33.9-450c0-216.4-33.9-450-33.9-450s-185.3-146.2-372.7-254.4C1119.2,87.4,900,0,900,0S680.8,87.4,493.3,195.6z"/>
<path fill="#FFFFFF" d="M900,530c204,0,370,166,370,370s-166,370-370,370s-370-166-370-370S696,530,900,530 M900,462.8
c-241.5,0-437.2,195.8-437.2,437.2s195.8,437.2,437.2,437.2s437.2-195.8,437.2-437.2S1141.5,462.8,900,462.8L900,462.8z"/>
<path fill="#FFFFFF" d="M900,595.8C732,595.8,595.8,732,595.8,900S732,1204.2,900,1204.2V595.8z"/>
<circle fill="#FFFFFF" cx="900" cy="272.5" r="77.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -85,4 +85,11 @@ $mycroft-theme: mat-light-theme($mycroft-palette-primary, $mycroft-palette-accen
body {
background-color: #f1f1f1;
}
.mycroft-snackbar {
width: 500px;
}
.mycroft-snackbar .mat-simple-snackbar-action {
color: #22a7f0
}