Compare commits
2 Commits
7f97e300ff
...
7df9c61763
Author | SHA1 | Date |
---|---|---|
Benedek László | 7df9c61763 | |
Benedek László | 1f7ee78d6a |
|
@ -7,7 +7,9 @@ export const routes: Routes = [
|
||||||
{ path: 'feed', loadChildren: () => import('./feed/feed.module').then(m => m.FeedModule), canActivate: [CheckTokenCanActivate] },
|
{ path: 'feed', loadChildren: () => import('./feed/feed.module').then(m => m.FeedModule), canActivate: [CheckTokenCanActivate] },
|
||||||
{ path: 'user', loadChildren: () => import('./user/user.module').then(m => m.UserModule), canActivate: [CheckTokenCanActivate] },
|
{ path: 'user', loadChildren: () => import('./user/user.module').then(m => m.UserModule), canActivate: [CheckTokenCanActivate] },
|
||||||
{ path: 'new-post', loadChildren: () => import('./new-post/new-post.module').then(m => m.NewPostModule), canActivate: [CheckTokenCanActivate] },
|
{ path: 'new-post', loadChildren: () => import('./new-post/new-post.module').then(m => m.NewPostModule), canActivate: [CheckTokenCanActivate] },
|
||||||
{ path: '', redirectTo: 'feed', pathMatch: 'full' },
|
{ path: 'search', loadChildren: () => import('./search/search.module').then(m => m.SearchModule), canActivate: [CheckTokenCanActivate] },
|
||||||
|
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
|
||||||
|
{ path: '**', redirectTo: 'feed', pathMatch: 'full' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { SearchComponent } from './search.component';
|
||||||
|
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{ path: ':query', component: SearchComponent }
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class SearchRoutingModule {
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<app-top-menu (side)="sideMenu.nav?.toggle()"></app-top-menu>
|
||||||
|
<app-side-menu #sideMenu>
|
||||||
|
<div id="main">
|
||||||
|
<app-large-user *ngFor="let user of users" [user]="user"></app-large-user>
|
||||||
|
</div>
|
||||||
|
</app-side-menu>
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SearchComponent } from './search.component';
|
||||||
|
|
||||||
|
describe('SearchComponent', () => {
|
||||||
|
let component: SearchComponent;
|
||||||
|
let fixture: ComponentFixture<SearchComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [SearchComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SearchComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { User } from '../../model/User';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { UserService } from '../services/data/user.service';
|
||||||
|
import { SmallUserComponent } from '../shared/views/small-user/small-user.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-search',
|
||||||
|
templateUrl: './search.component.html',
|
||||||
|
styleUrl: './search.component.scss',
|
||||||
|
})
|
||||||
|
export class SearchComponent {
|
||||||
|
query: String | undefined;
|
||||||
|
users: Array<User> | undefined;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute, private userSvc: UserService) {
|
||||||
|
this.route.params.subscribe(params => { this.query = params['query'] });
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.userSvc.searchByUsername(this.query as String)
|
||||||
|
.then(users => {
|
||||||
|
this.users = users;
|
||||||
|
})
|
||||||
|
.catch(()=>{alert('failed to retrieve users')})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { SearchRoutingModule } from './search-routing.module';
|
||||||
|
import { SearchComponent } from './search.component';
|
||||||
|
import { SmallUserComponent } from '../shared/views/small-user/small-user.component';
|
||||||
|
import { TopMenuComponent } from '../shared/top-menu/top-menu.component';
|
||||||
|
import { SideMenuComponent } from '../shared/side-menu/side-menu.component';
|
||||||
|
import { LargeUserComponent } from '../shared/views/large-user/large-user.component';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
SearchComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SearchRoutingModule,
|
||||||
|
SmallUserComponent,
|
||||||
|
LargeUserComponent,
|
||||||
|
TopMenuComponent,
|
||||||
|
SideMenuComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class SearchModule { }
|
|
@ -4,6 +4,7 @@ import { AuthService } from '../auth/auth.service';
|
||||||
import { AngularFirestore, Reference } from '@angular/fire/compat/firestore';
|
import { AngularFirestore, Reference } from '@angular/fire/compat/firestore';
|
||||||
import { User } from '../../../model/User';
|
import { User } from '../../../model/User';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
import { DocumentReference } from '@angular/fire/firestore';
|
import { DocumentReference } from '@angular/fire/firestore';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
@ -53,50 +54,50 @@ export class PostService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getPosts(username: String, lenght: Number, start: Number) {
|
getPosts(username: String | undefined): Promise<Array<Post>> {
|
||||||
return new Promise<Array<Post>>((resolve, reject) => {
|
return new Promise<Array<Post>>(async (resolve, reject) => {
|
||||||
if (this.auth.checkAllowed()) {
|
|
||||||
if (username == undefined) {
|
if (!this.auth.checkAllowed())
|
||||||
this.auth.getUser().subscribe(cred => {
|
|
||||||
// get the user by id
|
|
||||||
this.afs.collection<User>('user', ref => ref.where('id', '==', cred?.uid)).valueChanges().subscribe(user => {
|
|
||||||
// get their posts
|
|
||||||
this.afs.collection<Post>('post', ref => ref.where('user', '==', this.afs.doc('/user/' + user[0].username).ref)).valueChanges({ idField: 'id' }).subscribe(posts => {
|
|
||||||
posts.forEach(post => {
|
|
||||||
// get how many likes it has
|
|
||||||
this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => {
|
|
||||||
// check if we liked this post
|
|
||||||
post.liked = likes.filter(like => (like as any).user.id == user[0].username).length != 0;
|
|
||||||
post.user = user[0] as User;
|
|
||||||
post.likes = likes.length;
|
|
||||||
})
|
|
||||||
resolve(posts)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.usersvc.getCurrentUser()
|
|
||||||
.then(currentUser => {
|
|
||||||
// get the user by username
|
|
||||||
this.afs.collection<User>('user').doc(username as string).valueChanges().subscribe(user => {
|
|
||||||
// get their posts
|
|
||||||
this.afs.collection<Post>('post', ref => ref.where('user', '==', this.afs.doc('/user/' + username).ref)).valueChanges({ idField: 'id' }).subscribe(posts => {
|
|
||||||
posts.forEach(post => {
|
|
||||||
// get how many likes it has
|
|
||||||
this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => {
|
|
||||||
post.liked = likes.filter(like => (like as any).user.id == currentUser.username).length != 0;
|
|
||||||
post.user = user as User;
|
|
||||||
post.likes = likes.length;
|
|
||||||
})
|
|
||||||
resolve(posts)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject()
|
reject()
|
||||||
|
|
||||||
|
let result: Array<Post> = new Array<Post>;
|
||||||
|
|
||||||
|
if (username == undefined) {
|
||||||
|
// /user -> currentUser
|
||||||
|
let user = await this.usersvc.getCurrentUser();
|
||||||
|
let userRef = this.afs.doc('/user/' + user.username).ref;
|
||||||
|
let posts = (await firstValueFrom(this.afs.collection<Post>('post', ref => ref.where('user', '==', userRef)).valueChanges()));
|
||||||
|
posts.forEach(async (post) => {
|
||||||
|
let likes = await firstValueFrom(this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges());
|
||||||
|
result.push({
|
||||||
|
user: user,
|
||||||
|
content: post.content,
|
||||||
|
image: post.image,
|
||||||
|
likes: likes.length,
|
||||||
|
liked: likes.filter(like => (like as any).user.id == user.username).length != 0,
|
||||||
|
id: post.id
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
resolve(result);
|
||||||
|
} else {
|
||||||
|
// /user/name
|
||||||
|
let user = await this.usersvc.getUser(username);
|
||||||
|
let userRef = this.afs.doc('/user/' + user.username).ref;
|
||||||
|
let currentUser = await this.usersvc.getCurrentUser();
|
||||||
|
let posts = (await firstValueFrom(this.afs.collection<Post>('post', ref => ref.where('user', '==', userRef)).valueChanges()));
|
||||||
|
posts.forEach(async (post) => {
|
||||||
|
let likes = await firstValueFrom(this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges());
|
||||||
|
result.push({
|
||||||
|
user: user,
|
||||||
|
content: post.content,
|
||||||
|
image: post.image,
|
||||||
|
likes: likes.length,
|
||||||
|
liked: likes.filter(like => (like as any).user.id == currentUser.username).length != 0,
|
||||||
|
id: post.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
resolve(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export class UserService {
|
||||||
return new Promise<User>((resolve, reject) => {
|
return new Promise<User>((resolve, reject) => {
|
||||||
if (this.auth.checkAllowed()) {
|
if (this.auth.checkAllowed()) {
|
||||||
if (username != undefined) {
|
if (username != undefined) {
|
||||||
this.afs.collection<User>('user', ref => ref.where('username', '==', username)).valueChanges().subscribe(data => { resolve(data[0] as User) });
|
this.afs.collection<User>('user').doc(username as string).valueChanges().subscribe(data => { resolve(data as User) });
|
||||||
} else {
|
} else {
|
||||||
this.auth.getUser().subscribe(cred => {
|
this.auth.getUser().subscribe(cred => {
|
||||||
this.afs.collection<User>('user', ref => ref.where('id', '==', cred?.uid)).valueChanges().subscribe(user => { resolve(user[0]) })
|
this.afs.collection<User>('user', ref => ref.where('id', '==', cred?.uid)).valueChanges().subscribe(user => { resolve(user[0]) })
|
||||||
|
@ -26,9 +26,9 @@ export class UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentUser(): Promise<User> {
|
getCurrentUser(): Promise<User> {
|
||||||
return new Promise<User>((resolve,reject)=>{
|
return new Promise<User>((resolve, reject) => {
|
||||||
this.auth.getUser().subscribe(user => {
|
this.auth.getUser().subscribe(user => {
|
||||||
this.afs.collection<User>('user', ref => ref.where('id', '==', user?.uid)).valueChanges().subscribe(users=>{
|
this.afs.collection<User>('user', ref => ref.where('id', '==', user?.uid)).valueChanges().subscribe(users => {
|
||||||
if (users.length != 0)
|
if (users.length != 0)
|
||||||
resolve(users[0]);
|
resolve(users[0]);
|
||||||
else
|
else
|
||||||
|
@ -49,4 +49,12 @@ export class UserService {
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchByUsername(query: String): Promise<Array<User>> {
|
||||||
|
return new Promise<Array<User>>((resolve, reject) => {
|
||||||
|
this.afs.collection<User>('user').valueChanges().subscribe(users => {
|
||||||
|
resolve(users.filter(user => user.username.includes(query as string)));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,16 @@
|
||||||
|
|
||||||
Quack
|
Quack
|
||||||
|
|
||||||
<mat-form-field>
|
<span>
|
||||||
<mat-label>Search</mat-label>
|
<mat-form-field>
|
||||||
<input matInput type="text" #search>
|
<mat-label>Search</mat-label>
|
||||||
<button matSuffix mat-icon-button (click)="search.value = ''">
|
<input matInput type="text" #search>
|
||||||
<mat-icon *ngIf="search.value != ''">close</mat-icon>
|
<button *ngIf="search.value != ''" matSuffix mat-icon-button (click)="search.value = ''">
|
||||||
|
<mat-icon>close</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-icon-button [routerLink]="'/search/'+search.value">
|
||||||
|
<mat-icon>search</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
</span>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
|
@ -3,6 +3,7 @@ mat-toolbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
height: var(--top-menu-height);
|
height: var(--top-menu-height);
|
||||||
|
padding-top: 10px;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
@ -10,9 +11,13 @@ mat-toolbar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-form-field {
|
span {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
aspect-ratio: 1;
|
||||||
|
}
|
||||||
|
|
||||||
box-shadow: 0px 3px 15px 0px rgba(0,0,0,0.4);
|
box-shadow: 0px 3px 15px 0px rgba(0,0,0,0.4);
|
||||||
}
|
}
|
|
@ -4,11 +4,12 @@ import { MatInputModule } from '@angular/material/input';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { NgIf } from '@angular/common';
|
import { NgIf } from '@angular/common';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-top-menu',
|
selector: 'app-top-menu',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [MatToolbarModule, MatInputModule, MatIconModule, MatButtonModule, NgIf],
|
imports: [MatToolbarModule, MatInputModule, MatIconModule, MatButtonModule, NgIf, RouterModule],
|
||||||
templateUrl: './top-menu.component.html',
|
templateUrl: './top-menu.component.html',
|
||||||
styleUrl: './top-menu.component.scss'
|
styleUrl: './top-menu.component.scss'
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { CommonModule } from '@angular/common';
|
||||||
import { SmallUserComponent } from '../small-user/small-user.component';
|
import { SmallUserComponent } from '../small-user/small-user.component';
|
||||||
import { Post } from '../../../../model/Post';
|
import { Post } from '../../../../model/Post';
|
||||||
import { NgIf } from '@angular/common';
|
import { NgIf } from '@angular/common';
|
||||||
import { AuthService } from '../../../services/auth/auth.service';
|
|
||||||
import { PostService } from '../../../services/data/post.service';
|
import { PostService } from '../../../services/data/post.service';
|
||||||
|
import { UserService } from '../../../services/data/user.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-post',
|
selector: 'app-post',
|
||||||
|
@ -19,11 +19,11 @@ export class PostComponent implements OnInit {
|
||||||
isOwned: boolean = false;
|
isOwned: boolean = false;
|
||||||
deleted: boolean = false;
|
deleted: boolean = false;
|
||||||
|
|
||||||
constructor(private auth: AuthService, private postSv: PostService) { }
|
constructor(private userSv: UserService, private postSv: PostService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.auth.getUser().subscribe(user => {
|
this.userSv.getCurrentUser().then(user => {
|
||||||
this.isOwned = user?.email == this.post?.user.email;
|
this.isOwned = user?.username == this.post?.user.username;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,8 @@ export class UserComponent implements OnInit{
|
||||||
|
|
||||||
constructor(private postService: PostService, private userService: UserService, private route: ActivatedRoute) { }
|
constructor(private postService: PostService, private userService: UserService, private route: ActivatedRoute) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
async ngOnInit(): Promise<void> {
|
||||||
this.userService.getUser(this.route.snapshot.params['username'])
|
this.user = await this.userService.getUser(this.route.snapshot.params['username']);
|
||||||
.then(user => { this.user = user })
|
this.posts = await this.postService.getPosts(this.route.snapshot.params['username']);
|
||||||
.catch(() => alert('failed to get user'));
|
|
||||||
|
|
||||||
this.postService.getPosts(this.route.snapshot.params['username'], 10, 0)
|
|
||||||
.then(posts => { this.posts = posts; })
|
|
||||||
.catch(()=> { alert('failed to fetch feed'); });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue