update and delete
This commit is contained in:
BIN
backend/blog.db
BIN
backend/blog.db
Binary file not shown.
@ -4,11 +4,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"git.schreifuchs.ch/schreifuchs/ng-blog/backend/model"
|
"git.schreifuchs.ch/schreifuchs/ng-blog/backend/model"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s Service) CreatePost(w http.ResponseWriter, r *http.Request) {
|
func (s Service) SavePost(w http.ResponseWriter, r *http.Request) {
|
||||||
var post model.Post
|
var post model.Post
|
||||||
if err := json.NewDecoder(r.Body).Decode(&post); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&post); err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
@ -37,3 +39,23 @@ func (s Service) GetAllPosts(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(&posts)
|
json.NewEncoder(w).Encode(&posts)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Service) DeletePost(w http.ResponseWriter, r *http.Request) {
|
||||||
|
idStr, ok := mux.Vars(r)["postID"]
|
||||||
|
if !ok {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := strconv.Atoi(idStr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.db.Delete(&model.Post{}, id).Error
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprint(w, err.Error())
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
@ -30,7 +30,9 @@ func main() {
|
|||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.Use(cors.HandlerForOrigin("*"))
|
r.Use(cors.HandlerForOrigin("*"))
|
||||||
r.Handle("/login", auth.Login(user, password, []byte(secret))).Methods("POST")
|
r.Handle("/login", auth.Login(user, password, []byte(secret))).Methods("POST")
|
||||||
r.Handle("/posts", auth.Authenticated([]byte(secret))(blg.CreatePost)).Methods("POST")
|
r.Handle("/posts", auth.Authenticated([]byte(secret))(blg.SavePost)).Methods("POST")
|
||||||
|
r.Handle("/posts", auth.Authenticated([]byte(secret))(blg.SavePost)).Methods("PUT")
|
||||||
|
r.Handle("/posts/{postID}", auth.Authenticated([]byte(secret))(blg.DeletePost)).Methods("DELETE")
|
||||||
r.Handle("/posts", http.HandlerFunc(blg.GetAllPosts)).Methods("GET")
|
r.Handle("/posts", http.HandlerFunc(blg.GetAllPosts)).Methods("GET")
|
||||||
r.Methods("OPTIONS").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
r.Methods("OPTIONS").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// The CORS middleware should set up the headers for you
|
// The CORS middleware should set up the headers for you
|
||||||
|
@ -5,6 +5,7 @@ import { AdminComponent } from './routes/admin/admin.component';
|
|||||||
import { LoggedInGuard } from './shared/guards/logged-in.guard';
|
import { LoggedInGuard } from './shared/guards/logged-in.guard';
|
||||||
import { PostEditorComponent } from './components/post-editor/post-editor.component';
|
import { PostEditorComponent } from './components/post-editor/post-editor.component';
|
||||||
import { CreatePostComponent } from './routes/post/create-post/create-post.component';
|
import { CreatePostComponent } from './routes/post/create-post/create-post.component';
|
||||||
|
import { UpdatePostComponent } from './routes/post/update-post/update-post.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{ path: '', component: HomeComponent },
|
{ path: '', component: HomeComponent },
|
||||||
@ -12,7 +13,11 @@ export const routes: Routes = [
|
|||||||
path: 'post',
|
path: 'post',
|
||||||
children: [
|
children: [
|
||||||
{ path: 'new', component: CreatePostComponent },
|
{ path: 'new', component: CreatePostComponent },
|
||||||
{ path: ':id', component: PostComponent },
|
{ path: ':id/edit', component: UpdatePostComponent },
|
||||||
|
{
|
||||||
|
path: ':id',
|
||||||
|
component: PostComponent,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ path: 'admin', component: AdminComponent, canActivate: [LoggedInGuard] },
|
{ path: 'admin', component: AdminComponent, canActivate: [LoggedInGuard] },
|
||||||
|
@ -12,9 +12,23 @@
|
|||||||
<section class="grid grid-cols-1 gap-5 m-5">
|
<section class="grid grid-cols-1 gap-5 m-5">
|
||||||
<article
|
<article
|
||||||
*ngFor="let post of posts()"
|
*ngFor="let post of posts()"
|
||||||
class="p-5 flex flex-col items-start rounded-s bg-white drop-shadow-md hover:drop-shadow-lg"
|
class="p-5 grid grid-cols-5 grid-rows-3 items-start rounded-s bg-white drop-shadow-md hover:drop-shadow-lg"
|
||||||
>
|
>
|
||||||
<h3 class="text-xl">{{ post.title }}</h3>
|
<h3 class="text-xl col-span-4">{{ post.title }}</h3>
|
||||||
<p><strong>TL;DR; </strong>{{ post.tldr }}</p>
|
<p class="col-start-1 col-span-4 row-start-2 row-span-2">
|
||||||
|
<strong>TL;DR; </strong>{{ post.tldr }}
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
[routerLink]="`/post/${post.id}/edit`"
|
||||||
|
class="col-start-5 row-start-1 bg-amber-400 rounded-full p-1 px-5 hover:bg-amber-500 active:bg-amber-600 transition-colors text-center"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
(click)="delete(post.id)"
|
||||||
|
class="col-start-5 row-start-3 bg-orange-400 rounded-full p-1 px-5 hover:bg-amber-500 active:bg-orange-600 transition-colors"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
@ -11,5 +11,10 @@ import { RouterLink, RouterOutlet } from '@angular/router';
|
|||||||
templateUrl: './admin.component.html',
|
templateUrl: './admin.component.html',
|
||||||
})
|
})
|
||||||
export class AdminComponent {
|
export class AdminComponent {
|
||||||
posts = inject(PostsService).getPosts();
|
private postsService = inject(PostsService);
|
||||||
|
posts = this.postsService.getPosts();
|
||||||
|
|
||||||
|
delete(id: number) {
|
||||||
|
this.postsService.deletePost(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<div class="flex items-center justify-between mb-5">
|
||||||
|
<h1 class="text-3xl">Update a Post</h1>
|
||||||
|
<button
|
||||||
|
class="bg-amber-400 rounded-full p-1 px-5 hover:bg-amber-500 active:bg-amber-600 transition-colors"
|
||||||
|
(click)="save()"
|
||||||
|
>
|
||||||
|
save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<app-post-editor [post]="post" (postChange)="post.set($event)" />
|
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UpdatePostComponent } from './update-post.component';
|
||||||
|
|
||||||
|
describe('UpdatePostComponent', () => {
|
||||||
|
let component: UpdatePostComponent;
|
||||||
|
let fixture: ComponentFixture<UpdatePostComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [UpdatePostComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(UpdatePostComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
effect,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
signal,
|
||||||
|
WritableSignal,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { PostsService } from '../../../shared/services/posts.service';
|
||||||
|
import { inject } from '@angular/core';
|
||||||
|
import { Post } from '../../../shared/interfaces/post';
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
import { PostEditorComponent } from '../../../components/post-editor/post-editor.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-update-post',
|
||||||
|
imports: [PostEditorComponent],
|
||||||
|
templateUrl: './update-post.component.html',
|
||||||
|
})
|
||||||
|
export class UpdatePostComponent implements OnInit {
|
||||||
|
@Input() id!: string;
|
||||||
|
private postsService = inject(PostsService);
|
||||||
|
private location = inject(Location);
|
||||||
|
post: WritableSignal<Post> = signal({
|
||||||
|
id: 0,
|
||||||
|
title: '',
|
||||||
|
tldr: '',
|
||||||
|
content: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const p = this.postsService.getPost(parseInt(this.id))();
|
||||||
|
if (p == undefined) {
|
||||||
|
this.location.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.post.set(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.postsService.updatePost(this.post());
|
||||||
|
this.location.back();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
effect,
|
|
||||||
inject,
|
inject,
|
||||||
Injectable,
|
Injectable,
|
||||||
Signal,
|
Signal,
|
||||||
@ -37,6 +36,15 @@ export class PostsService {
|
|||||||
return computed(() => this.posts().get(id));
|
return computed(() => this.posts().get(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deletePost(id: number) {
|
||||||
|
this.http.delete(`${environment.apiRoot}/posts/${id}`).subscribe(() => {
|
||||||
|
this.posts.update((p) => {
|
||||||
|
p.delete(id);
|
||||||
|
return new Map(p);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
createPost(post: Post) {
|
createPost(post: Post) {
|
||||||
this.http
|
this.http
|
||||||
.post<Post>(`${environment.apiRoot}/posts`, post)
|
.post<Post>(`${environment.apiRoot}/posts`, post)
|
||||||
@ -44,4 +52,11 @@ export class PostsService {
|
|||||||
this.posts.update((p) => new Map(p.set(res.id, res)));
|
this.posts.update((p) => new Map(p.set(res.id, res)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
updatePost(post: Post) {
|
||||||
|
this.http
|
||||||
|
.put<Post>(`${environment.apiRoot}/posts`, post)
|
||||||
|
.subscribe((res) => {
|
||||||
|
this.posts.update((p) => new Map(p.set(res.id, res)));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user