Skip to content

Commit

Permalink
Started adding the ability for them to self manage their accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
tidusjar committed Mar 21, 2021
1 parent 612fbb2 commit 27f0d6e
Show file tree
Hide file tree
Showing 15 changed files with 379 additions and 175 deletions.
5 changes: 4 additions & 1 deletion src/Ombi/ClientApp/src/app/interfaces/IUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ export interface IIdentityResult {
successful: boolean;
}

export interface IUpdateLocalUser extends IUser {
export interface IUpdateLocalUser {
currentPassword: string;
password: string;
id: string;
emailAddress: string;
confirmNewPassword: string;
}

Expand Down
12 changes: 6 additions & 6 deletions src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@
<mat-nav-list>
<span *ngFor="let nav of navItems">

<div *ngIf="(nav.requiresAdmin && isAdmin || !nav.requiresAdmin) && nav.enabled">
<div class="menu-spacing" *ngIf="(nav.requiresAdmin && isAdmin || !nav.requiresAdmin) && nav.enabled">


<a id="{{nav.id}}" *ngIf="nav.externalLink" mat-list-item [href]="nav.link" target="_blank"
matTooltip="{{nav.toolTipMessage | translate}}" matTooltipPosition="right"
[routerLinkActive]="'active-list-item'">

<i *ngIf="nav.icon" class="fa-lg {{nav.icon}}"
<i *ngIf="nav.icon" class="fa-lg {{nav.icon}} icon-spacing"
style="padding-left: 5px; padding-right: 5px;" aria-hidden="true"></i>
&nbsp;{{nav.name | translate}}
</a>
<a id="{{nav.id}}" *ngIf="!nav.externalLink" mat-list-item [routerLink]="nav.link" [style]="nav.color"
[routerLinkActive]="'active-list-item'">

<i class="fa-lg {{nav.icon}}"></i>
<i class="fa-lg {{nav.icon}} icon-spacing"></i>
&nbsp;{{nav.name | translate}}
</a>
</div>
</span>

<a id="nav-logout" mat-list-item [routerLinkActive]="'active-list-item'"
<a class="menu-spacing" id="nav-logout" mat-list-item [routerLinkActive]="'active-list-item'"
aria-label="Toggle sidenav" (click)="logOut();">
<i class="fa-lg fas fa-sign-out-alt"></i>
<i class="fa-lg fas fa-sign-out-alt icon-spacing"></i>
&nbsp;{{ 'NavigationBar.Logout' | translate }}
</a>

Expand Down Expand Up @@ -82,7 +82,7 @@
</div>
<div class="col-1">
<a routerLink="/user-preferences">
<img [matTooltip]="username" class="profile-img" [src]="getUserImage()" />
<img [matTooltip]="username" id="profile-image" class="profile-img" [src]="getUserImage()" />
</a>
</div>

Expand Down
8 changes: 8 additions & 0 deletions src/Ombi/ClientApp/src/app/my-nav/my-nav.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
display: flex;
}

.menu-spacing {
margin-bottom: 5%;
}

.icon-spacing {
margin-right: 5%;
}

