added snackbar for a failed install due to authorization and a mycroft logo for skills developed in-house.
parent
eb7b75e9ba
commit
fceb5b5682
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
]
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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 { }
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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')
|
||||
}
|
||||
|
||||
}
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ],
|
||||
|
|
|
@ -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}
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 |
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue