adding raw text editor for making content

This commit is contained in:
hilmanski
2023-10-03 11:17:02 +08:00
parent ac5a8ef5b8
commit 09453fe44d
4 changed files with 151 additions and 86 deletions
+11
View File
@@ -11,6 +11,17 @@ def get_post(post_id: int):
post = session.get(Post, post_id)
return post
def update_post(post_id: int, data: dict):
session = Session(engine)
post = session.get(Post, post_id)
for key, value in data.items():
setattr(post, key, value)
session.add(post)
session.commit()
session.refresh(post)
return post
def remove_post(post_id: int):
session = Session(engine)
post = session.get(Post, post_id)
+7 -2
View File
@@ -1,5 +1,5 @@
import os
import random
# import random
from fastapi import FastAPI
from dotenv import load_dotenv
from serpapi import GoogleSearch
@@ -16,7 +16,7 @@ from nltk.util import bigrams, trigrams
import operator
import nltk
from .db.post import add_post, save_links, get_post, get_all_post, remove_post
from .db.post import add_post, save_links, get_post, get_all_post, remove_post, update_post
@@ -98,6 +98,11 @@ def getPost(post_id: str):
post = get_post(post_id)
return post
@app.put('/posts/{post_id}')
def updatePost(post_id: str, data: dict):
post = update_post(post_id, data)
return post
@app.delete('/posts/{post_id}')
def deletePost(post_id: str):
post = remove_post(post_id)
+92 -84
View File
@@ -1,5 +1,6 @@
import Link from "next/link";
import Terms from "@/components/Terms";
import TextEditor from "@/components/TextEditor";
async function getData(id: string) {
const res = await fetch(`http://localhost:8000/posts/${id}`)
@@ -23,10 +24,20 @@ export default async function Editor({
const data = await getData(params.id);
const searchResult = data.search_result
return (
<div className="my-10 max-w-7xl mx-auto">
<div className="flex justify-between mb-5">
<p className="text-xl">
Title: {data.title}
</p>
<Link href="/" className="underline">
Home
</Link>
</div>
<section className="fixed">
<p>Menu</p>
@@ -39,98 +50,95 @@ export default async function Editor({
</div>
</section>
<section className="ml-[200px] w-8/12">
<section className="flex justify-between">
<div className="flex justify-between">
<p className="text-xl">
Title: {data.title}
</p>
<Link href="/" className="underline">
Home
</Link>
</div>
<section className="ml-[200px] w-3/12 max-h-screen overflow-y-scroll">
{
searchResult.answer_box && (
<section
id="answer-box"
className="my-5 p-3 border border-emerald-600 text-sm">
<h3 className="text-emerald-700 ">Answer Box (Featued Snippet)</h3>
<p className="italic">
{
searchResult.answer_box.snippet
}
</p>
{
searchResult.answer_box.list && (
<div>
<p className="text-bold italic">Info: Features snippet is a list</p>
{
searchResult.answer_box && (
<section
id="answer-box"
className="my-5 p-3 border border-emerald-600 text-sm">
<h3 className="text-emerald-700 ">Answer Box (Featued Snippet)</h3>
<p className="italic">
{
searchResult.answer_box.list.map((item, index) => {
return (
<div key={index}>
<p>{item}</p>
</div>
)
})
searchResult.answer_box.snippet
}
</div>
)
}
</p>
<p>
<a className="text-sky-700"
href={searchResult.answer_box.link}>
source
</a>
</p>
</section>
)
}
{
searchResult.related_questions.length > 0 && (
<section
id="related-questions"
className="my-5 p-3 border border-emerald-600 text-sm">
<h3 className="text-emerald-700 mb-2">Related Questions</h3>
{
searchResult.related_questions.map((item, index) => {
return (
<div key={index} className="mb-1">
<p className="font-bold"> {item.question} </p>
<p className="italic"> {item.snippet} </p>
</div>
{
searchResult.answer_box.list && (
<div>
<p className="text-bold italic">Info: Features snippet is a list</p>
{
searchResult.answer_box.list.map((item, index) => {
return (
<div key={index}>
<p>{item}</p>
</div>
)
})
}
</div>
)
})
}
</section>
)
}
}
{
searchResult.related_searches.length > 0 && (
<section
id="related-searches"
className="my-5 p-3 border border-emerald-600 text-sm">
<h3 className="text-emerald-700 mb-2">Related Searches</h3>
{
searchResult.related_searches.map((item, index) => {
return (
<div key={index} className="mb-1">
<p className=""> {item.query} </p>
</div>
)
})
}
</section>
)
}
<p>
<a className="text-sky-700"
href={searchResult.answer_box.link}>
source
</a>
</p>
</section>
)
}
<Terms id={params.id} />
{
searchResult.related_questions.length > 0 && (
<section
id="related-questions"
className="my-5 p-3 border border-emerald-600 text-sm">
<h3 className="text-emerald-700 mb-2">Related Questions</h3>
{
searchResult.related_questions.map((item, index) => {
return (
<div key={index} className="mb-1">
<p className="font-bold"> {item.question} </p>
<p className="italic"> {item.snippet} </p>
</div>
)
})
}
</section>
)
}
{
searchResult.related_searches.length > 0 && (
<section
id="related-searches"
className="my-5 p-3 border border-emerald-600 text-sm">
<h3 className="text-emerald-700 mb-2">Related Searches</h3>
{
searchResult.related_searches.map((item, index) => {
return (
<div key={index} className="mb-1">
<p className=""> {item.query} </p>
</div>
)
})
}
</section>
)
}
<Terms id={params.id} />
</section>
<TextEditor
id={params.id}
prevContent={data.content} />
</section>
</div>
)
@@ -0,0 +1,41 @@
"use client";
import { useState } from "react";
export default function TextEditor({id, prevContent}: {id: string, prevContent: string}) {
const [content, setContent] = useState<string>(prevContent)
const saveContent = () => {
fetch(`http://localhost:8000/posts/${id}/`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: content
})
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err))
}
return (
<section className="ml-5 w-8/12">
<div className="flex justify-between items-center mb-5">
<p className="font-bold text-xl">Text Editor</p>
<button
onClick={() => {saveContent()}}
className="bg-sky-400 hover:bg-sky-600 p-3 rounded-lg text-white">
Save
</button>
</div>
<textarea
value={content || ''}
onChange={(e) => {setContent(e.target.value)}}
className="w-full h-screen border border-gray-300 p-5"></textarea>
</section>
)
}