Skip to content

Commit fd2c903

Browse files
authored
Merge pull request #38 from AnguHashBlog/main
Multiple Issues - features and fixes
2 parents 7b833a2 + 18793db commit fd2c903

31 files changed

+811
-426
lines changed

angular-primeng-app/src/app/components/footer/footer.component.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Component } from '@angular/core';
1+
import { Component, inject } from '@angular/core';
22
import { BlogService } from '../../services/blog.service';
33
import { Subscription } from 'rxjs';
44

55
import { ToolbarModule } from 'primeng/toolbar';
6+
import { BlogInfo } from '../../models/blog-info';
67

78
@Component({
89
selector: 'app-footer',
@@ -12,17 +13,17 @@ import { ToolbarModule } from 'primeng/toolbar';
1213
styleUrl: './footer.component.scss'
1314
})
1415
export class FooterComponent {
16+
blogURL!: string;
17+
blogInfo!: BlogInfo;
1518
blogName = '';
16-
1719
date = new Date().getFullYear();
20+
blogService: BlogService = inject(BlogService);
1821

1922
private querySubscription?: Subscription;
2023

21-
constructor(private blogService: BlogService) {
22-
}
23-
2424
ngOnInit() {
25-
this.querySubscription = this.blogService.getBlogInfo()
25+
this.blogURL = this.blogService.getBlogURL();
26+
this.querySubscription = this.blogService.getBlogInfo(this.blogURL)
2627
.subscribe((data) => this.blogName = data.title);
2728
}
2829

angular-primeng-app/src/app/components/header/header.component.html

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ <h1>{{ blogName }}</h1>
66
</a>
77
<div class="controls">
88
<app-search-dialog [blogId]="blogId"></app-search-dialog>
9+
<app-settings-dialog></app-settings-dialog>
910
<p-inputSwitch [(ngModel)]="checked" (click)="onThemeChange(checked ? 'dark' : 'light')" id="theme-switch"></p-inputSwitch>
1011
</div>
1112
</div>
@@ -27,7 +28,7 @@ <h1>{{ blogName }}</h1>
2728
</div>
2829
</div>
2930
<div class="follow">
30-
<p-button (click)="showDialog()" label="Follow" [raised]="true"></p-button>
31+
<app-follow-dialog></app-follow-dialog>
3132
</div>
3233
</div>
3334
<div class="toolbar-row">
@@ -38,12 +39,3 @@ <h1>{{ blogName }}</h1>
3839
</div>
3940
</div>
4041
</p-toolbar>
41-
42-
<p-dialog [(visible)]="visible" [style]="{width: '27vw'}">
43-
<div class="logo-wrapper">
44-
<img class="logo" src="/assets/images/anguhashblog-logo-purple-bgr.jpg" alt="">
45-
</div>
46-
<h3>Hey, 👋 sign up or sign in to interact.</h3>
47-
<a class="button" href="https://hashnode.com/" target="_blank" rel="noopener noreferrer"><img src="/assets/images/hashnode-logo-white.png" alt="Sign in">Sign in with Hashnode</a>
48-
<p>This blog is powered by <a class="link" href="https://hashnode.com/" target="_blank" rel="noopener noreferrer">Hashnode</a>. To interact with the content on this blog, please log in through Hashnode.</p>
49-
</p-dialog>

angular-primeng-app/src/app/components/header/header.component.scss

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -64,59 +64,8 @@ p-toolbar {
6464
}
6565
}
6666

67-
p-dialog {
68-
h3 {
69-
font-size: 1.1rem;
70-
font-weight: 400;
71-
text-align: center;
72-
}
73-
74-
.logo-wrapper {
75-
display: flex;
76-
align-items: center;
77-
justify-content: center;
78-
79-
.logo {
80-
width: 5rem;
81-
height: 5rem;
82-
margin: 1rem;
83-
border-radius: 50%;
84-
}
85-
}
86-
87-
.button {
88-
display: flex;
89-
align-items: center;
90-
justify-content: center;
91-
background-color: #2563eb;
92-
color: #fff;
93-
font-size: 1.1rem;
94-
padding: 0.7rem 3rem;
95-
margin: 2rem 1rem;
96-
border: none;
97-
border-radius: 3rem;
98-
99-
img {
100-
width: 1.5rem;
101-
height: 1.5rem;
102-
margin-right: 0.5rem;
103-
}
104-
}
105-
106-
.link {
107-
color: #2563eb;
108-
font-size: 0.8.5rem;
109-
margin: 0;
110-
}
111-
112-
p {
113-
font-size: 0.8rem;
114-
text-align: center;
115-
}
116-
}
117-
11867
.controls {
11968
display: flex;
12069
align-items: center;
121-
gap: 10px;
70+
gap: 0.5rem;
12271
}
Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
1-
import { Component, inject, OnInit } from "@angular/core";
1+
import { Component, inject, OnDestroy, OnInit } from "@angular/core";
22
import { FormsModule } from "@angular/forms";
33
import { ThemeService } from "../../services/theme.service";
44
import { BlogService } from "../../services/blog.service";
55
import { AsyncPipe, KeyValuePipe } from "@angular/common";
66
import { RouterLink } from "@angular/router";
77
import { BlogInfo, BlogLinks } from "../../models/blog-info";
88
import { SeriesList } from "../../models/post";
9+
import { SearchDialogComponent } from "../../partials/search-dialog/search-dialog.component";
10+
import { Subscription } from "rxjs";
911

