Merge branch 'develop' of https://github.com/ombi-app/Ombi into develop

pull/4143/head
tidusjar 4 years ago
commit 8a9230730c

@ -3,7 +3,7 @@
<div id="result{{result.id}}" *ngIf="fullyLoaded" class="ombi-card dark-card c" [style.display]="hide ? 'none' : 'block'"> <div id="result{{result.id}}" *ngIf="fullyLoaded" class="ombi-card dark-card c" [style.display]="hide ? 'none' : 'block'">
<div class="card-top-info"> <div class="card-top-info">
<div class="top-left" id="type{{result.id}}"> <div class="top-left" id="type{{result.id}}">
{{RequestType[result.type] | humanize}} {{ 'Common.' + RequestType[result.type] | translate }}
</div> </div>
<div class="{{getStatusClass()}} top-right" id="status{{result.id}}"> <div class="{{getStatusClass()}} top-right" id="status{{result.id}}">
<span class="indicator"></span><span class="indicator-text" id="availabilityStatus{{result.id}}">{{getAvailbilityStatus()}}</span> <span class="indicator"></span><span class="indicator-text" id="availabilityStatus{{result.id}}">{{getAvailbilityStatus()}}</span>
@ -21,9 +21,10 @@
</div> </div>
<div class="row button-request-container" *ngIf="!result.available && !result.approved && !result.requested"> <div class="row button-request-container" *ngIf="!result.available && !result.approved && !result.requested">
<div class="button-request poster-overlay"> <div class="button-request poster-overlay">
<button id="requestButton{{result.id}}{{result.type}}{{discoverType}}" mat-raised-button class="btn-green full-width poster-request-btn" (click)="request($event)"> <button id="requestButton{{result.id}}{{result.type}}{{discoverType}}" *ngIf="requestable" mat-raised-button class="btn-ombi full-width poster-request-btn" (click)="request($event)">
<i *ngIf="!loading" class="fa-lg fas fa-cloud-download-alt"></i> <i *ngIf="!loading" class="fa-lg fas fa-cloud-download-alt"></i>
<i *ngIf="loading" class="fas fa-spinner fa-pulse fa-2x fa-fw" aria-hidden="true"></i> <i *ngIf="loading" class="fas fa-spinner fa-pulse fa-2x fa-fw" aria-hidden="true"></i>
{{'Common.Request' | translate }}
</button> </button>
</div> </div>
</div> </div>

