diff --git a/pages/index.tsx b/pages/index.tsx index f6ac7358..7645f0fc 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -115,11 +115,14 @@ const IndexSidebarCard = ({ sidebar }) => { return ( <> - {posts.length > 0 && + #{sidebar.tagName} - + + {posts.length > 0 && + <> + { @@ -127,7 +130,9 @@ const IndexSidebarCard = ({ sidebar }) => { } - } + + } + ) } \ No newline at end of file diff --git a/pages/tags/index.tsx b/pages/tags/index.tsx index b0f7f00b..7fa63abd 100644 --- a/pages/tags/index.tsx +++ b/pages/tags/index.tsx @@ -12,32 +12,30 @@ import SEO from "components/seo" import siteConfig from "configs/site-config" import PageContainer1 from "layouts/page-container1" import React, { useEffect, useState } from "react" -import { HomeSidebar } from 'pages/index' import Card, { CardBody, CardHeader } from "components/card" import { config } from "configs/config" -import { getSvgIcon } from "components/svg-icon" import { Tag } from "src/types/tag" import { requestApi } from "utils/axios/request" import TagCard from 'src/components/tags/tag-card' import useSession from "hooks/use-session" import Link from "next/link" import { IDType } from "src/types/id" +import { SearchFilter } from "src/types/search" const tagsFilter = [{ + id: SearchFilter.Best, name: 'Popular', desc: 'Extremely active tags in terms of posts in the last 7 days.' }, +// { +// id: SearchFilter.Latest, +// name: "Recently Added", +// desc: "Tags that are recently added, sorted from newest to oldest." +// }, { - name: "Recently Added", - desc: "Tags that are recently added, sorted from newest to oldest." -}, -{ + id: SearchFilter.Favorites, name: "Most Followers", desc: "Tags with the maximum number of followers and posts all time.", -}, -{ - name: "New Proposals", - desc: "Follow these tags to cast your vote. We periodically approve tags based on community interest." } ] @@ -48,7 +46,7 @@ const TagsPage = () => { const session = useSession() const getTags = () => { - requestApi.get(`/tag/all`).then((res) => setTags(res.data)).catch(_ => setTags([])) + requestApi.get(`/tag/all?filter=${filter.id}`).then((res) => setTags(res.data)).catch(_ => setTags([])) } const getUserTags = async () => { @@ -115,19 +113,19 @@ const TagsPage = () => { - {tags.map(t => )} + {tags.map(t => )} - {userTags.length > 0 && + 我关注的Tags - + {userTags.length > 0 && { - userTags.map(tag => + userTags.map(tag => {tag.icon && } #{tag.name} @@ -135,8 +133,8 @@ const TagsPage = () => { ) } - - } + } + diff --git a/server/internal/api/tag.go b/server/internal/api/tag.go index 69007e72..08da109a 100644 --- a/server/internal/api/tag.go +++ b/server/internal/api/tag.go @@ -2,9 +2,11 @@ package api import ( "net/http" + "sort" "strconv" "github.com/gin-gonic/gin" + "github.com/imdotdev/im.dev/server/internal/interaction" "github.com/imdotdev/im.dev/server/internal/tags" "github.com/imdotdev/im.dev/server/internal/user" "github.com/imdotdev/im.dev/server/pkg/common" @@ -24,12 +26,23 @@ func GetTag(c *gin.Context) { } func GetTags(c *gin.Context) { + filter := c.Query("filter") res, err := models.GetTags() if err != nil { c.JSON(err.Status, common.RespError(err.Message)) return } + if filter == models.FilterFavorites { + for _, tag := range res { + tag.Follows = interaction.GetFollows(tag.ID) + } + + sort.Sort(models.FollowTags(res)) + } else { + sort.Sort(res) + } + c.JSON(http.StatusOK, common.RespSuccess(res)) } diff --git a/server/internal/storage/init_tags.go b/server/internal/storage/init_tags.go index fd5b0f82..89f42027 100644 --- a/server/internal/storage/init_tags.go +++ b/server/internal/storage/init_tags.go @@ -21,7 +21,7 @@ var tagsList = []*models.Tag{ &models.Tag{Title: "Machine Learning", Name: "machine-learning", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1513321644252/Sk43El-fz.png?w=180&h=180&fit=crop&crop=entropy&auto=compress", Md: ""}, &models.Tag{Title: "Developer", Name: "developer", Icon: "https://cdn.hashnode.com/res/hashnode/image/upload/v1554321431158/MqVqSHr8Q.jpeg?w=180&h=180&fit=crop&crop=entropy&auto=compress", Md: ""}, &models.Tag{Title: "Docker", Name: "docker", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--7L1txQC1--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/87/docker-badge.png", Md: "Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications, whether on laptops, data center VMs, or the cloud.\n\n\n\u003cWebsiteLink type=\"official\" url=\"https://reactjs.org/\" /\u003e"}, - &models.Tag{Title: "Kubernetes", Name: "kubernetes", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--XXaJdQCT--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/88/kubernetes-badge.png", Md: "\n\n\n\u003cWebsiteLink type=\"official\" url=\"https://kubernetes.io/\" /\u003e"}, + &models.Tag{Title: "Kubernetes", Name: "kubernetes", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--XXaJdQCT--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/88/kubernetes-badge.png", Md: "Kubernetes, also known as K8s, is an open-source system for automating deployment, scaling, and management of containerized applications.\n\n\n\u003cWebsiteLink type=\"official\" url=\"https://kubernetes.io/\" /\u003e"}, &models.Tag{Title: "Rust", Name: "rust", Icon: "https://res.cloudinary.com/practicaldev/image/fetch/s--4RD0-X0v--/c_limit,f_auto,fl_progressive,q_80,w_180/https://dev-to-uploads.s3.amazonaws.com/uploads/badge/badge_image/35/rust-badge.png", Md: "Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.\n\n\n\u003cWebsiteLink type=\"official\" url=\"https://rust-lang.org/\" /\u003e"}, &models.Tag{Title: "Web Development", Name: "webdev", Icon: "https://i.postimg.cc/RVP8fWFz/web-dev-logo.png", Md: ""}, &models.Tag{Title: "Testing", Name: "testing", Icon: "https://i.postimg.cc/0ygM0fzs/testing-image.png", Md: "Executing a program or application with the intent of finding the software bugs is known as Software Testing. It is normally done to detect the differences between given input and expected output."}, diff --git a/server/pkg/models/tag.go b/server/pkg/models/tag.go index 280618f8..f3f3942c 100644 --- a/server/pkg/models/tag.go +++ b/server/pkg/models/tag.go @@ -38,6 +38,14 @@ func (t Tags) Less(i, j int) bool { return t[i].Posts > t[j].Posts } +type FollowTags []*Tag + +func (t FollowTags) Len() int { return len(t) } +func (t FollowTags) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t FollowTags) Less(i, j int) bool { + return t[i].Follows > t[j].Follows +} + func GetTargetTags(targetID string) ([]string, []*Tag, error) { ids := make([]string, 0) rows, err := db.Conn.Query("SELECT tag_id FROM tags_using WHERE target_id=?", targetID) diff --git a/src/components/tags/tag-card.tsx b/src/components/tags/tag-card.tsx index 04cba6a7..1bc2dd3e 100644 --- a/src/components/tags/tag-card.tsx +++ b/src/components/tags/tag-card.tsx @@ -11,11 +11,12 @@ type Props = PropsOf & { showActions?: boolean onEdit?: any onDelete?: any + unit?: string } export const TagCard= (props:Props) =>{ - const {tag,showActions=false,onEdit,onDelete} = props + const {tag,showActions=false,onEdit,onDelete,unit="posts"} = props return ( @@ -32,7 +33,7 @@ export const TagCard= (props:Props) =>{ {/* */} : -  posts +  {unit} } )