1012
import { ToolbarModule } from "primeng/toolbar";
1113
import { ButtonModule } from "primeng/button";
1214
import { InputSwitchModule } from "primeng/inputswitch";
1315
import { DialogModule } from "primeng/dialog";
14-
import { SearchDialogComponent } from "../../partials/search-dialog/search-dialog.component";
16+
import { SettingsDialogComponent } from "../../partials/settings-dialog/settings-dialog.component";
17+
import { FollowDialogComponent } from "../../partials/follow-dialog/follow-dialog.component";
1518

1619
@Component({
1720
selector: "app-header",
1821
standalone: true,
1922
imports: [
2023
AsyncPipe,
2124
SearchDialogComponent,
25+
SettingsDialogComponent,
26+
FollowDialogComponent,
2227
ButtonModule,
2328
FormsModule,
2429
InputSwitchModule,
@@ -30,10 +35,12 @@ import { SearchDialogComponent } from "../../partials/search-dialog/search-dialo
3035
templateUrl: "./header.component.html",
3136
styleUrl: "./header.component.scss",
3237
})
33-
export class HeaderComponent implements OnInit {
34-
blogInfo!: BlogInfo;
38+
export class HeaderComponent implements OnInit, OnDestroy {
39+
blogURL!: string;
40+
blogInfo!: BlogInfo;
3541
blogId: string = "";
36-
blogName: string = "";
42+
blogName: string = "";
43+
blogImage: string = "/assets/images/anguhashblog-logo-purple-bgr.jpg";
3744
blogSocialLinks!: BlogLinks;
3845
checked: boolean = true;
3946
selectedTheme: string = "dark";
@@ -42,19 +49,38 @@ export class HeaderComponent implements OnInit {
4249
themeService: ThemeService = inject(ThemeService);
4350
blogService: BlogService = inject(BlogService);
4451

52+
private querySubscription?: Subscription;
53+
4554
ngOnInit(): void {
46-
this.blogService
47-
.getBlogInfo()
55+
this.blogURL = this.blogService.getBlogURL();
56+
this.querySubscription = this.blogService
57+
.getBlogInfo(this.blogURL)
4858
.subscribe((data) => {
4959
this.blogInfo = data;
50-
this.blogId = this.blogInfo.id;
60+
this.blogId = this.blogInfo.id;
5161
this.blogName = this.blogInfo.title;
62+
if (this.blogInfo.isTeam && this.blogInfo.favicon) {
63+
this.blogImage = this.blogInfo.favicon;
64+
} else {
65+
this.blogImage = '/assets/images/anguhashblog-logo-purple-bgr.jpg'
66+
}
67+
if (!this.blogInfo.isTeam) {
68+
this.blogService
69+
.getAuthorInfo(this.blogURL)
70+
.subscribe((data) => {
71+
if (data.profilePicture) {
72+
this.blogImage = data.profilePicture;
73+
} else {
74+
this.blogImage = '/assets/images/anguhashblog-logo-purple-bgr.jpg'
75+
}
76+
});
77+
}
5278
const { __typename, ...links } = data.links;
5379
this.blogSocialLinks = links;
5480
});
5581

5682
this.blogService
57-
.getSeriesList()
83+
.getSeriesList(this.blogURL)
5884
.subscribe((data) => {
5985
this.seriesList = data;
6086
});
@@ -65,7 +91,7 @@ export class HeaderComponent implements OnInit {
6591
this.themeService.setTheme(theme);
6692
}
6793

68-
showDialog() {
69-
this.visible = true;
94+
ngOnDestroy(): void {
95+
this.querySubscription?.unsubscribe();
7096
}
7197
}

angular-primeng-app/src/app/components/post-details/post-details.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ <h1 class="title">{{ post.title }}</h1>
3030
</div>
3131
</div>
3232
</div>
33-
<div class="content" [innerHTML]="sanitizeHtml(post.content.html)"></div>
33+
<div class="content" [innerHTML]="post.content.html | sanitizerHtml" youtubeVideoEmbed></div>
3434
</article>
3535
}
3636
<app-footer></app-footer>

angular-primeng-app/src/app/components/post-details/post-details.component.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@
7575
.content {
7676
font-size: 1rem;
7777
line-height: 1.5rem;
78+
79+
iframe {
80+
width: 100%;
81+
height: calc(50vw * 0.5625);
82+
}
7883
}
7984
}
8085

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Component, inject, Input, OnDestroy, OnInit } from "@angular/core";
22
import { BlogService } from "../../services/blog.service";
33
import { AsyncPipe, DatePipe } from "@angular/common";
4-
import { Post } from "../../models/post";
4+
import { Post, SeriesList } from "../../models/post";
55
import { Observable, Subscription } from "rxjs";
6-
import { ActivatedRoute, RouterLink } from "@angular/router";
7-
import { BlogInfo } from "../../models/blog-info";
6+
import { RouterLink } from "@angular/router";
7+
import { BlogInfo, BlogLinks } from "../../models/blog-info";
88
import { FormsModule } from "@angular/forms";
99
import { SidenavComponent } from "../sidenav/sidenav.component";
1010
import { SearchDialogComponent } from "../../partials/search-dialog/search-dialog.component";
@@ -15,17 +15,20 @@ import { TagModule } from "primeng/tag";
1515
import { ToolbarModule } from "primeng/toolbar";
1616
import { ButtonModule } from "primeng/button";
1717
import { InputSwitchModule } from "primeng/inputswitch";
18-
import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
18+
import { SanitizerHtmlPipe } from "../../pipes/sanitizer-html.pipe";
19+
import { YoutubeVideoEmbedDirective } from "../../directives/youtube-video-embed.directive";
1920

2021
@Component({
2122
selector: "app-post-details",
2223
standalone: true,
2324
imports: [
2425
DatePipe,
2526
AsyncPipe,
27+
SanitizerHtmlPipe,
2628
RouterLink,
2729
SidenavComponent,
2830
FooterComponent,
31+
YoutubeVideoEmbedDirective,
2932
FormsModule,
3033
TagModule,
3134
ToolbarModule,
@@ -36,36 +39,47 @@ import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
3639
templateUrl: "./post-details.component.html",
3740
styleUrl: "./post-details.component.scss",
3841
})
39-
export class PostDetailsComponent implements OnInit {
40-
post$!: Observable<Post>;
41-
blogInfo!: BlogInfo;
42-
blogId: string = "";
43-
blogName: string = "";
42+
export class PostDetailsComponent implements OnInit, OnDestroy {
4443
checked: boolean = true;
4544
selectedTheme: string = "dark";
45+
blogURL!: string;
46+
blogInfo!: BlogInfo;
47+
blogId: string = "";
48+
blogName: string = "";
49+
blogSocialLinks!: BlogLinks;
50+
seriesList!: SeriesList[];
51+
post$!: Observable<Post>;
4652
themeService: ThemeService = inject(ThemeService);
47-
private sanitizer: DomSanitizer = inject(DomSanitizer);
4853
private blogService: BlogService = inject(BlogService);
54+
private querySubscription?: Subscription;
4955

50-
@Input({ required: true })
51-
set slug(slug: string) {
52-
this.post$ = this.blogService.getSinglePost(slug);
53-
}
54-
55-
ngOnInit(): void {
56-
this.blogService.getBlogInfo().subscribe((data) => {
57-
this.blogInfo = data;
58-
this.blogId = this.blogInfo.id;
59-
this.blogName = this.blogInfo.title;
60-
});
61-
}
56+
@Input({ required: true }) slug!: string;
6257

63-
sanitizeHtml(html: string): SafeHtml {
64-
return this.sanitizer.bypassSecurityTrustHtml(html);
58+
ngOnInit(): void {
59+
this.blogURL = this.blogService.getBlogURL();
60+
this.querySubscription = this.blogService
61+
.getBlogInfo(this.blogURL)
62+
.subscribe((data) => {
63+
this.blogInfo = data;
64+
this.blogId = this.blogInfo.id;
65+
this.blogName = this.blogInfo.title;
66+
const { __typename, ...links } = data.links;
67+
this.blogSocialLinks = links;
68+
});
69+
this.post$ = this.blogService.getSinglePost(this.blogURL,this.slug);
70+
this.querySubscription = this.blogService
71+
.getSeriesList(this.blogURL)
72+
.subscribe((data) => {
73+
this.seriesList = data;
74+
});
6575
}
6676

6777
onThemeChange(theme: string): void {
6878
this.selectedTheme = theme;
6979
this.themeService.setTheme(theme);
7080
}
81+
82+
ngOnDestroy(): void {
83+
this.querySubscription?.unsubscribe();
84+
}
7185
}
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<div class="posts-view">
22
<div class="cards-wrapper grid">
33
@for (post of posts$ | async; track post.id) {
4-
<p-card class="post-card" header="{{ post.title }}" (click)="navigateToPost(post.slug)">
5-
<ng-template pTemplate="header">
6-
<img class="card-image" [src]="post.coverImage.url" [alt]="post.title + ' image'" />
7-
</ng-template>
8-
</p-card>
4+
<a [routerLink]="['post', post.slug]">
5+
<p-card class="post-card" header="{{ post.title }}">
6+
<ng-template pTemplate="header">
7+
<img class="card-image" [src]="post.coverImage.url" [alt]="post.title + ' image'" />
8+
</ng-template>
9+
</p-card>
10+
</a>
911
}
1012
</div>
1113
</div>

angular-primeng-app/src/app/components/posts/posts.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
flex-wrap: wrap;
99
justify-content: center;
1010
margin: 2rem 1rem;
11+
12+
.post-card {
13+
display: flex;
14+
}
1115
}
1216
}
1317

0 commit comments

Comments
 (0)