@ -1,5 +1,4 @@
$ombi-primary:#3f3f3f; @import "~styles/variables.scss";
$card-background: #2b2b2b;
#cardImage { #cardImage {
border-radius: 5px; border-radius: 5px;
@ -141,19 +140,20 @@ small {
.card-top-info{ .card-top-info{
position: absolute; position: absolute;
text-transform: uppercase;
top: 0px; top: 0px;
width: 100%; width: 100%;
background-color: rgba(15,23,31,0.6); background-color: rgba(15,23,31,0.7);
display:flex; display:flex;
justify-content: space-between; justify-content: space-between;
padding-top:0.6em; padding-top:0.6em;
padding-bottom:0.3em; padding-bottom:0.3em;
z-index:2; z-index:2;
letter-spacing: 0.2px;
} }
.top-left { .top-left {
font-size: 14px; font-size: 14px;
font-weight:200;
padding-left: 0.5em; padding-left: 0.5em;
font-size: 14px; font-size: 14px;
} }
@ -161,6 +161,7 @@ small {
/* common */ /* common */
.top-right{ .top-right{
display:flex; display:flex;
font-weight:200;
} }
.top-right span.indicator, span.indicator-text { .top-right span.indicator, span.indicator-text {
@ -247,7 +248,7 @@ a.poster-overlay:hover{
width: 100%; width: 100%;
margin-left: 0; margin-left: 0;
margin-right: 0; margin-right: 0;
margin-top: -37px; margin-top: -36px;
margin-bottom: 0px; margin-bottom: 0px;
opacity:0; opacity:0;
transition: .5s ease; transition: .5s ease;
@ -261,4 +262,8 @@ a.poster-overlay:hover{
.c:hover .button-request-container { .c:hover .button-request-container {
opacity:1; opacity:1;
}
.btn-ombi{
background-color:#293a4c;
} }

@ -24,6 +24,8 @@ export class DiscoverCardComponent implements OnInit {
public fullyLoaded = false; public fullyLoaded = false;
public loading: boolean; public loading: boolean;
public requestable: boolean;
// This data is needed to open the dialog // This data is needed to open the dialog
private tvSearchResult: ISearchTvResultV2; private tvSearchResult: ISearchTvResultV2;
@ -44,19 +46,10 @@ export class DiscoverCardComponent implements OnInit {
} }
public async getExtraTvInfo() { public async getExtraTvInfo() {
// if (this.result.tvMovieDb) { this.tvSearchResult = await this.searchService.getTvInfoWithMovieDbId(+this.result.id);
this.tvSearchResult = await this.searchService.getTvInfoWithMovieDbId(+this.result.id); this.requestable = true;
// } else {
// this.tvSearchResult = await this.searchService.getTvInfo(+this.result.id);
// }
// if (!this.tvSearchResult || this.tvSearchResult?.status.length > 0 && this.tvSearchResult?.status === "404") {
// this.hide = true;
// return;
// }
this.setTvDefaults(this.tvSearchResult); this.setTvDefaults(this.tvSearchResult);
this.updateTvItem(this.tvSearchResult); this.updateTvItem(this.tvSearchResult);
} }
public async getAlbumInformation() { public async getAlbumInformation() {
@ -69,12 +62,13 @@ export class DiscoverCardComponent implements OnInit {
if (art.image) { if (art.image) {
this.result.posterPath = art.image; this.result.posterPath = art.image;
this.fullyLoaded = true;
} }
}) })
} }
this.result.title = x.startYear ? `${x.name} (${x.startYear})` : x.name; this.result.title = x.startYear ? `${x.name} (${x.startYear})` : x.name;
this.result.overview = x.overview; this.result.overview = x.overview;
this.fullyLoaded = true;
this.requestable = true;
}); });
} }
@ -166,6 +160,7 @@ export class DiscoverCardComponent implements OnInit {
} else { } else {
this.fullyLoaded = true; this.fullyLoaded = true;
} }
this.requestable = true;
} }
private updateMovieItem(updated: ISearchMovieResultV2) { private updateMovieItem(updated: ISearchMovieResultV2) {

@ -71,7 +71,7 @@
.discover-filter-buttons-group { .discover-filter-buttons-group {
background: $ombi-background-primary; background: $ombi-background-primary;
border: 1px solid $ombi-background-primary-accent; border: 1px solid #293a4c;
border-radius: 30px; border-radius: 30px;
color:#fff; color:#fff;
margin-bottom:10px; margin-bottom:10px;
@ -84,6 +84,7 @@
border-radius: 30px; border-radius: 30px;
padding-left: 20px; padding-left: 20px;
padding-right: 20px; padding-right: 20px;
border-left:none;
} }
::ng-deep .mat-button-toggle-appearance-standard .mat-button-toggle-label-content{ ::ng-deep .mat-button-toggle-appearance-standard .mat-button-toggle-label-content{
@ -91,7 +92,7 @@
} }
.button-active{ .button-active{
background:$ombi-active; background:#293a4c;
} }

@ -221,7 +221,7 @@
.social-icons-container{ .social-icons-container{
position:absolute; position:absolute;
top:84px; top:0px;
right:0px; right:0px;
width:100%; width:100%;
background-color:rgba(15,23,31,.6); background-color:rgba(15,23,31,.6);
@ -329,6 +329,10 @@
margin-left:10px; margin-left:10px;
} }
.dark-theme{
position:relative;
}
@media (max-width:500px){ @media (max-width:500px){
.row.justify-content-center.justify-content-sm-start.header-container{ .row.justify-content-center.justify-content-sm-start.header-container{
flex-wrap:wrap; flex-wrap:wrap;

@ -53,36 +53,33 @@
<i class="fa-lg fas fa-bars"></i> <i class="fa-lg fas fa-bars"></i>
</button> </button>
<div class="col-8 col-lg-10 top-search-bar"> <div class="top-search-block">
<span class="justify-content-center align-items-center">
<!-- Search Bar --> <!-- Search Bar -->
<div> <div class="top-search-bar">
<app-nav-search></app-nav-search> <app-nav-search></app-nav-search>
</div> </div>
</span> <button id="search-filter" mat-icon-button [matMenuTriggerFor]="filterMenu">
<i class="fa-lg fas fa-filter"></i>
</button>
<mat-menu #filterMenu="matMenu" yPosition="below" class="smaller-panel">
<mat-slide-toggle id="filterMovies" class="mat-menu-item slide-menu" [checked]="searchFilter.movies"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Movie)">
{{ 'NavigationBar.Filter.Movies' | translate}}</mat-slide-toggle>
<mat-slide-toggle id="filterTv" class="mat-menu-item slide-menu" [checked]="searchFilter.tvShows"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.TvShow)">
{{ 'NavigationBar.Filter.TvShows' | translate}}</mat-slide-toggle>
<mat-slide-toggle id="filterMusic" class="mat-menu-item slide-menu" [checked]="searchFilter.music"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Music)">
{{ 'NavigationBar.Filter.Music' | translate}}</mat-slide-toggle>
<!-- <mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.people"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.People)">
{{ 'NavigationBar.Filter.People' | translate}}</mat-slide-toggle> -->
</mat-menu>
</div> </div>
<div class="col-1 top-filter"> <div class="profile-block">
<button id="search-filter" mat-icon-button [matMenuTriggerFor]="filterMenu">
<i class="fa-lg fas fa-filter"></i>
</button>
<mat-menu #filterMenu="matMenu" yPosition="below" class="smaller-panel">
<mat-slide-toggle id="filterMovies" class="mat-menu-item slide-menu" [checked]="searchFilter.movies"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Movie)">
{{ 'NavigationBar.Filter.Movies' | translate}}</mat-slide-toggle>
<mat-slide-toggle id="filterTv" class="mat-menu-item slide-menu" [checked]="searchFilter.tvShows"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.TvShow)">
{{ 'NavigationBar.Filter.TvShows' | translate}}</mat-slide-toggle>
<mat-slide-toggle id="filterMusic" class="mat-menu-item slide-menu" [checked]="searchFilter.music"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Music)">
{{ 'NavigationBar.Filter.Music' | translate}}</mat-slide-toggle>
<!-- <mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.people"
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.People)">
{{ 'NavigationBar.Filter.People' | translate}}</mat-slide-toggle> -->
</mat-menu>
</div>
<div class="col-1">
<a routerLink="/user-preferences"> <a routerLink="/user-preferences">
<img [matTooltip]="username" id="profile-image" class="profile-img" [src]="getUserImage()" /> <div class="profile-username" data-test="profile-username">{{username}}</div>
<div class="profile-img" data-test="profile-image"><img [src]="getUserImage()" /></div>
</a> </a>
</div> </div>

