new post service and ui
This commit is contained in:
parent
b56053af8d
commit
f3c165173f
14
.firebaserc
Normal file
14
.firebaserc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"targets": {
|
||||||
|
"quack-1": {
|
||||||
|
"hosting": {
|
||||||
|
"quack": [
|
||||||
|
"quack-1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"projects": {
|
||||||
|
"default": "quack-1"
|
||||||
|
}
|
||||||
|
}
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -40,3 +40,8 @@ testem.log
|
|||||||
# System files
|
# System files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
# Firebase
|
||||||
|
.firebase
|
||||||
|
*-debug.log
|
||||||
|
.runtimeconfig.json
|
||||||
|
19
angular.json
19
angular.json
@ -96,8 +96,25 @@
|
|||||||
],
|
],
|
||||||
"scripts": []
|
"scripts": []
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"deploy": {
|
||||||
|
"builder": "@angular/fire:deploy",
|
||||||
|
"options": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "quack:build:production",
|
||||||
|
"serveTarget": "quack:serve:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "quack:build:development",
|
||||||
|
"serveTarget": "quack:serve:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
9
firebase.json
Normal file
9
firebase.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"hosting": [
|
||||||
|
{
|
||||||
|
"target": "quack",
|
||||||
|
"source": ".",
|
||||||
|
"frameworksBackend": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1301
package-lock.json
generated
1301
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
|||||||
"@angular/common": "^17.3.0",
|
"@angular/common": "^17.3.0",
|
||||||
"@angular/compiler": "^17.3.0",
|
"@angular/compiler": "^17.3.0",
|
||||||
"@angular/core": "^17.3.0",
|
"@angular/core": "^17.3.0",
|
||||||
|
"@angular/fire": "^17.0.1",
|
||||||
"@angular/forms": "^17.3.0",
|
"@angular/forms": "^17.3.0",
|
||||||
"@angular/material": "^17.3.3",
|
"@angular/material": "^17.3.3",
|
||||||
"@angular/platform-browser": "^17.3.0",
|
"@angular/platform-browser": "^17.3.0",
|
||||||
|
@ -6,7 +6,8 @@ export const routes: Routes = [
|
|||||||
{ path: 'auth', loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule) },
|
{ path: 'auth', loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule) },
|
||||||
{ 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: '', redirectTo: 'feed', pathMatch: 'full'}
|
{ path: 'new-post', loadChildren: () => import('./new-post/new-post.module').then(m => m.NewPostModule), canActivate: [CheckTokenCanActivate] },
|
||||||
|
{ path: '', redirectTo: 'feed', pathMatch: 'full' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import { ApplicationConfig } from '@angular/core';
|
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
import { routes } from './app-routing.module';
|
import { routes } from './app-routing.module';
|
||||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||||
|
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
|
||||||
|
import { getAuth, provideAuth } from '@angular/fire/auth';
|
||||||
|
import { getFirestore, provideFirestore } from '@angular/fire/firestore';
|
||||||
|
import { getStorage, provideStorage } from '@angular/fire/storage';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideRouter(routes), provideAnimationsAsync()]
|
providers: [provideRouter(routes), provideAnimationsAsync(), importProvidersFrom(provideFirebaseApp(() => initializeApp({ "projectId": "quack-1", "appId": "1:697758733170:web:433bd10dcb3566c06683eb", "storageBucket": "quack-1.appspot.com", "apiKey": "AIzaSyA4GSbuT6SNs_SPXvwVxyRyLcU_tlV9qo0", "authDomain": "quack-1.firebaseapp.com", "messagingSenderId": "697758733170" }))), importProvidersFrom(provideAuth(() => getAuth())), importProvidersFrom(provideFirestore(() => getFirestore())), importProvidersFrom(provideStorage(() => getStorage()))]
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@ import { FeedComponent } from './feed.component';
|
|||||||
import { TopMenuComponent } from '../shared/top-menu/top-menu.component';
|
import { TopMenuComponent } from '../shared/top-menu/top-menu.component';
|
||||||
import { SideMenuComponent } from '../shared/side-menu/side-menu.component';
|
import { SideMenuComponent } from '../shared/side-menu/side-menu.component';
|
||||||
import { PostComponent } from '../shared/views/post/post.component';
|
import { PostComponent } from '../shared/views/post/post.component';
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -19,7 +18,6 @@ import { MatSidenavModule } from '@angular/material/sidenav';
|
|||||||
SideMenuComponent,
|
SideMenuComponent,
|
||||||
PostComponent,
|
PostComponent,
|
||||||
NgFor,
|
NgFor,
|
||||||
MatSidenavModule
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class FeedModule { }
|
export class FeedModule { }
|
||||||
|
11
src/app/new-post/new-post-routing.module.ts
Normal file
11
src/app/new-post/new-post-routing.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { NewPostComponent } from './new-post.component';
|
||||||
|
|
||||||
|
const routes: Routes = [{ path: '', component: NewPostComponent }];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class NewPostRoutingModule { }
|
16
src/app/new-post/new-post.component.html
Normal file
16
src/app/new-post/new-post.component.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<app-top-menu (side)="sideMenu.nav?.toggle()"></app-top-menu>
|
||||||
|
<app-side-menu #sideMenu>
|
||||||
|
<div id="main">
|
||||||
|
<div class="post-container outline">
|
||||||
|
<form [formGroup]="contentGroup" (ngSubmit)="publish()">
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Content</mat-label>
|
||||||
|
<textarea formControlName="content" matInput cdkTextareaAutosize cdkAutosizeMinRows="1"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
<div class="buttons">
|
||||||
|
<button mat-button type="submit">Publish</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</app-side-menu>
|
9
src/app/new-post/new-post.component.scss
Normal file
9
src/app/new-post/new-post.component.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
mat-form-field {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
margin: 10px 10px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
margin: 0 auto 10px auto;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
23
src/app/new-post/new-post.component.spec.ts
Normal file
23
src/app/new-post/new-post.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NewPostComponent } from './new-post.component';
|
||||||
|
|
||||||
|
describe('NewPostComponent', () => {
|
||||||
|
let component: NewPostComponent;
|
||||||
|
let fixture: ComponentFixture<NewPostComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [NewPostComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(NewPostComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
27
src/app/new-post/new-post.component.ts
Normal file
27
src/app/new-post/new-post.component.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PostService } from '../services/data/post.service';
|
||||||
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-new-post',
|
||||||
|
templateUrl: './new-post.component.html',
|
||||||
|
styleUrls: ['./new-post.component.scss', '../shared/views/post/post.component.scss']
|
||||||
|
})
|
||||||
|
export class NewPostComponent {
|
||||||
|
contentGroup: FormGroup = new FormGroup({
|
||||||
|
content: new FormControl('', [Validators.required])
|
||||||
|
});
|
||||||
|
constructor(private post: PostService, private router: Router,) { }
|
||||||
|
|
||||||
|
publish() {
|
||||||
|
if (this.contentGroup.valid) {
|
||||||
|
this.post.newPost(this.contentGroup.get("content")?.value as String, "")
|
||||||
|
.then(() => { this.router.navigateByUrl("/feed") })
|
||||||
|
.catch(() => alert("failed to publish post"));
|
||||||
|
} else {
|
||||||
|
alert("content empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
src/app/new-post/new-post.module.ts
Normal file
32
src/app/new-post/new-post.module.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { NewPostRoutingModule } from './new-post-routing.module';
|
||||||
|
import { NewPostComponent } from './new-post.component';
|
||||||
|
import { TopMenuComponent } from '../shared/top-menu/top-menu.component';
|
||||||
|
import { SideMenuComponent } from '../shared/side-menu/side-menu.component';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
NewPostComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
NewPostRoutingModule,
|
||||||
|
TopMenuComponent,
|
||||||
|
SideMenuComponent,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatButtonModule,
|
||||||
|
CdkTextareaAutosize
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class NewPostModule { }
|
@ -60,10 +60,10 @@ export class PostService {
|
|||||||
return new Promise<Array<Post>>((resolve, reject) => {
|
return new Promise<Array<Post>>((resolve, reject) => {
|
||||||
// TODO: fetch feed
|
// TODO: fetch feed
|
||||||
this.auth.getToken()
|
this.auth.getToken()
|
||||||
.then( (token)=> {
|
.then((token) => {
|
||||||
resolve(this.examplePosts);
|
resolve(this.examplePosts);
|
||||||
})
|
})
|
||||||
.catch( ()=> { reject() });
|
.catch(() => { reject() });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,10 +71,32 @@ export class PostService {
|
|||||||
return new Promise<Array<Post>>((resolve, reject) => {
|
return new Promise<Array<Post>>((resolve, reject) => {
|
||||||
// TODO: fetch feed
|
// TODO: fetch feed
|
||||||
this.auth.getToken()
|
this.auth.getToken()
|
||||||
.then( (token)=> {
|
.then((token) => {
|
||||||
resolve(this.examplePosts);
|
resolve(this.examplePosts);
|
||||||
})
|
})
|
||||||
.catch( ()=> { reject() });
|
.catch(() => { reject() });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
newPost(content: String, image: String) {
|
||||||
|
return new Promise<Boolean>((resolve, reject) => {
|
||||||
|
// TODO: make post
|
||||||
|
this.auth.getToken()
|
||||||
|
.then((token) => {
|
||||||
|
this.examplePosts.push({
|
||||||
|
user: {
|
||||||
|
username: "Zámbó Jimmy",
|
||||||
|
picture: "assets/placeholder-profile-picture.png",
|
||||||
|
followed: true
|
||||||
|
},
|
||||||
|
content: content,
|
||||||
|
image: image,
|
||||||
|
likes: 0,
|
||||||
|
liked: false
|
||||||
|
})
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.catch(() => { reject() })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<mat-sidenav mode="over" [disableClose]="false" [autoFocus]="true" [fixedInViewport]="true">
|
<mat-sidenav mode="over" [disableClose]="false" [autoFocus]="true" [fixedInViewport]="true">
|
||||||
<button mat-button [routerLink]="'/feed'">Feed</button>
|
<button mat-button [routerLink]="'/feed'">Feed</button>
|
||||||
<button mat-button [routerLink]="'/user'">Profile</button>
|
<button mat-button [routerLink]="'/user'">Profile</button>
|
||||||
<button mat-button >New Post</button>
|
<button mat-button [routerLink]="'/new-post'">New Post</button>
|
||||||
<button mat-button (click)="logout()">Logout</button>
|
<button mat-button (click)="logout()">Logout</button>
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content><ng-content></ng-content></mat-sidenav-content>
|
<mat-sidenav-content><ng-content></ng-content></mat-sidenav-content>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
|
import { Component, ViewChild } from '@angular/core';
|
||||||
import { Router, RouterModule } from '@angular/router';
|
import { Router, RouterModule } from '@angular/router';
|
||||||
import { AuthService } from '../../services/auth/auth.service';
|
import { AuthService } from '../../services/auth/auth.service';
|
||||||
import { MatSidenav, MatSidenavModule } from '@angular/material/sidenav';
|
import { MatSidenav, MatSidenavModule } from '@angular/material/sidenav';
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Search</mat-label>
|
<mat-label>Search</mat-label>
|
||||||
<input matInput type="text" #search>
|
<input matInput type="text" #search>
|
||||||
<button matSuffix mat-icon-button aria-label="Clear" (click)="search.value = ''">
|
<button matSuffix mat-icon-button (click)="search.value = ''">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon *ngIf="search.value != ''">close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
@ -3,11 +3,12 @@ import { MatToolbarModule } from '@angular/material/toolbar';
|
|||||||
import { MatInputModule } from '@angular/material/input';
|
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';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-top-menu',
|
selector: 'app-top-menu',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [MatToolbarModule, MatInputModule, MatIconModule, MatButtonModule],
|
imports: [MatToolbarModule, MatInputModule, MatIconModule, MatButtonModule, NgIf],
|
||||||
templateUrl: './top-menu.component.html',
|
templateUrl: './top-menu.component.html',
|
||||||
styleUrl: './top-menu.component.scss'
|
styleUrl: './top-menu.component.scss'
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user