diff --git a/src/Ombi/Attributes/WizardActionFilter.cs b/src/Ombi/Attributes/WizardActionFilter.cs new file mode 100644 index 000000000..644256d08 --- /dev/null +++ b/src/Ombi/Attributes/WizardActionFilter.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.DependencyInjection; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using System.Threading.Tasks; + +namespace Ombi.Attributes +{ + public class WizardActionFilter : IAsyncActionFilter + { + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + var settingsService = context.HttpContext.RequestServices.GetRequiredService>(); + + var settings = await settingsService.GetSettingsAsync(); + + if (!settings.Wizard) + { + await next(); + return; + } + context.Result = new UnauthorizedResult(); + } + } +} diff --git a/src/Ombi/ClientApp/angular.json b/src/Ombi/ClientApp/angular.json index cd17cccc0..2e3ff44e5 100644 --- a/src/Ombi/ClientApp/angular.json +++ b/src/Ombi/ClientApp/angular.json @@ -29,7 +29,10 @@ "src/styles/_imports.scss", "node_modules/bootstrap/scss/bootstrap.scss", "node_modules/primeng/resources/themes/md-dark-deeppurple/theme.css", - "node_modules/font-awesome/scss/font-awesome.scss", + "node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss", + "node_modules/@fortawesome/fontawesome-free/scss/regular.scss", + "node_modules/@fortawesome/fontawesome-free/scss/solid.scss", + "node_modules/@fortawesome/fontawesome-free/scss/brands.scss", "node_modules/primeng/resources/primeng.min.css", "node_modules/primeicons/primeicons.css", "node_modules/please-wait/src/please-wait.scss", diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json index 777dcfe8c..6c1713eff 100644 --- a/src/Ombi/ClientApp/package.json +++ b/src/Ombi/ClientApp/package.json @@ -24,6 +24,7 @@ "@angularclass/hmr": "^2.1.3", "@aspnet/signalr": "^1.1.0", "@auth0/angular-jwt": "^2.1.0", + "@fortawesome/fontawesome-free": "^5.15.2", "@fullcalendar/core": "^4.2.0", "@fullcalendar/daygrid": "^4.4.0", "@fullcalendar/interaction": "^4.2.0", @@ -39,7 +40,6 @@ "chart.js": "2.9.4", "core-js": "^2.5.4", "eventemitter2": "^5.0.1", - "font-awesome": "^4.7.0", "fullcalendar": "^4.0.0-alpha.4", "jquery": "3.3.1", "lodash": "^4.17.20", diff --git a/src/Ombi/ClientApp/src/app/app.component.html b/src/Ombi/ClientApp/src/app/app.component.html index f5f2d82eb..a8e527a6b 100644 --- a/src/Ombi/ClientApp/src/app/app.component.html +++ b/src/Ombi/ClientApp/src/app/app.component.html @@ -45,7 +45,7 @@ diff --git a/src/Ombi/ClientApp/src/app/custompage/custompage.component.html b/src/Ombi/ClientApp/src/app/custompage/custompage.component.html index d35c94141..ae2d00eb7 100644 --- a/src/Ombi/ClientApp/src/app/custompage/custompage.component.html +++ b/src/Ombi/ClientApp/src/app/custompage/custompage.component.html @@ -5,7 +5,7 @@
@@ -14,7 +14,7 @@
diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card-details.component.html b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card-details.component.html index d7bac2d96..3ac12d570 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card-details.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card-details.component.html @@ -16,35 +16,35 @@ + class="fas fa-play-circle fa-2x grow"> + class="fas fa-play-circle fa-2x grow"> + class="fas fa-play-circle fa-2x grow"> + class="fas fa-play-circle fa-2x grow"> + class="fas fa-play-circle fa-2x grow"> + class="fas fa-play-circle fa-2x grow"> - +
@@ -123,14 +123,14 @@ - @@ -140,27 +140,27 @@ + {{'Common.Available' | translate }} + {{'Common.PartiallyAvailable' | translate }} {{'Search.ViewOnPlex' | + href="{{tv.plexUrl}}" target="_blank"> {{'Search.ViewOnPlex' | translate}} {{'Search.ViewOnEmby' | + target="_blank"> {{'Search.ViewOnEmby' | translate}} {{'Search.ViewOnJellyfin' | + target="_blank"> {{'Search.ViewOnJellyfin' | translate}}
- {{getAvailbilityStatus()}} + {{getAvailbilityStatus()}}
diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss index 2c787eb37..21318e02b 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.scss @@ -159,17 +159,27 @@ small { } /* common */ -.top-right span { +.top-right{ + display:flex; +} + +.top-right span.indicator, span.indicator-text { display: none; background-color: transparent; color: #fff; text-shadow: 0 1px 1px rgba(0,0,0,.2); text-align: right; font-size: 14px; +} + +.top-right span.indicator{ + padding-right: 0px; +} +.top-right span.indicator-text{ padding-right: 1em; } -.top-right span:before{ +.top-right span.indicator:before{ content: ''; width: 10px; height: 10px; @@ -179,29 +189,29 @@ small { margin-right:5px; } -.top-right.available span{ +.top-right.available span.indicator, span.indicator-text{ display:block; } -.top-right.available span:before{ +.top-right.available span.indicator:before{ display: inline-block; background-color: #1DE9B6; } -.top-right.approved span { +.top-right.approved span.indicator, span.indicator-text { display: block; } -.top-right.approved span:before{ +.top-right.approved span.indicator:before{ display: inline-block; background-color: #ff5722; } -.top-right.requested span { +.top-right.requested span.indicator, span.indicator-text { display: block; } -.top-right.requested span:before{ +.top-right.requested span.indicator:before{ display: inline-block; background-color: #ffd740; } @@ -212,4 +222,18 @@ small { a.poster-overlay:hover{ text-decoration: none; +} + +@media screen and (max-width: 400px){ + .ellipsis{ + display:none; + } + + .top-right span.indicator-text{ + display:none; + } + + .top-right span.indicator{ + padding-right:1em; + } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss index d95586507..0951061a1 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss +++ b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.scss @@ -9,4 +9,9 @@ h2{ margin-top:40px; margin-left:40px; font-size: 24px; +} + +::ng-deep .p-carousel-item{ + min-height:290px; + max-height:290px; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.html b/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.html index e413cc372..959538444 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/grid/discover-grid.component.html @@ -118,14 +118,14 @@ *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"> @@ -135,7 +135,7 @@ diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html index 965017163..5a8ad4b42 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html @@ -9,7 +9,7 @@
-

{{'Discovery.NoSearch' | translate}}

+

{{'Discovery.NoSearch' | translate}}

\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/interfaces/IPlex.ts b/src/Ombi/ClientApp/src/app/interfaces/IPlex.ts index de3fc8cf1..6afc13e21 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IPlex.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IPlex.ts @@ -14,6 +14,8 @@ export interface IPlexOAuthViewModel { export interface IPlexOAuthAccessToken { accessToken: string; + success: boolean; + error: string; } export interface IPlexUser { diff --git a/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html index 44be113c6..c2de76c2b 100644 --- a/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/src/app/issues/issueDetails.component.html @@ -61,7 +61,7 @@
-
+

{{comment.comment}}

diff --git a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html index 298ce4c11..7f5d13c3c 100644 --- a/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html +++ b/src/Ombi/ClientApp/src/app/landingpage/landingpage.component.html @@ -13,21 +13,21 @@
-

 Notice

+

 Notice


- +
-

{{ 'LandingPage.OnlineHeading' | translate }}

+

{{ 'LandingPage.OnlineHeading' | translate }}

-

{{ 'LandingPage.PartiallyOnlineHeading' | translate }}

+

{{ 'LandingPage.PartiallyOnlineHeading' | translate }}

There is {{mediaServerStatus.serversUnavailable}} server offline out of {{mediaServerStatus.totalServers}}.

@@ -35,7 +35,7 @@
-

{{ 'LandingPage.OfflineHeading' | translate }}

+

{{ 'LandingPage.OfflineHeading' | translate }}

diff --git a/src/Ombi/ClientApp/src/app/login/login.component.html b/src/Ombi/ClientApp/src/app/login/login.component.html index d48b58e31..ced032260 100644 --- a/src/Ombi/ClientApp/src/app/login/login.component.html +++ b/src/Ombi/ClientApp/src/app/login/login.component.html @@ -40,7 +40,7 @@
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html index 46c5b97c9..1a7db7f91 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/artist/artist-details.component.html @@ -23,12 +23,12 @@
+ {{ 'MediaDetails.RequestAllAlbums' | translate }} + {{ 'MediaDetails.RequestSelectedAlbums' | translate }} + {{ 'MediaDetails.ClearSelection' | translate }} @@ -39,39 +39,39 @@ --> diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index 6e809c90d..ecd15dc45 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -32,68 +32,71 @@
-
- - +
+
+ +
-
- - - {{'Search.ViewOnPlex' | translate}} - - - - {{'Search.ViewOnEmby' | translate}} - - - - {{'Search.ViewOnJellyfin' | translate}} - - - - - - - - + + + + + + + + + + + - - - - - - - - - + + + + - - - - - +
@@ -125,6 +128,28 @@
+ + +
+
+ + Trailers + + + + + + + + +
+
+
@@ -172,20 +197,6 @@
- - - - {{'MediaDetails.VideosTitle' | translate}} - - - -
- -
- -
-
-
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html index 0cde69b8b..847f51491 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html @@ -1,32 +1,32 @@ diff --git a/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss b/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss index e8ed3e2e1..6e752ce80 100644 --- a/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss +++ b/src/Ombi/ClientApp/src/app/media-details/media-details.component.scss @@ -14,12 +14,6 @@ } } -@media (max-width: 767px) { - #summary-wrapper { - height: 350px !important; - } -} - #summary-wrapper .full-screenshot, .summary-wrapper .full-screenshot, #watching-wrapper .full-screenshot, @@ -43,7 +37,7 @@ background-size: cover; background-position: 50% 10%; transition: all .5s; - height: 300px; + height: 600px; color: #fff; position: relative; } @@ -85,7 +79,7 @@ #summary-wrapper .summary .container, .summary-wrapper .summary .container { position: absolute; - bottom: 0; + bottom: 300px; left: 0; right: 0; } @@ -176,7 +170,8 @@ } .media-row { - padding-top: 2%; + padding-top: 56px; + padding-left: 26px; } .cast-profile-img { @@ -235,7 +230,7 @@ text-align:right; display:flex; justify-content: flex-end; - padding-right:2em; + padding-right:2.5% } .viewon-btn { @@ -255,3 +250,27 @@ border: 1px solid #00a4dc; color: #00a4dc; } + +::ng-deep .p-carousel-indicators { + display: none !important; + } + + +#info-wrapper{ + margin-top:-200px; +} +.full-screenshot.enabled.overlay{ + background-image: linear-gradient(to bottom, transparent, 50%, $ombi-background-primary); +} + +.row.justify-content-center.justify-content-sm-start.header-container{ + flex-wrap: nowrap; +} + +.details-button-container{ + width:100%; +} + +.info-wrapper .row{ + flex-wrap:wrap; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html index 368341b3d..cb23212d2 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html @@ -29,7 +29,7 @@ {{nav.icon}} -  {{nav.name | translate}} diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts index 9a5ec794c..d7216d114 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts @@ -87,7 +87,7 @@ export class MyNavComponent implements OnInit { // { name: "NavigationBar.Calendar", icon: "calendar_today", link: "/calendar", requiresAdmin: false, enabled: true }, { name: "NavigationBar.Donate", icon: "attach_money", link: "https://www.paypal.me/PlexRequestsNet", externalLink: true, requiresAdmin: true, enabled: true, toolTip: true, style: "color:red;", toolTipMessage: 'NavigationBar.DonateTooltip', faIcon: null }, { name: "NavigationBar.Donate", icon: "attach_money", link: customizationSettings.customDonationUrl, externalLink: true, requiresAdmin: false, enabled: customizationSettings.enableCustomDonations, toolTip: true, toolTipMessage: customizationSettings.customDonationMessage, faIcon: null }, - { name: "NavigationBar.FeatureSuggestion", icon: null, link: "https://features.ombi.io/", externalLink: true, requiresAdmin: true, enabled: true, toolTip: true, toolTipMessage: 'NavigationBar.FeatureSuggestionTooltip', faIcon: "fa-lightbulb-o" }, + { name: "NavigationBar.FeatureSuggestion", icon: null, link: "https://features.ombi.io/", externalLink: true, requiresAdmin: true, enabled: true, toolTip: true, toolTipMessage: 'NavigationBar.FeatureSuggestionTooltip', faIcon: "fa-lightbulb" }, { name: "NavigationBar.Settings", icon: "settings", link: "/Settings/About", requiresAdmin: true, enabled: true, faIcon: null }, { name: "NavigationBar.UserPreferences", icon: "person", link: "/user-preferences", requiresAdmin: false, enabled: true, faIcon: null }, ]; diff --git a/src/Ombi/ClientApp/src/app/requests/movierequests.component.html b/src/Ombi/ClientApp/src/app/requests/movierequests.component.html index 3f8485fce..ad82ffbb9 100644 --- a/src/Ombi/ClientApp/src/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/src/app/requests/movierequests.component.html @@ -4,13 +4,13 @@ (keyup)="search($event)">
{{ 'Requests.Denied' | translate }} - +
@@ -124,11 +124,11 @@ - + - +
@@ -137,14 +137,14 @@
@@ -186,11 +186,11 @@
@@ -200,14 +200,14 @@
+ {{ 'Filter.ClearFilter' | translate }} diff --git a/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.html index 3565898ed..9f5e08fdd 100644 --- a/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/src/app/requests/music/musicrequests.component.html @@ -4,13 +4,13 @@ (keyup)="search($event)"> @@ -32,9 +32,9 @@ - - - -
- - - +
+
+ +
+
+
+

Protect your Ombi

+ Create an Admin account to make sure you are always able to access your Ombi. +
+ + + +
+ + + +
+ You'll need to configure e-mail to reset your password! +
+
diff --git a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts index e691ca627..ec87a5668 100644 --- a/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/createadmin/createadmin.component.ts @@ -4,6 +4,7 @@ import { ICreateWizardUser } from "../../interfaces"; @Component({ selector: "wizard-local-admin", templateUrl: "./createadmin.component.html", + styleUrls: ["../welcome/welcome.component.scss"] }) export class CreateAdminComponent { diff --git a/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.html b/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.html index 9c92f8a86..53f4bd161 100644 --- a/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.html @@ -1,31 +1,40 @@ - -
-
-
-
- - - -
+
+
+ +
+
+
+

Emby Configuration

+
+
+
+
+ + + +
-
+
- - - -
-
- Enable SSL -
-
- - - - -
-
- Save
+ + + +
+
+ Enable SSL +
+
+ + + + +
+
+
+
+
+
diff --git a/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts b/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts index f528d8be3..fb0c167a6 100644 --- a/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/emby/emby.component.ts @@ -8,6 +8,7 @@ import { IEmbySettings } from "../../interfaces"; @Component({ selector: "wizard-emby", templateUrl: "./emby.component.html", + styleUrls: ["../welcome/welcome.component.scss"], }) export class EmbyComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.html b/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.html index f88342c1d..653e54876 100644 --- a/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.html @@ -1,31 +1,40 @@ - -
-
-
-
- - - -
+
+
+ +
+
+
+

Jellyfin Configuration

+
+
+
+
+ + + +
-
+
- - - -
-
- Enable SSL -
-
- - - - -
-
- Save
+ + + +
+
+ Enable SSL +
+
+ + + + +
+
+
+
+
+
diff --git a/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.ts b/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.ts index e6b96d0f7..f3779b6be 100644 --- a/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/jellyfin/jellyfin.component.ts @@ -8,6 +8,7 @@ import { IJellyfinSettings } from "../../interfaces"; @Component({ selector: "wizard-jellyfin", templateUrl: "./jellyfin.component.html", + styleUrls: ["../welcome/welcome.component.scss"] }) export class JellyfinComponent implements OnInit { diff --git a/src/Ombi/ClientApp/src/app/wizard/models/OmbiConfigModel.ts b/src/Ombi/ClientApp/src/app/wizard/models/OmbiConfigModel.ts new file mode 100644 index 000000000..29e6e68a9 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/wizard/models/OmbiConfigModel.ts @@ -0,0 +1,5 @@ +export interface IOmbiConfigModel { + applicationName: string; + applicationUrl: string; + logo: string; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html new file mode 100644 index 000000000..33d15bb58 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.html @@ -0,0 +1,28 @@ +
+
+ +
+
+
+

Customize your Ombi

+

Customize your {{config.applicationName}}

+
+ + + +
+
+ + + +
+
+ + Custom Logo + + +
+
+
+
+ diff --git a/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.ts b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.ts new file mode 100644 index 000000000..0b7e3863b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/wizard/ombiconfig/ombiconfig.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from "@angular/core"; +import { IOmbiConfigModel } from "../models/OmbiConfigModel"; +import { WizardService } from "../services/wizard.service"; + +@Component({ + selector: "wizard-ombi", + templateUrl: "./ombiconfig.component.html", + styleUrls: ["../welcome/welcome.component.scss"] +}) +export class OmbiConfigComponent { + + @Input() public config: IOmbiConfigModel; +} diff --git a/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.html b/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.html index 4a120f790..611dc4500 100644 --- a/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.html @@ -1,24 +1,38 @@ -
-
- - - -
-
- - - -
-
-Please note we do not store this information, we only store your Plex Authorization Token that will allow Ombi to view your media and users -
-
- +
+
+
-
-

OR

-
-
- +
+
+

Plex Configuration

+
+
+ + + +
+
+ + + +
+
+ Please note we do not store this information, we only store your Plex Authorization Token that will allow Ombi to view your media and users +
+
+
+ +
+
+

OR

+
+
+ +
+
+
+
diff --git a/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts b/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts index e469ddc00..bc80c65cb 100644 --- a/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/plex/plex.component.ts @@ -9,12 +9,15 @@ import { StorageService } from "../../shared/storage/storage-service"; @Component({ selector: "wizard-plex", templateUrl: "./plex.component.html", + styleUrls: ["../welcome/welcome.component.scss"], }) export class PlexComponent implements OnInit, OnDestroy { public login: string; public password: string; public pinTimer: any; + public completed: boolean; + public oauthLoading: boolean; private clientId: string; @@ -42,7 +45,7 @@ export class PlexComponent implements OnInit, OnDestroy { usePlexAdminAccount: true, }).subscribe(y => { if (y.result) { - this.router.navigate(["login"]); + this.notificationService.success("Created your Plex User!"); } else { this.notificationService.error("Could not get the Plex Admin Information"); if (y.errors.length > 0) { @@ -56,6 +59,7 @@ export class PlexComponent implements OnInit, OnDestroy { } public oauth() { + this.oauthLoading = true; const oAuthWindow = window.open(window.location.toString(), "_blank", `toolbar=0, location=0, status=0, @@ -68,20 +72,24 @@ export class PlexComponent implements OnInit, OnDestroy { this.authService.login({ usePlexOAuth: true, password: "", rememberMe: true, username: "", plexTvPin: pin }).subscribe(x => { oAuthWindow!.location.replace(x.url); - this.pinTimer = setInterval(() => { // this.notify.info("Authenticating", "Loading... Please Wait"); this.getPinResult(x.pinId); - }, 10000); + }, 3000); }); }); } public getPinResult(pinId: number) { this.plexOauth.oAuth(pinId).subscribe(x => { + if (!x.accessToken) { + if(!x.success) { + this.oauthLoading = false; + clearInterval(this.pinTimer); + this.notificationService.error(`Error From Plex: ${x.error}`) + } return; - // RETURN } this.identityService.createWizardUser({ @@ -92,10 +100,14 @@ export class PlexComponent implements OnInit, OnDestroy { if (u.result) { this.authService.oAuth(pinId).subscribe(c => { this.store.save("id_token", c.access_token); - this.router.navigate(["login"]); + this.completed = true; + this.notificationService.success("Created your Plex User!"); + this.oauthLoading = false; + clearInterval(this.pinTimer); }); } else { + this.oauthLoading = false; if (u.errors.length > 0) { console.log(u.errors[0]); } diff --git a/src/Ombi/ClientApp/src/app/wizard/services/wizard.service.ts b/src/Ombi/ClientApp/src/app/wizard/services/wizard.service.ts new file mode 100644 index 000000000..0f6511265 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/wizard/services/wizard.service.ts @@ -0,0 +1,19 @@ +import { PlatformLocation, APP_BASE_HREF } from "@angular/common"; +import { HttpClient } from "@angular/common/http"; +import { Injectable, Inject } from "@angular/core"; +import { Observable } from "rxjs"; +import { ICustomizationSettings } from "../../interfaces"; +import { ServiceHelpers } from "../../services"; +import { IOmbiConfigModel } from "../models/OmbiConfigModel"; + + +@Injectable() +export class WizardService extends ServiceHelpers { + constructor(public http: HttpClient, @Inject(APP_BASE_HREF) href:string) { + super(http, "/api/v2/wizard/", href); + } + + public addOmbiConfig(config: IOmbiConfigModel): Observable { + return this.http.post(`${this.url}config`, config, {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html index dfec7f8d9..6f46803c4 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.html @@ -1,67 +1,87 @@ -
+
+
Welcome -

Welcome to Ombi, this wizard will quickly take you through the inital setup!

-
- +
+ +
+
+

Welcome to Ombi!

+

This wizard will quickly take you through the inital setup!

+

If you encounter any problems, please reach out on the following platforms:

+
+ +
+
+
+
+
-
- Plex - -
- - -
-
-
- - -
- Emby - -
- - -
-
-
- - -
- Jellyfin - -
- - -
-
-
- - -
- Create a local admin - -
- - -
-
-
+
+ Media Server + + + + + + + +
+ + +
+ Create a local admin + +
+ + +
+
+
+ +
+ Ombi config + +
+ + +
+
+
Done - All setup! Press Finish to continue and login to Ombi! +
+
+ +
+
+
+

All setup!

+ Press Finish to continue and login to Ombi! +
+
+
- - + +
-
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.scss b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.scss new file mode 100644 index 000000000..053516b6f --- /dev/null +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.scss @@ -0,0 +1,172 @@ +@import "~styles/variables.scss"; +.welcome-container{ + display:flex; + height:100%; + width:100%; +} + +.welcome-container .logo{ + font-family: Montserrat,sans-serif; + text-transform: uppercase; + color: #62d2fa; + font-weight: 700; + font-size: 5em; + display:flex; + justify-content: center; + align-items: center; + height:300px; +} + +.left-container{ + width:30%; +} + +.right-container{ + width:60%; + float:right; +} + +.right-container-content{ + width:100%; +} + +.welcome-container .right-container{ + display:flex; + align-items: center; + justify-content: center; +} + +.welcome-buttons{ + float:right; +} + +.fab:before { + font-family: 'Font Awesome 5 Brands'; +} + +.social-media .fab{ + font-family: Roboto, "Helvetica Neue", sans-serif; +} + +.fas:before { + font-family:"Font Awesome 5 Free"; + font-weight:800; +} + +.social-media .fas{ + font-family: Roboto, "Helvetica Neue", sans-serif; + font-weight:400; +} + +.social-media a{ + color: #FFF; +} + +.social-media{ + display:grid; +} + +.fa-ul { + list-style-type: none; + margin-left: 2.5em; + padding-left: 0; +} + +.fa-li { + left: -2em; + position: absolute; + text-align: center; + width: 2em; + line-height: inherit; +} + +.social-media ul li{ + font-size:16px; + padding:5px; +} + + +.left-container.mediaserver img{ + object-fit: contain; + width: 100%; +} + +.left-container.mediaserver{ + display:flex; + justify-content: center; + align-items: center; + height:300px; + padding:20px; +} + +.right-container.mediaserver{ + display:flex; + justify-content: center; + align-items:center; +} + +.right-container-content .mediaserver{ + display:block; +} + +.mediaserver-container{ + display:flex; + height:100%; + width:100%; + justify-content: space-between; +} + +.plex-buttons{ + display:flex; + justify-content: center; + align-items: center; +} + +p.space-or{ + padding:20px; + margin-top:20px; +} + +.viewon-btn.plex { + border: 1px solid #e5a00d; + color: #e5a00d; +} + +.viewon-btn { + background-color: transparent; + text-decoration: none; +} + +.viewon-btn.standard { + border: 1px solid #FFF; +} + +.viewon-btn.emby { + border: 1px solid #52B54B; + color: #52B54B; +} + +.viewon-btn.jellyfin { + border: 1px solid #A45FC4; + color: #A45FC4; +} + +.text-logo{ + font-size:12em; +} + +.left{ + float:left; +} + +.right{ + float:right; +} + +small.important{ + color:red; +} + +h1.wizard-title{ + margin-top:30px; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts index a46b04bd4..849977b55 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts @@ -1,35 +1,53 @@ -import { Component, OnInit } from "@angular/core"; +import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; import { Router } from "@angular/router"; import { ICreateWizardUser } from "../../interfaces"; import { IdentityService, NotificationService } from "../../services"; +import { IOmbiConfigModel } from "../models/OmbiConfigModel"; +import { WizardService } from "../services/wizard.service"; +import { MatHorizontalStepper } from'@angular/material/stepper'; +import { StepperSelectionEvent } from "@angular/cdk/stepper"; @Component({ templateUrl: "./welcome.component.html", + styleUrls: ["./welcome.component.scss"], }) export class WelcomeComponent implements OnInit { - + + @ViewChild('stepper', {static: false}) public stepper: MatHorizontalStepper; public localUser: ICreateWizardUser; - - constructor(private router: Router, - private identityService: IdentityService, private notificationService: NotificationService) { } + public config: IOmbiConfigModel; + + constructor(private router: Router, private identityService: IdentityService, + private notificationService: NotificationService, private WizardService: WizardService) { } - public ngOnInit(): void { + public ngOnInit(): void { this.localUser = { password:"", username:"", usePlexAdminAccount:false } + this.config = { + applicationName: null, + applicationUrl: null, + logo: null + }; } public createUser() { - this.identityService.createWizardUser(this.localUser).subscribe(x => { - if (x.result) { + this.WizardService.addOmbiConfig(this.config).subscribe(config => { + if(config != null) { + this.identityService.createWizardUser(this.localUser).subscribe(x => { + if (x.result) { + // save the config this.router.navigate(["login"]); } else { if (x.errors.length > 0) { this.notificationService.error(x.errors[0]); + this.stepper.previous(); } } }); } + }, configErr => this.notificationService.error(configErr)); + } } diff --git a/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts b/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts index 1e34a1de9..501995ce6 100644 --- a/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts +++ b/src/Ombi/ClientApp/src/app/wizard/wizard.module.ts @@ -11,12 +11,14 @@ import { JellyfinComponent } from "./jellyfin/jellyfin.component"; import { MediaServerComponent } from "./mediaserver/mediaserver.component"; import { PlexComponent } from "./plex/plex.component"; import { WelcomeComponent } from "./welcome/welcome.component"; +import { OmbiConfigComponent } from "./ombiconfig/ombiconfig.component"; import { EmbyService } from "../services"; import { JellyfinService } from "../services"; import { PlexService } from "../services"; import { IdentityService } from "../services"; import { PlexOAuthService } from "../services"; +import { WizardService } from "./services/wizard.service"; import { SharedModule } from "../shared/shared.module"; @@ -27,6 +29,7 @@ const routes: Routes = [ { path: "Emby", component: EmbyComponent}, { path: "Jellyfin", component: JellyfinComponent}, { path: "CreateAdmin", component: CreateAdminComponent}, + { path: "OmbiConfig", component: OmbiConfigComponent}, ]; @NgModule({ imports: [ @@ -44,6 +47,7 @@ const routes: Routes = [ CreateAdminComponent, EmbyComponent, JellyfinComponent, + OmbiConfigComponent, ], exports: [ RouterModule, @@ -54,6 +58,7 @@ const routes: Routes = [ EmbyService, JellyfinService, PlexOAuthService, + WizardService, ], }) diff --git a/src/Ombi/ClientApp/src/styles/Styles.scss b/src/Ombi/ClientApp/src/styles/Styles.scss index 7fd667cf2..f34d199a0 100644 --- a/src/Ombi/ClientApp/src/styles/Styles.scss +++ b/src/Ombi/ClientApp/src/styles/Styles.scss @@ -37,6 +37,7 @@ .mat-flat-button.mat-accent, .mat-raised-button.mat-accent, .mat-fab.mat-accent, .mat-mini-fab.mat-accent{ color: $ombi-active-text; + background-color: $ombi-active; } .mat-menu-panel{ @@ -100,3 +101,43 @@ background: $ombi-background-accent; } } + + .mat-tooltip{ + background: $ombi-background-accent; + } + + //Wizard CSS + .mat-stepper-horizontal, .mat-stepper-vertical{ + background: $ombi-background-accent; + } + + .wizard-background{ + background-color: $ombi-background-primary; + width:100%; + height:100vh; + display:flex; + align-items:center; + justify-content: center; + } + + .wizard-inner{ + color:#FFF; + min-height: 450px; + } + + .wizard-inner .mat-stepper-horizontal { + min-height: 450px; + } + + .mat-step-header .mat-step-icon{ + background-color:$ombi-active; + color: $ombi-active-text; + } + + .mat-tab-group.mat-primary .mat-ink-bar, .mat-tab-nav-bar.mat-primary .mat-ink-bar{ + background-color: $ombi-active; + } + + .mat-flat-button, .mat-raised-button, .mat-fab, .mat-mini-fab{ + background-color: $ombi-active; + } diff --git a/src/Ombi/ClientApp/src/styles/primeng-overrides.scss b/src/Ombi/ClientApp/src/styles/primeng-overrides.scss index 4ccb0765e..e8c023644 100644 --- a/src/Ombi/ClientApp/src/styles/primeng-overrides.scss +++ b/src/Ombi/ClientApp/src/styles/primeng-overrides.scss @@ -9,10 +9,10 @@ .ui-carousel-viewport { border:0 !important; - background-color:transparent !important; + background-color:transparent !important; } .ui-carousel .ui-carousel-header { background-color:transparent !important; - border: 0 !important; -} \ No newline at end of file + border: 0 !important; +} diff --git a/src/Ombi/ClientApp/yarn.lock b/src/Ombi/ClientApp/yarn.lock index a834d8bdf..d976c8be5 100644 --- a/src/Ombi/ClientApp/yarn.lock +++ b/src/Ombi/ClientApp/yarn.lock @@ -1126,6 +1126,11 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@fortawesome/fontawesome-free@^5.15.2": + version "5.15.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz#218cd7276ab4f9ab57cc3d2efa2697e6a579f25d" + integrity sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA== + "@fullcalendar/core@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@fullcalendar/core/-/core-4.4.0.tgz#79dbc0cca836ce628a07e739a456da11ff141373" @@ -3841,10 +3846,6 @@ follow-redirects@^1.0.0: dependencies: debug "=3.1.0" -font-awesome@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" diff --git a/src/Ombi/Controllers/V1/IdentityController.cs b/src/Ombi/Controllers/V1/IdentityController.cs index 63f8211ca..342e4620d 100644 --- a/src/Ombi/Controllers/V1/IdentityController.cs +++ b/src/Ombi/Controllers/V1/IdentityController.cs @@ -139,7 +139,7 @@ namespace Ombi.Controllers.V1 public async Task CreateWizardUser([FromBody] CreateUserWizardModel user) { var users = UserManager.Users; - if (users.Any(x => x.NormalizedUserName != "API")) + if (users.Any(x => x.UserType == UserType.LocalUser)) { // No one should be calling this. Only the wizard return new SaveWizardResult { Result = false, Errors = new List { "Looks like there is an existing user!" } }; @@ -169,7 +169,7 @@ namespace Ombi.Controllers.V1 ImportPlexAdmin = true }); - return await SaveWizardUser(user, adminUser); + return await SaveWizardUser(user, adminUser, false); } var userToCreate = new OmbiUser @@ -179,10 +179,10 @@ namespace Ombi.Controllers.V1 StreamingCountry = "US" }; - return await SaveWizardUser(user, userToCreate); + return await SaveWizardUser(user, userToCreate, true); } - private async Task SaveWizardUser(CreateUserWizardModel user, OmbiUser userToCreate) + private async Task SaveWizardUser(CreateUserWizardModel user, OmbiUser userToCreate, bool completeWizard) { IdentityResult result; var retVal = new SaveWizardResult(); @@ -210,10 +210,13 @@ namespace Ombi.Controllers.V1 _log.LogInformation("Added the Admin role"); } - // Update the wizard flag - var settings = await OmbiSettings.GetSettingsAsync(); - settings.Wizard = true; - await OmbiSettings.SaveSettingsAsync(settings); + if (completeWizard) + { + // Update the wizard flag + var settings = await OmbiSettings.GetSettingsAsync(); + settings.Wizard = true; + await OmbiSettings.SaveSettingsAsync(settings); + } } if (!result.Succeeded) { diff --git a/src/Ombi/Controllers/V2/WizardController.cs b/src/Ombi/Controllers/V2/WizardController.cs new file mode 100644 index 000000000..bb3bed5b6 --- /dev/null +++ b/src/Ombi/Controllers/V2/WizardController.cs @@ -0,0 +1,54 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Ombi.Attributes; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Models.V2; +using Ombi.Settings.Settings.Models; +using System.Threading.Tasks; + +namespace Ombi.Controllers.V2 +{ + [ServiceFilter(typeof(WizardActionFilter))] + [AllowAnonymous] + public class WizardController : V2Controller + { + private ISettingsService _customizationSettings { get; } + + public WizardController(ISettingsService customizationSettings) + { + _customizationSettings = customizationSettings; + } + + [HttpPost("config")] + [ApiExplorerSettings(IgnoreApi =true)] + public async Task OmbiConfig([FromBody] OmbiConfigModel config) + { + if (config == null) + { + return BadRequest(); + } + + var settings = await _customizationSettings.GetSettingsAsync(); + + if (config.ApplicationName.HasValue()) + { + settings.ApplicationName = config.ApplicationName; + } + + if(config.ApplicationUrl.HasValue()) + { + settings.ApplicationUrl = config.ApplicationUrl; + } + + if(config.Logo.HasValue()) + { + settings.Logo = config.Logo; + } + + await _customizationSettings.SaveSettingsAsync(settings); + + return new OkObjectResult(settings); + } + } +} diff --git a/src/Ombi/Models/V2/OmbiConfigModel.cs b/src/Ombi/Models/V2/OmbiConfigModel.cs new file mode 100644 index 000000000..caecdfa2b --- /dev/null +++ b/src/Ombi/Models/V2/OmbiConfigModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ombi.Models.V2 +{ + public class OmbiConfigModel + { + public string ApplicationName { get; set; } + public string ApplicationUrl { get; set; } + public string Logo { get; set; } + } +} diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index fecaaccb3..56e28ce14 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -30,6 +30,7 @@ using Newtonsoft.Json; using ILogger = Serilog.ILogger; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Ombi.HealthChecks; +using Ombi.Attributes; namespace Ombi { @@ -97,6 +98,7 @@ namespace Ombi services.RegisterApplicationDependencies(); // Ioc and EF services.AddSwagger(); services.AddAppSettingsValues(Configuration); + services.AddScoped(); services.AddCors(o => o.AddPolicy("MyPolicy", builder => {