@ -24,7 +24,8 @@
} }
.icon-spacing { .icon-spacing {
margin-right: 5%; width:40px;
text-align: center;
} }
.example-form { .example-form {
@ -48,12 +49,6 @@
padding: 0px 5px; padding: 0px 5px;
} }
::ng-deep .dark .active-list-item {
background: $accent-dark !important;
color:black !important;
font-weight:500;
}
.slide-menu { .slide-menu {
width: 100%; width: 100%;
} }
@ -62,6 +57,27 @@
max-width: 170px !important; max-width: 170px !important;
} }
.top-bar-container{
width: 95%;
display: flex;
justify-content: center;
align-items: center;
margin: auto;
}
.top-search-block{
height:84px;
display:flex;
justify-content: center;
align-items: center;
flex:1;
margin-right:5%;
}
.top-search-bar{
width:100%;
}
.mat-drawer-content { .mat-drawer-content {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@ -71,36 +87,34 @@
/* overflow: auto; */ /* overflow: auto; */
} }
.profile-img-container { .profile-block a{
margin: 20px auto 10px; color: #FFF;
overflow: hidden; font-size: 0.8em;
text-align: center; font-weight: 100;
width: 80%; display:flex;
justify-content: flex-end;
align-items: flex-end;
text-transform: capitalize;
flex:0 0 250px;
} }
.profile-img {
float: left; .profile-username{
width: 45px; justify-content: center;
border-radius: 100%; display:flex;
} height:50px;
.profile-info { align-items: center;
overflow: hidden; margin-right:5px;
text-align: left;
}
.profile-info > h3 {
font-size: 15px;
text-transform: capitalize;
// color: #333;
margin-bottom: 2px;
} }
.profile-info > p {
// color: #333; @media (max-width: 600px) {
font-size: 11px; .profile-username{
margin-top: 5px; display:none;
}
} }
.profile-img img { .profile-img img {
width: 45px; width: 50px;
} }
@ -125,7 +139,6 @@
text-transform: uppercase; text-transform: uppercase;
color: $ombi-active; color: $ombi-active;
align-items:center; align-items:center;
justify-content: center;
font-weight: 700; font-weight: 700;
font-size:36px; font-size:36px;
padding:40px 20px; padding:40px 20px;
@ -133,7 +146,6 @@
max-width: 350px; max-width: 350px;
display: flex; display: flex;
white-space: normal; white-space: normal;
text-align: center;
} }
.outer-profile { .outer-profile {
@ -173,18 +185,11 @@
.top-bar-container{ .top-bar-container{
background: $ombi-background-primary; background: $ombi-background-primary;
color:$ombi-background-primary-accent; color:$ombi-background-primary-accent;
padding-top:1em;
} }
} }
.top-search-bar{
margin-left: 30px;
}
::ng-deep .mat-toolbar-row, .mat-toolbar-single-row{ ::ng-deep .mat-toolbar-row, .mat-toolbar-single-row{
height:auto; height:auto;
}
.top-search-bar{
height:84px;
} }

