diff --git a/api/memo.go b/api/memo.go index 75dcd35c..bfb7b940 100644 --- a/api/memo.go +++ b/api/memo.go @@ -42,8 +42,12 @@ type MemoFind struct { CreatorID *int `json:"creatorId"` // Domain specific fields - Pinned *bool - Tag *string + Pinned *bool + ContentSearch *string + + // Pagination + Limit int + Offset int } type MemoDelete struct { diff --git a/server/memo.go b/server/memo.go index c03f3204..a99dadd7 100644 --- a/server/memo.go +++ b/server/memo.go @@ -77,7 +77,14 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { } tag := c.QueryParam("tag") if tag != "" { - memoFind.Tag = &tag + contentSearch := "#" + tag + " " + memoFind.ContentSearch = &contentSearch + } + if limit, err := strconv.Atoi(c.QueryParam("limit")); err == nil { + memoFind.Limit = limit + } + if offset, err := strconv.Atoi(c.QueryParam("offset")); err == nil { + memoFind.Offset = offset } list, err := s.Store.FindMemoList(memoFind) @@ -177,4 +184,25 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { return nil }) + + g.GET("/memo/amount", func(c echo.Context) error { + userID := c.Get(getUserIDContextKey()).(int) + normalRowStatus := api.Normal + memoFind := &api.MemoFind{ + CreatorID: &userID, + RowStatus: &normalRowStatus, + } + + memoList, err := s.Store.FindMemoList(memoFind) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo list").SetInternal(err) + } + + c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) + if err := json.NewEncoder(c.Response().Writer).Encode(len(memoList)); err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo amount").SetInternal(err) + } + + return nil + }) } diff --git a/server/server.go b/server/server.go index c5c3c676..91e5c974 100644 --- a/server/server.go +++ b/server/server.go @@ -70,6 +70,7 @@ func NewServer(profile *profile.Profile) *Server { s.registerMemoRoutes(apiGroup) s.registerShortcutRoutes(apiGroup) s.registerResourceRoutes(apiGroup) + s.registerTagRoutes(apiGroup) return s } diff --git a/server/tag.go b/server/tag.go new file mode 100644 index 00000000..4cc90af5 --- /dev/null +++ b/server/tag.go @@ -0,0 +1,51 @@ +package server + +import ( + "encoding/json" + "memos/api" + "net/http" + "regexp" + + "github.com/labstack/echo/v4" +) + +func (s *Server) registerTagRoutes(g *echo.Group) { + g.GET("/tag", func(c echo.Context) error { + userID := c.Get(getUserIDContextKey()).(int) + contentSearch := "#" + memoFind := api.MemoFind{ + CreatorID: &userID, + ContentSearch: &contentSearch, + } + + memoList, err := s.Store.FindMemoList(&memoFind) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo list").SetInternal(err) + } + + tagMapSet := make(map[string]bool) + + r, err := regexp.Compile("#(.+?) ") + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compile regexp").SetInternal(err) + } + for _, memo := range memoList { + for _, rawTag := range r.FindAllString(memo.Content, -1) { + tag := r.ReplaceAllString(rawTag, "$1") + tagMapSet[tag] = true + } + } + + tagList := []string{} + for tag := range tagMapSet { + tagList = append(tagList, tag) + } + + c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) + if err := json.NewEncoder(c.Response().Writer).Encode(tagList); err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode tags response").SetInternal(err) + } + + return nil + }) +} diff --git a/server/webhook.go b/server/webhook.go index 03fa6ad5..ee9bbf3b 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -114,7 +114,14 @@ func (s *Server) registerWebhookRoutes(g *echo.Group) { } tag := c.QueryParam("tag") if tag != "" { - memoFind.Tag = &tag + contentSearch := tag + " " + memoFind.ContentSearch = &contentSearch + } + if limit, err := strconv.Atoi(c.QueryParam("limit")); err == nil { + memoFind.Limit = limit + } + if offset, err := strconv.Atoi(c.QueryParam("offset")); err == nil { + memoFind.Offset = offset } list, err := s.Store.FindMemoList(memoFind) diff --git a/store/memo.go b/store/memo.go index 8e281516..cc500987 100644 --- a/store/memo.go +++ b/store/memo.go @@ -209,10 +209,20 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) { if v := find.Pinned; v != nil { where = append(where, "id in (SELECT memo_id FROM memo_organizer WHERE pinned = 1 AND user_id = memo.creator_id )") } - if v := find.Tag; v != nil { - where, args = append(where, "content LIKE ?"), append(args, "%#"+*v+" %") + if v := find.ContentSearch; v != nil { + where, args = append(where, "content LIKE ?"), append(args, "%"+*v+"%") } + pagination := "" + if find.Limit > 0 { + pagination = fmt.Sprintf("%s LIMIT %d", pagination, find.Limit) + if find.Offset > 0 { + pagination = fmt.Sprintf("%s OFFSET %d", pagination, find.Offset) + } + } + + println(pagination) + rows, err := db.Query(` SELECT id, @@ -223,7 +233,7 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) { row_status FROM memo WHERE `+strings.Join(where, " AND ")+` - ORDER BY created_ts DESC`, + ORDER BY created_ts DESC`+pagination, args..., ) if err != nil {