Skip to content

Commit

Permalink
Added support for Gravatar images on user accounts [#684]
Browse files Browse the repository at this point in the history
 * Changed the user icon in the sidebar with their gravatar image.
 * Added the gravatar image to the account edit page.
  • Loading branch information
mcpierce committed Jun 27, 2021
1 parent 066c42f commit 0fc8154
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 99 deletions.
1 change: 1 addition & 0 deletions comixed-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"lodash": "^4.17.21",
"messageformat": "^2.3.0",
"ngx-filesaver": "^11.0.0",
"ngx-gravatar": "^11.0.0",
"ngx-translate-messageformat-compiler": "^4.8.0",
"ngx-translate-multi-http-loader": "^3.0.0",
"normalize-url": "^4.5.1",
Expand Down
4 changes: 3 additions & 1 deletion comixed-web/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import { CollectionsModule } from '@app/collections/collections.module';
import { LastReadModule } from '@app/last-read/last-read.module';
import { ComicFileModule } from '@app/comic-file/comic-file.module';
import { ComicBookModule } from '@app/comic-book/comic-book.module';
import { GravatarModule } from 'ngx-gravatar';

@NgModule({
declarations: [
Expand Down Expand Up @@ -128,7 +129,8 @@ import { ComicBookModule } from '@app/comic-book/comic-book.module';
MatSelectModule,
FlexLayoutModule,
MatSidenavModule,
MatListModule
MatListModule,
GravatarModule
],
providers: [
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@
<mat-icon>navigate_before</mat-icon>
</button>
{{
"comic-book.label.page-title"
| translate: { which: pageIndex + 1, count: comic.pages.length }
"comic-book.label.page-title"
| translate: { which: pageIndex + 1, count: comic.pages.length }
}}
<button
mat-icon-button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
[matTooltip]="'navigation.tooltip.account' | translate"
[routerLink]="'/account'"
>
<mat-icon>person</mat-icon>
<img ngxGravatar [alt]="user.email" [email]="user.email" />
</button>

<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { MatSelectModule } from '@angular/material/select';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { BehaviorSubject } from 'rxjs';
import { ComicViewMode } from '@app/library/models/comic-view-mode.enum';
import { GravatarModule } from 'ngx-gravatar';

describe('NavigationBarComponent', () => {
const USER = USER_ADMIN;
Expand All @@ -75,6 +76,7 @@ describe('NavigationBarComponent', () => {
RouterTestingModule.withRoutes([{ path: '*', redirectTo: '' }]),
TranslateModule.forRoot(),
LoggerModule.forRoot(),
GravatarModule,
MatDialogModule,
MatMenuModule,
MatIconModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<img
ngxGravatar
[alt]="user.email"
[email]="user.email"
[size]="imageSize"
[round]="false"
/>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UserCardComponent } from './user-card.component';
import { LoggerModule } from '@angular-ru/logger';
import { USER_READER } from '@app/user/user.fixtures';
import { GravatarModule } from 'ngx-gravatar';

describe('UserCardComponent', () => {
const USER = USER_READER;

let component: UserCardComponent;
let fixture: ComponentFixture<UserCardComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [UserCardComponent],
imports: [LoggerModule.forRoot(), GravatarModule]
}).compileComponents();

fixture = TestBed.createComponent(UserCardComponent);
component = fixture.componentInstance;
component.user = USER;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { Component, Input, OnInit } from '@angular/core';
import { User } from '@app/user/models/user';
import { LoggerService } from '@angular-ru/logger';

@Component({
selector: 'cx-user-card',
templateUrl: './user-card.component.html',
styleUrls: ['./user-card.component.scss']
})
export class UserCardComponent implements OnInit {
@Input() user: User;
@Input() imageSize = 'auto';

constructor(private logger: LoggerService) {}

ngOnInit(): void {}
}
Original file line number Diff line number Diff line change
@@ -1,101 +1,107 @@
<mat-toolbar class="cx-light-dark-background">
<div class="cx-spacer"></div>
<button
id="save-button"
class="cx-action-button"
mat-icon-button
color="primary"
[disabled]="!userForm.valid"
(click)="onSaveChanges()"
>
<mat-icon>save</mat-icon>
</button>
<button
id="reset-button"
class="cx-action-button"
mat-icon-button
color="warn"
[disabled]="!userForm.dirty"
(click)="onResetChanges()"
>
<mat-icon>undo</mat-icon>
</button>
</mat-toolbar>
<form [formGroup]="userForm">
<mat-card *ngIf="!!user">
<mat-card-title>
{{ "user.edit-current-user.page-title" | translate }}
</mat-card-title>
<mat-card-subtitle>{{ user.email }}</mat-card-subtitle>
<mat-card-content>
<mat-form-field class="cx-width-100" appearance="fill">
<mat-label>
{{ "user.edit-current-user.label.email" | translate }}
</mat-label>
<input
id="email-input"
matInput
type="email"
formControlName="email"
required
/>
</mat-form-field>
<mat-form-field class="cx-width-100" appearance="fill">
<mat-label>
{{ "user.edit-current-user.label.password" | translate }}
</mat-label>
<input
id="password-input"
matInput
type="password"
formControlName="password"
(keyup)="onPasswordChanged()"
/>
<mat-error>
<span *ngIf="userForm.controls.password.errors?.minLength">
{{
"validation.value-too-short"
| translate
: {
length:
userForm.controls.password.errors.minLength
.requiredLength
}
}}
</span>
<span *ngIf="userForm.controls.password.errors?.maxLength">
{{
"validation.value-too-long"
| translate
: {
length:
userForm.controls.password.errors.maxLength
.requiredLength
}
}}
</span>
</mat-error>
</mat-form-field>
<mat-form-field class="cx-width-100" appearance="fill">
<mat-label>
{{ "user.edit-current-user.label.password-verify" | translate }}
</mat-label>
<input
id="password-verify-input"
matInput
type="password"
formControlName="passwordVerify"
/>
<mat-error>
<span *ngIf="userForm.errors?.passwordsDontMatch">
{{
"user.edit-current-user.validation.passwords-dont-match"
| translate
}}
</span>
</mat-error>
</mat-form-field>
<div class="cx-horizontal-container">
<div class="cx-grow-1 cx-padding-5">
<mat-form-field class="cx-width-100" appearance="fill">
<mat-label>
{{ "user.edit-current-user.label.email" | translate }}
</mat-label>
<input
id="email-input"
matInput
type="email"
formControlName="email"
required
/>
</mat-form-field>
<mat-form-field class="cx-width-100" appearance="fill">
<mat-label>
{{ "user.edit-current-user.label.password" | translate }}
</mat-label>
<input
id="password-input"
matInput
type="password"
formControlName="password"
(keyup)="onPasswordChanged()"
/>
<mat-error>
<span *ngIf="userForm.controls.password.errors?.minLength">
{{
"validation.value-too-short"
| translate
: {
length:
userForm.controls.password.errors.minLength
.requiredLength
}
}}
</span>
<span *ngIf="userForm.controls.password.errors?.maxLength">
{{
"validation.value-too-long"
| translate
: {
length:
userForm.controls.password.errors.maxLength
.requiredLength
}
}}
</span>
</mat-error>
</mat-form-field>
<mat-form-field class="cx-width-100" appearance="fill">
<mat-label>
{{ "user.edit-current-user.label.password-verify" | translate }}
</mat-label>
<input
id="password-verify-input"
matInput
type="password"
formControlName="passwordVerify"
/>
<mat-error>
<span *ngIf="userForm.errors?.passwordsDontMatch">
{{
"user.edit-current-user.validation.passwords-dont-match"
| translate
}}
</span>
</mat-error>
</mat-form-field>
</div>
<div class="cx-grow-0 cx-border-primary-1 cx-padding-5">
<cx-user-card [user]="user" [imageSize]="imageSize"></cx-user-card>
</div>
</div>
</mat-card-content>
<mat-card-actions>
<button
id="save-button"
class="cx-action-button"
mat-raised-button
color="primary"
[disabled]="!userForm.valid"
(click)="onSaveChanges()"
>
<mat-icon>save</mat-icon>
<mat-label>{{ "button.save" | translate }}</mat-label>
</button>
<button
id="reset-button"
class="cx-action-button"
mat-raised-button
color="warn"
[disabled]="!userForm.dirty"
(click)="onResetChanges()"
>
<mat-icon>undo</mat-icon>
<mat-label>{{ "button.reset" | translate }}</mat-label>
</button>
</mat-card-actions>
</mat-card>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import { saveCurrentUser } from '@app/user/actions/user.actions';
import { Confirmation } from '@app/core/models/confirmation';
import { TitleService } from '@app/core/services/title.service';
import { ConfirmationService } from '@app/core/services/confirmation.service';
import { MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { UserCardComponent } from '@app/user/components/user-card/user-card.component';

describe('AccountEditPageComponent', () => {
const USER = USER_READER;
Expand All @@ -50,13 +53,15 @@ describe('AccountEditPageComponent', () => {

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AccountEditPageComponent],
declarations: [AccountEditPageComponent, UserCardComponent],
imports: [
FormsModule,
ReactiveFormsModule,
LoggerModule.forRoot(),
TranslateModule.forRoot(),
MatDialogModule
MatDialogModule,
MatIconModule,
MatToolbarModule
],
providers: [
provideMockStore({ initialState }),
Expand Down

0 comments on commit 0fc8154

Please sign in to comment.