.example-form {
min-width: 150px;
max-width: 500px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,135 @@
<div class="small-middle-container" *ngIf="username">
<h3 [translate]="'UserPreferences.Welcome'" [translateParams]="{username: username}"></h3>


<hr>
<div class="row top-spacing">
<div class="col-4">
<div>
<small>{{'UserPreferences.LanguageDescription' | translate}}</small>
<br>
<mat-form-field>
<mat-label [translate]="'UserPreferences.OmbiLanguage'"></mat-label>
<mat-select id="langSelect" [(value)]="selectedLang" (selectionChange)="languageSelected();">
<mat-option id="langSelect{{lang.value}}" *ngFor="let lang of availableLanguages" [value]="lang.value">
{{lang.display}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div>

</div>
<div class="row h-100">
<div class="col-1">
<img class="profile-img" [src]="getProfileImage()">
</div>
<div class="col-1"></div>
<div class="col-7">
<mat-label [translate]="'UserPreferences.MobileQRCode'"></mat-label>
<div id="noQrCode" *ngIf="!qrCodeEnabled" [translate]="'UserPreferences.NoQrCode'"></div>
<qrcode id="qrCode" *ngIf="qrCodeEnabled" [qrdata]="qrCode" [size]="256" [level]="'L'"></qrcode>
<button mat-raised-button (click)="openMobileApp($event)" *ngIf="customizationSettings.applicationUrl"> {{
'UserPreferences.LegacyApp' | translate }}</button>
<div class="col-11 align-middle">
<h2 id="usernameTitle">{{username}} <small id="emailTitle" *ngIf="user.emailAddress">({{user.emailAddress}})</small></h2>

</div>
</div>


<mat-tab-group>
<mat-tab label="Profile">
<div class="tab-content">

<div class="row">
<div class="col-1">
User Type:
</div>
<div class="col-11">
{{UserType[user.userType]}}
</div>
</div>

<div class="row">
<div class="col-4">
<div>
<small>{{'UserPreferences.LanguageDescription' | translate}}</small>
<br>
<mat-form-field>
<mat-label [translate]="'UserPreferences.OmbiLanguage'"></mat-label>
<mat-select id="langSelect" [(value)]="selectedLang" (selectionChange)="languageSelected();">
<mat-option id="langSelect{{lang.value}}" *ngFor="let lang of availableLanguages"
[value]="lang.value">
{{lang.display}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div>

</div>
</div>
<div class="col-1"></div>


<div class="col-4">
<div>
<small>{{'UserPreferences.StreamingCountryDescription' | translate}}</small>
<br>
<mat-form-field>
<mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label>
<mat-select id="streamingSelect" [(value)]="selectedCountry" (selectionChange)="countrySelected();">
<mat-option id="streamingSelect{{value}}" *ngFor="let value of countries" [value]="value">
{{value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div>
</div>
</div>
</div>



<div class="col-4">
<div>
<small>{{'UserPreferences.StreamingCountryDescription' | translate}}</small>
<br>
<mat-form-field>
<mat-label [translate]="'UserPreferences.StreamingCountry'"></mat-label>
<mat-select id="streamingSelect" [(value)]="selectedCountry" (selectionChange)="countrySelected();">
<mat-option id="streamingSelect{{value}}" *ngFor="let value of countries" [value]="value">
{{value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div>

</mat-tab>
<mat-tab *ngIf="user.userType === UserType.LocalUser" label="Security">
<div class="tab-content">
<h2>Change Details</h2>
<form novalidate [formGroup]="passwordForm" (ngSubmit)="updatePassword()">
<div class="row">
<div class="col-md-6 col-12">
<span>You need your current password to make any changes here</span>
<mat-form-field appearance="outline" floatLabel=always>
<mat-label>Current Password</mat-label>
<input id="currentPassword" matInput type="password" formControlName="currentPassword">
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-md-6 col-12">
<mat-form-field appearance="outline" floatLabel=always>
<mat-label>Email Address</mat-label>
<input id="email" matInput formControlName="emailAddress">
</mat-form-field>
</div>
</div>

<div class="row">
<div class="col-md-6 col-12">
<mat-form-field appearance="outline" floatLabel=always>
<mat-label>New Password</mat-label>
<input id="newPassword" matInput type="password" formControlName="password">
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-md-6 col-12">
<mat-form-field appearance="outline" floatLabel=always>
<mat-label>New Password Confirm</mat-label>
<input id="confirmPassword" matInput type="password" formControlName="confirmPassword">
</mat-form-field>
</div>
</div>
<button id="submitSecurity" mat-raised-button color="accent" type="submit">Update</button>
</form>

</div>
</div>

</mat-tab>


<mat-tab label="Preferences"> Coming Soon... </mat-tab>


<mat-tab label="Mobile">
<div class="tab-content">
<div class="col-7">
<mat-label [translate]="'UserPreferences.MobileQRCode'"></mat-label>
<div id="noQrCode" *ngIf="!qrCodeEnabled" [translate]="'UserPreferences.NoQrCode'"></div>
<qrcode id="qrCode" *ngIf="qrCodeEnabled" [qrdata]="qrCode" [size]="256" [level]="'L'"></qrcode>
<button mat-raised-button (click)="openMobileApp($event)" *ngIf="customizationSettings.applicationUrl"> {{
'UserPreferences.LegacyApp' | translate }}</button>
</div>
</div>
</mat-tab>
</mat-tab-group>



</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
.small-middle-container{
margin: auto;
margin-top: 3%;
width: 80%;
width: 90%;
}

.profile-img {
border-radius: 100%;
width: 75px;
}
.my-auto {
margin-top: auto;
margin-bottom: auto;
}

::ng-deep .mat-tab-body-content {
height: 100%;
overflow: hidden !important;
}

.tab-content {
margin-top: 1%;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Component, OnInit } from "@angular/core";
import { AuthService } from "../../../auth/auth.service";
import { TranslateService } from "@ngx-translate/core";
import { AvailableLanguages, ILanguage } from "./user-preference.constants";
import { StorageService } from "../../../shared/storage/storage-service";
import { IdentityService, NotificationService, SettingsService } from "../../../services";
import { ICustomizationSettings, IUser } from "../../../interfaces";
import { IdentityService, NotificationService, SettingsService, ValidationService } from "../../../services";
import { ICustomizationSettings, IUser, UserType } from "../../../interfaces";
import { Md5 } from "ts-md5";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";

@Component({
templateUrl: "./user-preference.component.html",
Expand All @@ -20,14 +21,19 @@ export class UserPreferenceComponent implements OnInit {
public countries: string[];
public selectedCountry: string;
public customizationSettings: ICustomizationSettings;
public UserType = UserType;

public passwordForm: FormGroup;

private user: IUser;

constructor(private authService: AuthService,
private readonly translate: TranslateService,
private readonly notification: NotificationService,
private readonly identityService: IdentityService,
private readonly settingsService: SettingsService) { }
private readonly settingsService: SettingsService,
private readonly fb: FormBuilder,
private readonly validationService: ValidationService) { }

public async ngOnInit() {
const user = this.authService.claims();
Expand All @@ -52,6 +58,23 @@ export class UserPreferenceComponent implements OnInit {
this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x);
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);

this.passwordForm = this.fb.group({
password: [null],
currentPassword: [null, Validators.required],
confirmPassword: [null],
emailAddress: [this.user.emailAddress, Validators.email]
})

this.passwordForm.controls.password.valueChanges.subscribe(x => {
if (x) {
this.validationService.enableValidation(this.passwordForm, "confirmPassword");
}
});
this.passwordForm.controls.confirmPassword.valueChanges.subscribe(x => {
if (x) {
this.validationService.enableValidation(this.passwordForm, "password");
}
});
}

public languageSelected() {
Expand All @@ -71,4 +94,55 @@ export class UserPreferenceComponent implements OnInit {
window.location.assign(url);
});
}

public getProfileImage(): string {
let emailHash: string|Int32Array;
if (this.user.emailAddress) {
const md5 = new Md5();
emailHash = md5.appendStr(this.user.emailAddress).end();
}
var fallback = this.customizationSettings.logo ? this.customizationSettings.logo : 'https://raw.githubusercontent.com/Ombi-app/Ombi/gh-pages/img/android-chrome-512x512.png';
return `https://www.gravatar.com/avatar/${emailHash}?d=${fallback}`;
}

public updatePassword() {
if (this.passwordForm.invalid) {
this.passwordForm.markAsDirty();
return;
}

var values = this.passwordForm.value;

this.identityService.updateLocalUser({
password: values.password,
confirmNewPassword: values.confirmPassword,
emailAddress: values.emailAddress,
id: this.user.id,
currentPassword: values.currentPassword
}).subscribe(x => {
if (x.successful) {
this.notification.success("Updated your information");
this.user.emailAddress = values.emailAddress;
} else {
this.notification.error(x.errors[0]);
}
})
}


private welcomeText: string;
private setWelcomeText() {
var d = new Date();
var hour = d.getHours();

if (hour >= 0 && hour < 12) {
this.welcomeText = 'NavigationBar.MorningWelcome';
}
if (hour >= 12 && hour < 18) {
this.welcomeText = 'NavigationBar.AfternoonWelcome';
}
if (hour >= 18 && hour < 24) {
this.welcomeText = 'NavigationBar.EveningWelcome';
}
}
}
Loading

0 comments on commit 27f0d6e

Please sign in to comment.