diff --git a/layouts/nav/post-nav.tsx b/layouts/nav/post-nav.tsx
index d60113bd..3dafc945 100644
--- a/layouts/nav/post-nav.tsx
+++ b/layouts/nav/post-nav.tsx
@@ -32,7 +32,7 @@ function PostNav(props:Props) {
useEffect(() => {
if (post) {
- requestApi.get(`/interaction/followed/${post.id}`).then(res => setFollowed(res.data))
+ requestApi.get(`/interaction/followed/${post.creator.id}`).then(res => setFollowed(res.data))
}
}, [])
@@ -50,7 +50,7 @@ function PostNav(props:Props) {
Sunface的博客
- {followed !== null && }
+ {followed !== null && }
diff --git a/pages/[username]/index.tsx b/pages/[username]/index.tsx
index c8fd43bf..f7eb62a0 100644
--- a/pages/[username]/index.tsx
+++ b/pages/[username]/index.tsx
@@ -22,27 +22,61 @@ import Posts from "components/story/posts"
import Link from "next/link"
import Empty from "components/empty"
import Count from "components/count"
+import { Tag } from "src/types/tag"
const UserPage = () => {
const router = useRouter()
const username = router.query.username
const session = useSession()
const [user, setUser]: [User, any] = useState(null)
+ const [rawPosts, setRawPosts]: [Post[], any] = useState([])
const [posts, setPosts]: [Post[], any] = useState([])
+ const [tags,setTags]:[Tag[],any] = useState([])
+ const [tagFilter,setTagFilter]:[Tag,any] = useState(null)
+
const borderColor = useColorModeValue('white', 'transparent')
useEffect(() => {
if (username) {
initData(username)
+
}
}, [username])
const initData = async (username) => {
const res = await requestApi.get(`/user/info/${username}`)
setUser(res.data)
+ getTags(res.data.id)
+
const res1 = await requestApi.get(`/user/posts/${res.data.id}`)
setPosts(res1.data)
+ setRawPosts(res1.data)
+ }
+
+ const getTags = async (userID) => {
+ const res = await requestApi.get(`/tag/user/${userID}`)
+ setTags(res.data)
}
+ const filterPostsByTag = tag => {
+ if (tag.id === tagFilter?.id) {
+ setTagFilter(null)
+ setPosts(rawPosts)
+ return
+ }
+
+ setTagFilter(tag)
+ const p = []
+ rawPosts.forEach(post => {
+ for (let i=0;i
@@ -61,7 +95,7 @@ const UserPage = () => {
{user.nickname}
{user.tagline && {user.tagline}}
- Followers
+ Followers
Following
{session?.user.id === user.id ?
@@ -91,7 +125,7 @@ const UserPage = () => {
{moment(user.created).fromNow()}
-
+
{user.github && }
{user.twitter && }
{user.facebook && }
@@ -107,7 +141,7 @@ const UserPage = () => {
}
{user.rawSkills.length > 0 &&
- My Tech Stack
+ 擅长技能
{
user.rawSkills.map(skill =>
@@ -120,13 +154,19 @@ const UserPage = () => {
}
}
- {/*
-
-
- 2 posts written
- 30 comments written
-
- */}
+
+ {tags.length > 0 &&
+ 博客标签
+
+ {
+ tags.map(tag =>
+
+ )
+ }
+
+ }
@@ -138,7 +178,7 @@ const UserPage = () => {
:
-
+
}
diff --git a/pages/bookmarks.tsx b/pages/bookmarks.tsx
index 8034b0b2..084ac082 100644
--- a/pages/bookmarks.tsx
+++ b/pages/bookmarks.tsx
@@ -29,7 +29,7 @@ import Empty from "components/empty"
const BookmarksPage = () => {
- const [filter, setFilter]:[Tag,any] = useState({id:"-1"})
+ const [filter, setFilter]:[Tag,any] = useState(null)
const [tags, setTags]: [Tag[], any] = useState([])
const [rawPosts,setRawPosts]: [Post[],any] = useState([])
const [posts,setPosts]: [Post[],any] = useState([])
@@ -37,42 +37,45 @@ import Empty from "components/empty"
useEffect(() => {
getBookmarkPosts()
}, [])
-
- useEffect(() => {
- filterPosts()
- }, [filter])
const getBookmarkPosts = async() => {
const res = await requestApi.get(`/story/bookmark/posts`)
setRawPosts(res.data)
setPosts(res.data)
- const ts = [{id:-1,title:'All Tags',icon: 'https://cdn.hashnode.com/res/hashnode/image/upload/v1605105898259/3vuMFM8qM.png?w=200&h=200&fit=crop&crop=entropy&auto=compress&auto=compress'}]
+ const ts = []
res.data.forEach(post => {
- post.rawTags?.forEach(tag => {
- if (!find(ts, t => t.id === tag.id)) {
- ts.push(tag)
- }
- })
+ for (let i=0;i t.id === tag.id)) {
+ ts.push(tag)
+ break
+ }
+ }
})
setTags(ts)
}
- const filterPosts = () => {
- if (filter.id === "-1") {
- setPosts(rawPosts)
- return
+ const filterPostsByTag = (t:Tag) => {
+ if (t.id === filter?.id) {
+ setPosts(rawPosts)
+ setFilter(null)
+ return
}
+
const newPosts = []
rawPosts.forEach(post => {
- post.rawTags?.forEach(tag => {
- if (tag.id === filter.id) {
- newPosts.push(post)
- }
- })
+ for (let i=0;i
{
tags.map(t =>
- setFilter(t)}>
+ filterPostsByTag(t)}>
{t.title}
)
diff --git a/pages/settings/profile.tsx b/pages/settings/profile.tsx
index 77c7ada9..12b6df0f 100644
--- a/pages/settings/profile.tsx
+++ b/pages/settings/profile.tsx
@@ -201,15 +201,6 @@ const UserProfilePage = () => {
)}
-
- {({ field, form }) => (
-
- 自我介绍
-
- {form.errors.about}
-
- )}
-
{({ field, form }) => (
@@ -218,9 +209,6 @@ const UserProfilePage = () => {
)}
-
-
-
diff --git a/pages/tags/[name].tsx b/pages/tags/[name].tsx
index 0a9eec0b..986a1ef8 100644
--- a/pages/tags/[name].tsx
+++ b/pages/tags/[name].tsx
@@ -18,6 +18,7 @@ import { Tag } from "src/types/tag"
import { requestApi } from "utils/axios/request"
import { isAdmin } from "utils/role"
import Follow from "components/interaction/follow"
+import Count from "components/count"
const UserPage = () => {
const router = useRouter()
@@ -88,12 +89,12 @@ const UserPage = () => {
- 59.8K
+
Followers
- {tag.postCount}
+
Posts
diff --git a/server/internal/api/tag.go b/server/internal/api/tag.go
index 76730ccf..084fb094 100644
--- a/server/internal/api/tag.go
+++ b/server/internal/api/tag.go
@@ -77,3 +77,14 @@ func DeleteTag(c *gin.Context) {
c.JSON(http.StatusOK, common.RespSuccess(nil))
}
+
+func GetUserTags(c *gin.Context) {
+ userID := c.Param("userID")
+ res, err := tags.GetUserTags(userID)
+ if err != nil {
+ c.JSON(err.Status, common.RespError(err.Message))
+ return
+ }
+
+ c.JSON(http.StatusOK, common.RespSuccess(res))
+}
diff --git a/server/internal/server.go b/server/internal/server.go
index 43b5bc76..0758eabc 100644
--- a/server/internal/server.go
+++ b/server/internal/server.go
@@ -62,7 +62,7 @@ func (s *Server) Start() error {
r.GET("/tag/all", api.GetTags)
r.GET("/tag/posts/:id", api.GetTagPosts)
r.GET("/tag/info/:name", api.GetTag)
-
+ r.GET("/tag/user/:userID", api.GetUserTags)
// user apis
r.GET("/user/all", api.GetUsers)
r.GET("/user/self", IsLogin(), api.GetUserSelf)
diff --git a/server/internal/storage/init.go b/server/internal/storage/init.go
index c9f60219..93ac1f87 100644
--- a/server/internal/storage/init.go
+++ b/server/internal/storage/init.go
@@ -22,13 +22,13 @@ func Init() error {
}
// check whether tables have been created
- var id int64
- err = db.Conn.QueryRow("select id from user where id=?", 1).Scan(&id)
+ var id string
+ err = db.Conn.QueryRow("select id from user where username=?", config.Data.User.SuperAdminUsername).Scan(&id)
if err != nil && !strings.Contains(err.Error(), "no such table") && err != sql.ErrNoRows {
return err
}
- if id != 1 {
+ if err == sql.ErrNoRows {
log.RootLogger.Info("Database tables have not been created, start creating")
err = initTables()
if err != nil {
diff --git a/server/internal/storage/sql_tables.go b/server/internal/storage/sql_tables.go
index fda323cb..a18bcf25 100644
--- a/server/internal/storage/sql_tables.go
+++ b/server/internal/storage/sql_tables.go
@@ -123,7 +123,8 @@ var sqlTables = map[string]string{
"tags_using": `CREATE TABLE IF NOT EXISTS tags_using (
tag_id VARCHAR(255),
target_type VARCHAR(1),
- target_id VARCHAR(255)
+ target_id VARCHAR(255),
+ target_creator VARCHAR(255)
);
CREATE INDEX IF NOT EXISTS tags_using_tagid
ON tags_using (tag_id);
diff --git a/server/internal/story/post.go b/server/internal/story/post.go
index ab52a5bd..989a31c6 100644
--- a/server/internal/story/post.go
+++ b/server/internal/story/post.go
@@ -95,7 +95,7 @@ func SubmitPost(c *gin.Context) (map[string]string, *e.Error) {
}
//update tags
- err = tags.UpdateTargetTags(post.ID, post.Tags)
+ err = tags.UpdateTargetTags(user.ID, post.ID, post.Tags)
if err != nil {
logger.Warn("upate tags error", "error", err)
return nil, e.New(http.StatusInternalServerError, e.Internal)
diff --git a/server/internal/story/posts.go b/server/internal/story/posts.go
index 105eebcf..aea07bfc 100644
--- a/server/internal/story/posts.go
+++ b/server/internal/story/posts.go
@@ -130,6 +130,12 @@ func getPosts(user *models.User, rows *sql.Rows) models.Posts {
}
ar.Likes = interaction.GetLikes(ar.ID)
+ _, rawTags, err := tags.GetTargetTags(ar.ID)
+ if err != nil {
+ logger.Warn("get tags error", "error", err)
+ }
+ ar.RawTags = rawTags
+
posts = append(posts, ar)
}
diff --git a/server/internal/tags/tags.go b/server/internal/tags/tags.go
index efb5d896..3450898e 100644
--- a/server/internal/tags/tags.go
+++ b/server/internal/tags/tags.go
@@ -8,6 +8,7 @@ import (
"time"
"github.com/asaskevich/govalidator"
+ "github.com/imdotdev/im.dev/server/internal/interaction"
"github.com/imdotdev/im.dev/server/pkg/db"
"github.com/imdotdev/im.dev/server/pkg/e"
"github.com/imdotdev/im.dev/server/pkg/log"
@@ -70,7 +71,7 @@ func SubmitTag(tag *models.Tag) *e.Error {
func GetTags() (models.Tags, *e.Error) {
tags := make(models.Tags, 0)
- rows, err := db.Conn.Query("SELECT id,creator,title,md,name,icon,cover,created,updated from tags")
+ rows, err := db.Conn.Query("SELECT id,creator,title,md,name,icon,cover from tags")
if err != nil {
if err == sql.ErrNoRows {
return tags, nil
@@ -82,7 +83,7 @@ func GetTags() (models.Tags, *e.Error) {
for rows.Next() {
var rawMd []byte
tag := &models.Tag{}
- err := rows.Scan(&tag.ID, &tag.Creator, &tag.Title, &rawMd, &tag.Name, &tag.Icon, &tag.Cover, &tag.Created, &tag.Updated)
+ err := rows.Scan(&tag.ID, &tag.Creator, &tag.Title, &rawMd, &tag.Name, &tag.Icon, &tag.Cover)
if err != nil {
logger.Warn("scan tags error", "error", err)
continue
@@ -94,7 +95,7 @@ func GetTags() (models.Tags, *e.Error) {
tag.SetCover()
tags = append(tags, tag)
- db.Conn.QueryRow("SELECT count(*) FROM tags_using WHERE tag_id=?", tag.ID).Scan(&tag.PostCount)
+ db.Conn.QueryRow("SELECT count(*) FROM tags_using WHERE tag_id=? and target_type != ?", tag.ID, models.IDTypeUser).Scan(&tag.Posts)
}
sort.Sort(tags)
@@ -115,8 +116,8 @@ func DeleteTag(id int64) *e.Error {
func GetTag(id string, name string) (*models.Tag, *e.Error) {
tag := &models.Tag{}
var rawmd []byte
- err := db.Conn.QueryRow("SELECT id,creator,title,name,icon,cover,created,updated,md from tags where id=? or name=?", id, name).Scan(
- &tag.ID, &tag.Creator, &tag.Title, &tag.Name, &tag.Icon, &tag.Cover, &tag.Created, &tag.Updated, &rawmd,
+ err := db.Conn.QueryRow("SELECT id,creator,title,name,icon,cover,md from tags where id=? or name=?", id, name).Scan(
+ &tag.ID, &tag.Creator, &tag.Title, &tag.Name, &tag.Icon, &tag.Cover, &rawmd,
)
if err != nil {
if err == sql.ErrNoRows {
@@ -129,9 +130,11 @@ func GetTag(id string, name string) (*models.Tag, *e.Error) {
md, _ := utils.Uncompress(rawmd)
tag.Md = string(md)
- db.Conn.QueryRow("SELECT count(*) FROM tags_using WHERE tag_id=?", tag.ID).Scan(&tag.PostCount)
+ db.Conn.QueryRow("SELECT count(*) FROM tags_using WHERE tag_id=? and target_type !=?", tag.ID, models.IDTypeUser).Scan(&tag.Posts)
tag.SetCover()
+ tag.Follows = interaction.GetFollows(tag.ID)
+
return tag, nil
}
@@ -173,14 +176,14 @@ func GetTargetTags(targetID string) ([]string, []*models.Tag, error) {
return ids, rawTags, nil
}
-func UpdateTargetTags(targetID string, tags []string) error {
+func UpdateTargetTags(targetCreator string, targetID string, tags []string) error {
_, err := db.Conn.Exec("DELETE FROM tags_using WHERE target_id=?", targetID)
if err != nil {
return err
}
for _, tag := range tags {
- _, err = db.Conn.Exec("INSERT INTO tags_using (tag_id,target_type,target_id) VALUES (?,?,?)", tag, models.GetIDType(targetID), targetID)
+ _, err = db.Conn.Exec("INSERT INTO tags_using (tag_id,target_type,target_id,target_creator) VALUES (?,?,?,?)", tag, models.GetIDType(targetID), targetID, targetCreator)
if err != nil {
logger.Warn("add post tag error", "error", err)
}
@@ -219,3 +222,39 @@ func GetTargetIDs(tagID string) ([]string, error) {
return ids, nil
}
+
+func GetUserTags(userID string) ([]*models.Tag, *e.Error) {
+ tagsMap := make(map[string]*models.Tag)
+
+ rows, err := db.Conn.Query("SELECT tag_id from tags_using where target_creator=?", userID)
+ if err != nil {
+ logger.Warn("get tag error", "error", err)
+ return nil, e.New(http.StatusInternalServerError, e.Internal)
+ }
+
+ var tagID string
+ for rows.Next() {
+ rows.Scan(&tagID)
+ tag, ok := tagsMap[tagID]
+ if !ok {
+ tagsMap[tagID] = &models.Tag{ID: tagID, Posts: 1}
+ } else {
+ tag.Posts = tag.Posts + 1
+ }
+ }
+
+ tags := make(models.Tags, 0)
+ for _, t := range tagsMap {
+ tag, err := GetSimpleTag(t.ID, "")
+ if err != nil {
+ logger.Warn("get simple tag error", "error", err)
+ continue
+ }
+ tag.Posts = t.Posts
+ tags = append(tags, tag)
+ }
+
+ sort.Sort(tags)
+
+ return tags, nil
+}
diff --git a/server/internal/user/users.go b/server/internal/user/users.go
index f297f36d..16a6fcff 100644
--- a/server/internal/user/users.go
+++ b/server/internal/user/users.go
@@ -7,6 +7,7 @@ import (
"time"
"github.com/imdotdev/im.dev/server/internal/cache"
+ "github.com/imdotdev/im.dev/server/internal/interaction"
"github.com/imdotdev/im.dev/server/internal/tags"
"github.com/imdotdev/im.dev/server/pkg/db"
"github.com/imdotdev/im.dev/server/pkg/e"
@@ -62,6 +63,8 @@ func GetUserDetail(id string, username string) (*models.User, *e.Error) {
user.RawSkills = rawSkills
user.Skills = skills
+ user.Follows = interaction.GetFollows(user.ID)
+
return user, nil
}
@@ -75,7 +78,7 @@ func UpdateUser(u *models.User) *e.Error {
return e.New(http.StatusInternalServerError, e.Internal)
}
- var nid int64
+ var nid string
err = db.Conn.QueryRow("SELECT id FROM user_profile WHERE id=?", u.ID).Scan(&nid)
if err != nil && err != sql.ErrNoRows {
logger.Warn("update user profile error", "error", err)
@@ -97,7 +100,7 @@ func UpdateUser(u *models.User) *e.Error {
}
//update user skills
- err = tags.UpdateTargetTags(u.ID, u.Skills)
+ err = tags.UpdateTargetTags("", u.ID, u.Skills)
if err != nil {
logger.Warn("upate tags error", "error", err)
return e.New(http.StatusInternalServerError, e.Internal)
diff --git a/server/pkg/models/tag.go b/server/pkg/models/tag.go
index 6ef82c67..8c0480d5 100644
--- a/server/pkg/models/tag.go
+++ b/server/pkg/models/tag.go
@@ -1,18 +1,17 @@
package models
-import "time"
-
type Tag struct {
- ID string `json:"id"`
- Creator string `json:"creator,omitempty"`
- Title string `json:"title"`
- Name string `json:"name,omitempty"`
- Md string `json:"md,omitempty"`
- Cover string `json:"cover,omitempty"`
- Icon string `json:"icon"`
- PostCount int `json:"postCount,omitempty"`
- Created time.Time `json:"created,omitempty"`
- Updated time.Time `json:"updated,omitempty"`
+ ID string `json:"id"`
+ Creator string `json:"creator,omitempty"`
+ Title string `json:"title"`
+ Name string `json:"name,omitempty"`
+ Md string `json:"md,omitempty"`
+ Cover string `json:"cover,omitempty"`
+ Icon string `json:"icon"`
+ Posts int `json:"posts"`
+ Follows int `json:"follows"`
+ // Created time.Time `json:"created,omitempty"`
+ // Updated time.Time `json:"updated,omitempty"`
}
func (t *Tag) SetCover() {
@@ -26,5 +25,5 @@ type Tags []*Tag
func (t Tags) Len() int { return len(t) }
func (t Tags) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t Tags) Less(i, j int) bool {
- return t[i].Created.Unix() > t[j].Created.Unix()
+ return t[i].Posts > t[j].Posts
}
diff --git a/server/pkg/models/user.go b/server/pkg/models/user.go
index a578e12c..68ef2f41 100644
--- a/server/pkg/models/user.go
+++ b/server/pkg/models/user.go
@@ -30,6 +30,8 @@ type User struct {
Facebook string `json:"facebook"`
Stackoverflow string `json:"stackoverflow"`
+ Follows int `json:"follows"`
+
LastSeenAt time.Time `json:"lastSeenAt,omitempty"`
Created time.Time `json:"created"`
}
diff --git a/src/components/story/tag-list-card.tsx b/src/components/story/tag-list-card.tsx
index 3d81effc..6e1f6d05 100644
--- a/src/components/story/tag-list-card.tsx
+++ b/src/components/story/tag-list-card.tsx
@@ -18,7 +18,7 @@ export const TagListCard= (props:Props) =>{
{tag.title}
- {tag.postCount} posts
+ {tag.posts} posts
diff --git a/src/components/tags/tag-card.tsx b/src/components/tags/tag-card.tsx
index 12b5d4eb..d83a1c0b 100644
--- a/src/components/tags/tag-card.tsx
+++ b/src/components/tags/tag-card.tsx
@@ -4,6 +4,7 @@ import { Tag } from "src/types/tag"
import { ReserveUrls } from "src/data/reserve-urls"
import NextLink from "next/link"
import userCustomTheme from "theme/user-custom"
+import Count from "components/count"
type Props = PropsOf & {
tag: Tag
@@ -31,7 +32,7 @@ export const TagCard= (props:Props) =>{
:
- {tag.postCount} posts
+ posts
}
)
diff --git a/src/components/user-menu.tsx b/src/components/user-menu.tsx
index 185e2bf8..0a63b77d 100644
--- a/src/components/user-menu.tsx
+++ b/src/components/user-menu.tsx
@@ -40,7 +40,7 @@ export const UserMenu = () => {
icon={session.user.avatar !== '' ? :
diff --git a/src/types/tag.ts b/src/types/tag.ts
index 8d92e820..88ed2c10 100644
--- a/src/types/tag.ts
+++ b/src/types/tag.ts
@@ -6,5 +6,6 @@ export interface Tag {
icon?: string
cover?: string
created?: string
- postCount?: number
+ posts?: number
+ follows?: number
}
\ No newline at end of file
diff --git a/src/types/user.ts b/src/types/user.ts
index 4a7ffec2..cae8d9d9 100644
--- a/src/types/user.ts
+++ b/src/types/user.ts
@@ -7,7 +7,7 @@ export interface Session {
export interface User {
// basic info
- id: number
+ id: string
username: string
nickname: string
avatar: string
@@ -32,12 +32,14 @@ export interface User {
facebook?: string
stackoverflow?: string
+ follows?: number
+
lastSeenAt?: string
created?: string
}
export interface UserSimple {
- id: number
+ id: string
username: string
nickname: string
avatar: string
diff --git a/theme.ts b/theme.ts
index 7e13a505..8396dff2 100644
--- a/theme.ts
+++ b/theme.ts
@@ -23,7 +23,6 @@ const customTheme = extendTheme({
},
styles: {
global: (props) => {
- console.log(props)
return ({
'.hover-bg:hover': {
background: mode(userCustomTheme.hoverBg.light,userCustomTheme.hoverBg.dark )(props),