@ -39,7 +39,6 @@ $ombi-accent: #258a6d;
::ng-deep .top-search-bar .mat-form-field-flex{ ::ng-deep .top-search-bar .mat-form-field-flex{
border: 1px solid #35465c; border: 1px solid #35465c;
border-radius:30px; border-radius:30px;
margin-top:20px;
height:50px; height:50px;
} }

@ -1,30 +1,26 @@
<div class="small-middle-container" *ngIf="username"> <div class="small-middle-container" *ngIf="username">
<div class="row h-100"> <div class="d-flex">
<div class="col-1"> <img class="profile-img" [src]="getProfileImage()">
<img class="profile-img" [src]="getProfileImage()"> <h2 id="usernameTitle">{{username}}
</div> <small id="emailTitle" *ngIf="user.emailAddress">({{user.emailAddress}})</small>
<div class="col-11 align-middle"> </h2>
<h2 id="usernameTitle">{{username}} <small id="emailTitle" *ngIf="user.emailAddress">({{user.emailAddress}})</small></h2>
</div>
</div> </div>
<mat-tab-group> <mat-tab-group>
<mat-tab label="Profile"> <mat-tab label="Profile">
<div class="tab-content"> <div class="tab-content">
<div class="row"> <div class="row user-type-row">
<div class="col-1"> <div class="col-5 col-sm-3 col-md-2">
User Type: User Type:
</div> </div>
<div class="col-11"> <div class="col-7 col-sm-9 col-md-10">
{{UserType[user.userType]}} {{UserType[user.userType]}}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-12 col-sm-6 col-xl-5">
<div> <div>
<small>{{'UserPreferences.LanguageDescription' | translate}}</small> <small>{{'UserPreferences.LanguageDescription' | translate}}</small>
<br> <br>
@ -38,14 +34,9 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div>
</div>
</div> </div>
<div class="col-1"></div>
<div class="col-12 col-sm-6 col-xl-5">
<div class="col-4">
<div> <div>
<small>{{'UserPreferences.StreamingCountryDescription' | translate}}</small> <small>{{'UserPreferences.StreamingCountryDescription' | translate}}</small>
<br> <br>
@ -58,13 +49,8 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div>
</div>
</div> </div>
</div> </div>
</div> </div>
</mat-tab> </mat-tab>

