diff --git a/backend/blog.db b/backend/blog.db
index 15e0e60..0f85c74 100644
Binary files a/backend/blog.db and b/backend/blog.db differ
diff --git a/backend/blog/controller.go b/backend/blog/controller.go
index 820829e..adceb86 100644
--- a/backend/blog/controller.go
+++ b/backend/blog/controller.go
@@ -4,11 +4,13 @@ import (
"encoding/json"
"fmt"
"net/http"
+ "strconv"
"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
if err := json.NewDecoder(r.Body).Decode(&post); err != nil {
w.WriteHeader(http.StatusBadRequest)
@@ -37,3 +39,23 @@ func (s Service) GetAllPosts(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(&posts)
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)
+}
diff --git a/backend/main.go b/backend/main.go
index 44b89b8..c6bd50b 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -30,7 +30,9 @@ func main() {
r := mux.NewRouter()
r.Use(cors.HandlerForOrigin("*"))
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.Methods("OPTIONS").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// The CORS middleware should set up the headers for you
diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts
index a32cbff..4b95202 100644
--- a/frontend/src/app/app.routes.ts
+++ b/frontend/src/app/app.routes.ts
@@ -5,6 +5,7 @@ import { AdminComponent } from './routes/admin/admin.component';
import { LoggedInGuard } from './shared/guards/logged-in.guard';
import { PostEditorComponent } from './components/post-editor/post-editor.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 = [
{ path: '', component: HomeComponent },
@@ -12,7 +13,11 @@ export const routes: Routes = [
path: 'post',
children: [
{ path: 'new', component: CreatePostComponent },
- { path: ':id', component: PostComponent },
+ { path: ':id/edit', component: UpdatePostComponent },
+ {
+ path: ':id',
+ component: PostComponent,
+ },
],
},
{ path: 'admin', component: AdminComponent, canActivate: [LoggedInGuard] },
diff --git a/frontend/src/app/routes/admin/admin.component.html b/frontend/src/app/routes/admin/admin.component.html
index 3a12edd..29d1db0 100644
--- a/frontend/src/app/routes/admin/admin.component.html
+++ b/frontend/src/app/routes/admin/admin.component.html
@@ -12,9 +12,23 @@
- {{ post.title }}
- TL;DR; {{ post.tldr }}
+ {{ post.title }}
+
+ TL;DR; {{ post.tldr }}
+
+
+ Edit
+
+
diff --git a/frontend/src/app/routes/admin/admin.component.ts b/frontend/src/app/routes/admin/admin.component.ts
index 3a0bebe..21256ee 100644
--- a/frontend/src/app/routes/admin/admin.component.ts
+++ b/frontend/src/app/routes/admin/admin.component.ts
@@ -11,5 +11,10 @@ import { RouterLink, RouterOutlet } from '@angular/router';
templateUrl: './admin.component.html',
})
export class AdminComponent {
- posts = inject(PostsService).getPosts();
+ private postsService = inject(PostsService);
+ posts = this.postsService.getPosts();
+
+ delete(id: number) {
+ this.postsService.deletePost(id);
+ }
}
diff --git a/frontend/src/app/routes/post/update-post/update-post.component.html b/frontend/src/app/routes/post/update-post/update-post.component.html
new file mode 100644
index 0000000..cebe496
--- /dev/null
+++ b/frontend/src/app/routes/post/update-post/update-post.component.html
@@ -0,0 +1,10 @@
+
+
Update a Post
+
+
+
diff --git a/frontend/src/app/routes/post/update-post/update-post.component.spec.ts b/frontend/src/app/routes/post/update-post/update-post.component.spec.ts
new file mode 100644
index 0000000..46e22f1
--- /dev/null
+++ b/frontend/src/app/routes/post/update-post/update-post.component.spec.ts
@@ -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;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [UpdatePostComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(UpdatePostComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/routes/post/update-post/update-post.component.ts b/frontend/src/app/routes/post/update-post/update-post.component.ts
new file mode 100644
index 0000000..6e1b7e2
--- /dev/null
+++ b/frontend/src/app/routes/post/update-post/update-post.component.ts
@@ -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 = 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();
+ }
+}
diff --git a/frontend/src/app/shared/services/posts.service.ts b/frontend/src/app/shared/services/posts.service.ts
index 82f3362..4e56e17 100644
--- a/frontend/src/app/shared/services/posts.service.ts
+++ b/frontend/src/app/shared/services/posts.service.ts
@@ -1,7 +1,6 @@
import { HttpClient } from '@angular/common/http';
import {
computed,
- effect,
inject,
Injectable,
Signal,
@@ -37,6 +36,15 @@ export class PostsService {
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) {
this.http
.post(`${environment.apiRoot}/posts`, post)
@@ -44,4 +52,11 @@ export class PostsService {
this.posts.update((p) => new Map(p.set(res.id, res)));
});
}
+ updatePost(post: Post) {
+ this.http
+ .put(`${environment.apiRoot}/posts`, post)
+ .subscribe((res) => {
+ this.posts.update((p) => new Map(p.set(res.id, res)));
+ });
+ }
}