@ -5,9 +5,22 @@
} }
.profile-img { .profile-img {
border-radius: 100%;
width: 75px; width: 75px;
height: 75px;
margin-right: 20px;
border-radius: 100%;
}
#usernameTitle {
margin: 0;
align-self: center;
overflow-wrap: anywhere;
} }
.user-type-row {
padding-bottom: 1.25em;
}
.my-auto { .my-auto {
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
@ -19,5 +32,5 @@
} }
.tab-content { .tab-content {
margin-top: 1%; margin-top: 1.5em;
} }

@ -31,7 +31,9 @@
"Validation": "Please check your entered values" "Validation": "Please check your entered values"
}, },
"Cancel": "Cancel", "Cancel": "Cancel",
"Submit": "Submit" "Submit": "Submit",
"tvShow": "TV Show",
"movie": "Movie"
}, },
"PasswordReset": { "PasswordReset": {
"EmailAddressPlaceholder": "Email Address", "EmailAddressPlaceholder": "Email Address",

@ -69,7 +69,11 @@ class NavBar {
} }
get userPreferences(): Cypress.Chainable<any> { get userPreferences(): Cypress.Chainable<any> {
return cy.get('#profile-image'); return cy.getByData('profile-image');
}
get username(): Cypress.Chainable<any> {
return cy.getByData('profile-username');
} }
get logout(): Cypress.Chainable<any> { get logout(): Cypress.Chainable<any> {

@ -0,0 +1,85 @@
describe("TV Request V1 API tests", () => {
beforeEach(() => {
cy.login();
});
it("Request All of TV Show (Fear the Walking Dead)", () => {
const request = {
TvDbId: 290853,
RequestAll: true,
};
cy.api({
url: "/api/v1/request/tv",
body: JSON.stringify(request),
method: "POST",
headers: {
Authorization: "Bearer " + window.localStorage.getItem("id_token"),
"Content-Type": "application/json",
},
}).then((res) => {
expect(res.status).equal(200);
const body = res.body;
expect(body.result).to.be.true;
expect(body.requestId).not.to.be.null;
expect(body.isError).to.be.false;
expect(body.errorMessage).to.be.null;
});
});
it("Request First Season of TV Show (American Horror Story)", () => {
const request = {
TvDbId: 250487,
FirstSeason: true,
};
cy.api({
url: "/api/v1/request/tv",
body: JSON.stringify(request),
method: "POST",
headers: {
Authorization: "Bearer " + window.localStorage.getItem("id_token"),
"Content-Type": "application/json",
},
}).then((res) => {
expect(res.status).equal(200);
const body = res.body;
expect(body.result).to.be.true;
expect(body.requestId).not.to.be.null;
expect(body.isError).to.be.false;
expect(body.errorMessage).to.be.null;
});
});
it("Request Two Episode of First Season TV Show (The Sopranos)", () => {
const request = {
TvDbId: 75299,
Seasons: [
{
SeasonNumber: 1,
Episodes: [
{ EpisodeNumber: 1 },
{ EpisodeNumber: 2 },
],
},
],
};
cy.api({
url: "/api/v1/request/tv",
body: JSON.stringify(request),
method: "POST",
headers: {
Authorization: "Bearer " + window.localStorage.getItem("id_token"),
"Content-Type": "application/json",
},
}).then((res) => {
expect(res.status).equal(200);
const body = res.body;
expect(body.result).to.be.true;
expect(body.requestId).not.to.be.null;
expect(body.isError).to.be.false;
expect(body.errorMessage).to.be.null;
});
});
});

@ -197,7 +197,7 @@ describe("Discover Cards Requests Tests", () => {
}); });
}); });
it.only("Available TV does not allow us to request", () => { it("Available TV does not allow us to request", () => {
cy.intercept("GET", "**/search/Tv/popular/**", (req) => { cy.intercept("GET", "**/search/Tv/popular/**", (req) => {
req.reply((res) => { req.reply((res) => {
const body = res.body; const body = res.body;

@ -0,0 +1,29 @@
import { discoverPage as Page } from "@/integration/page-objects";
import { DiscoverType } from "@/integration/page-objects/shared/DiscoverCard";
const mobiles = ['samsung-s10', 'iphone-x', 'iphone-xr', 'iphone-8']
describe("Discover Responsive Tests", () => {
beforeEach(() => {
cy.login();
});
mobiles.forEach((size: any) => {
// make assertions on the logo using
// an array of different viewports
it(`Should display card on ${size} screen`, () => {
window.localStorage.setItem("DiscoverOptions2", "2");
cy.intercept("GET", "**/search/Movie/Popular/**").as("moviePopular");
cy.viewport(size);
Page.visit();
cy.wait("@moviePopular").then((intecept) => {
const id = intecept.response.body[0].id;
const card = Page.popularCarousel.getCard(id, true, DiscoverType.Popular);
card.title.realHover();
card.verifyTitle(intecept.response.body[0].title);
})
})
})
});

@ -11,6 +11,7 @@ describe("Navigation Bar Tests", () => {
Page.navbar.requests.should("be.visible"); Page.navbar.requests.should("be.visible");
Page.navbar.discover.should("be.visible"); Page.navbar.discover.should("be.visible");
Page.navbar.userPreferences.should("be.visible"); Page.navbar.userPreferences.should("be.visible");
Page.navbar.username.contains("a");
Page.navbar.logout.should("be.visible"); Page.navbar.logout.should("be.visible");
}); });
@ -34,6 +35,7 @@ describe("Navigation Bar Tests", () => {
Page.navbar.requests.should("be.visible"); Page.navbar.requests.should("be.visible");
Page.navbar.discover.should("be.visible"); Page.navbar.discover.should("be.visible");
Page.navbar.userPreferences.should("be.visible"); Page.navbar.userPreferences.should("be.visible");
Page.navbar.username.contains(id);
Page.navbar.logout.should("be.visible"); Page.navbar.logout.should("be.visible");
}); });
}); });

@ -16,7 +16,7 @@ describe("Search Tests", () => {
card.topLevelCard.realHover(); card.topLevelCard.realHover();
card.title.should('have.text', "Dexter's Laboratory"); card.title.should('have.text', "Dexter's Laboratory");
card.overview.contains('Cartoon Network'); card.overview.contains('Cartoon Network');
card.requestType.contains('Tv Show'); card.requestType.contains('TV Show');
card.requestButton.should('exist'); card.requestButton.should('exist');
}); });
@ -115,7 +115,7 @@ describe("Search Tests", () => {
card.topLevelCard.realHover(); card.topLevelCard.realHover();
card.title.should('have.text', "It's Always Sunny in Philadelphia"); card.title.should('have.text', "It's Always Sunny in Philadelphia");
card.overview.contains('Irish pub'); card.overview.contains('Irish pub');
card.requestType.contains('Tv Show'); card.requestType.contains('TV Show');
card.requestButton.should('exist'); card.requestButton.should('exist');
}); });

Loading…
Cancel
Save