Skip to content

Adds api for latest & top author interactions #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.7"

services:
db:
image: postgres:14
Expand Down
21 changes: 21 additions & 0 deletions src/codes/clj/docs/backend/adapters/db/postgres.clj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
:author/avatar-url avatar-url
:author/created-at created-at})

(defn db->author+interaction
{:malli/schema [:=> [:cat [:sequential schemas.db/Author+InteractionsRow]]
[:sequential schemas.model.social/Author+Interactions]]}
[db-rows]
(map (fn [{:keys [interactions] :as author}]
(assoc (db->author author)
:author/interactions interactions))
db-rows))

(defn db->note
{:malli/schema [:=> [:cat [:maybe schemas.db/Row]] [:maybe schemas.model.social/Note]]}
[{:keys [id definition-id body created author-id] :as note}]
Expand Down Expand Up @@ -97,3 +106,15 @@
[:maybe schemas.model.social/Social]]}
[db-rows]
(first (db->socials db-rows)))

(defn db->any-socials
{:malli/schema [:=> [:cat [:sequential schemas.db/Row]]
[:maybe [:sequential schemas.model.social/AnySocial]]]}
[db-rows]
(let [notes (db->notes db-rows)
examples (db->examples db-rows)
see-alsos (db->see-alsos db-rows)]
(concat
(seq notes)
(seq examples)
(seq see-alsos))))
29 changes: 29 additions & 0 deletions src/codes/clj/docs/backend/adapters/social.clj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
:avatar-url avatar-url
:created-at created-at})

(defn author-interaction->model->wire
{:malli/schema [:=> [:cat [:sequential schemas.model.social/Author+Interactions]]
[:sequential schemas.wire.out.social/Author+Interactions]]}
[author+interactions]
(->> author+interactions
(map (fn [{:author/keys [interactions] :as author}]
(assoc (author->model->wire author)
:interactions interactions)))
(sort-by :interactions #(compare %2 %1))))

(defn editor->model->wire
{:malli/schema [:=> [:cat schemas.model.social/Editor] schemas.wire.social/Editor]}
[{:editor/keys [edited-at] :as author}]
Expand Down Expand Up @@ -129,3 +139,22 @@
(enc/assoc-some
(author->model->wire author)
:socials (map social->model->wire socials)))

(defn any-social->model->wire
{:malli/schema [:=> [:cat [:sequential schemas.model.social/AnySocial]]
[:maybe [:sequential schemas.wire.out.social/AnySocial]]]}
[any-socials]
(let [notes (->> any-socials
(filter #(:note/note-id %))
(map note->model->wire))
examples (->> any-socials
(filter #(:example/example-id %))
(map example->model->wire))
see-alsos (->> any-socials
(filter #(:see-also/see-also-id %))
(map see-also->model->wire))]
(->> (concat
(seq notes)
(seq examples)
(seq see-alsos))
(sort-by :created-at #(compare %2 %1)))))
12 changes: 12 additions & 0 deletions src/codes/clj/docs/backend/controllers/social.clj
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,15 @@
[:maybe schemas.model.social/Social]]}
[definition-id {:keys [database]}]
(db.postgres/get-by-definition definition-id database))

(defn get-top-authors
{:malli/schema [:=> [:cat :int schemas.types/Components]
[:maybe [:sequential schemas.model.social/Author+Interactions]]]}
[limit {:keys [database]}]
(db.postgres/get-top-authors limit database))

(defn get-latest-interactions
{:malli/schema [:=> [:cat :int schemas.types/Components]
[:maybe [:sequential schemas.model.social/AnySocial]]]}
[limit {:keys [database]}]
(db.postgres/get-latest-interactions limit database))
43 changes: 43 additions & 0 deletions src/codes/clj/docs/backend/db/postgres.clj
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,46 @@
sql/format)
(execute! db)
adapters/db->social-definition))

(defn get-top-authors
{:malli/schema [:=> [:cat :int schemas.types/DatabaseComponent]
[:maybe [:sequential schemas.model.social/Author+Interactions]]]}
[limit db]
(->> (-> (sql.helpers/select
:author/*
[[:count :social/id] :interactions])
(sql.helpers/from [(sql.helpers/union-all
(-> (sql.helpers/select
[:note/note-id :id]
[:note/author-id :author-id])
(sql.helpers/from :note))
(-> (sql.helpers/select
[:example-edit/example-edit-id :id]
[:example-edit/author-id :author-id])
(sql.helpers/from :example-edit))
(-> (sql.helpers/select
[:see-also/see-also-id :id]
[:see-also/author-id :author-id])
(sql.helpers/from :see-also))) :social])
(sql.helpers/join :author
[:= :social/author-id :author/author-id])
(sql.helpers/group-by :author/author-id)
(sql.helpers/order-by [:interactions :desc])
(sql.helpers/limit limit)
sql/format)
(execute! db)
adapters/db->author+interaction))

(defn get-latest-interactions
{:malli/schema [:=> [:cat :int schemas.types/DatabaseComponent]
[:maybe [:sequential schemas.model.social/AnySocial]]]}
[limit db]
(->> (-> (sql.helpers/union-all
get-note-query
get-example-query
get-see-also-query)
(sql.helpers/order-by [:created :desc])
(sql.helpers/limit limit)
sql/format)
(execute! db)
adapters/db->any-socials))
16 changes: 16 additions & 0 deletions src/codes/clj/docs/backend/ports/http_in/social.clj
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,19 @@
:notes []
:examples []
:see-alsos []})})

(defn get-top-authors
[{{{:keys [limit]} :query} :parameters
components :components}]
{:status 200
:body (-> (or limit 10)
(controllers.social/get-top-authors components)
adapters.social/author-interaction->model->wire)})

(defn get-latest-interactions
[{{{:keys [limit]} :query} :parameters
components :components}]
{:status 200
:body (-> (or limit 10)
(controllers.social/get-latest-interactions components)
adapters.social/any-social->model->wire)})
19 changes: 18 additions & 1 deletion src/codes/clj/docs/backend/routes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,24 @@
:responses {200 {:body schemas.wire.out.social/Social}
404 {:body :string}
500 {:body :string}}
:handler ports.http-in.social/get-by-definition}}]]]
:handler ports.http-in.social/get-by-definition}}]]

["/query"
["/top-authors"
{:get {:summary "get top contributing author list"
:parameters {:query [:map [:limit {:optional true} :int]]}
:responses {200 {:body [:sequential schemas.wire.out.social/Author+Interactions]}
404 {:body :string}
500 {:body :string}}
:handler ports.http-in.social/get-top-authors}}]

["/latest-interactions"
{:get {:summary "get latest social interactions list"
:parameters {:query [:map [:limit {:optional true} :int]]}
:responses {200 {:body [:sequential schemas.wire.out.social/AnySocial]}
404 {:body :string}
500 {:body :string}}
:handler ports.http-in.social/get-latest-interactions}}]]]

["/document"
{:swagger {:tags ["document"]}}
Expand Down
3 changes: 3 additions & 0 deletions src/codes/clj/docs/backend/schemas/db/postgres.clj
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@
:account-source
:avatar-url
:created-at]))

(def Author+InteractionsRow
(mu/assoc AuthorRow :interactions :int))
6 changes: 6 additions & 0 deletions src/codes/clj/docs/backend/schemas/model/social.clj
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,11 @@
[:social/examples [:sequential Example]]
[:social/see-alsos [:sequential SeeAlso]]])

(def AnySocial
[:or Example Note SeeAlso])

(def Author+Socials
(mu/assoc Author [:author/socials {:optional true}] [:sequential Social]))

(def Author+Interactions
(mu/assoc Author :author/interactions :int))
6 changes: 6 additions & 0 deletions src/codes/clj/docs/backend/schemas/wire/out/social.clj
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,11 @@
[:examples [:sequential Example]]
[:see-alsos [:sequential SeeAlso]]])

(def AnySocial
[:or Example Note SeeAlso])

(def Author+Socials
(mu/assoc Author [:socials {:optional true}] [:sequential Social]))

(def Author+Interactions
(mu/assoc Author :interactions :int))
29 changes: 28 additions & 1 deletion test/integration/codes/clj/docs/backend/db/postgres_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[com.stuartsierra.component :as component]
[integration.codes.clj.docs.backend.util :as util]
[integration.codes.clj.docs.backend.util.db.postgres :as util.db.postgres]
[matcher-combinators.matchers :as m]
[parenthesin.components.config.aero :as components.config]
[parenthesin.components.db.jdbc-hikari :as components.database]
[parenthesin.helpers.malli :as helpers.malli]
Expand Down Expand Up @@ -71,7 +72,33 @@
:example/author-id)]
:social/see-alsos [see-also-1]}]}

(db/get-author+socials "delboni" "github" database))))
(db/get-author+socials "delboni" "github" database)))

(flow "check latest top authors in db"
(match? (m/in-any-order
[#:author{:author-id uuid?
:login "not-delboni"
:account-source "github"
:avatar-url "https://my.pic.com/me.jpg"
:created-at inst?
:interactions 3}
#:author{:author-id uuid?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic.com/me2.jpg"
:created-at inst?
:interactions 3}])
(util.db.postgres/get-top-authors 10)))

(flow "check latest social interactions in db"
(match? (m/in-any-order
[#:note{:note-id uuid?}
#:note{:note-id uuid?}
#:example{:example-id uuid?}
#:example{:example-id uuid?}
#:see-also{:see-also-id uuid?}
#:see-also{:see-also-id uuid?}])
(util.db.postgres/get-latest-interactions 10))))

(defflow see-also-db-test
{:init (util/start-system! create-and-start-components!)
Expand Down
77 changes: 77 additions & 0 deletions test/integration/codes/clj/docs/backend/social_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,31 @@
(state-flow.server/request! {:method :get
:uri "/api/social/author/delboni/github"})))

(flow "should return top authors"
(match? {:status 200
:body [{:author-id string?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic/me.jpg"
:created-at string?
:interactions 1}]}
(state-flow.server/request! {:method :get
:uri "/api/social/query/top-authors"})))

(flow "should return latest interactions"
(match? {:status 200
:body [{:note-id string?
:definition-id "clojure.core/disj"
:body "my edited note about this function."
:created-at string?
:author {:author-id string?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic/me.jpg"
:created-at string?}}]}
(state-flow.server/request! {:method :get
:uri "/api/social/query/latest-interactions"})))

(flow "should not be able to delete if not allowed"
(match? {:status 403
:body "You not allowed to delete this note."}
Expand Down Expand Up @@ -246,6 +271,26 @@
(state-flow.server/request! {:method :get
:uri "/api/social/author/delboni/github"})))

(flow "should return top authors"
(match? {:status 200
:body [{:author-id string?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic/me.jpg"
:created-at string?
:interactions 1}]}
(state-flow.server/request! {:method :get
:uri "/api/social/query/top-authors"})))

(flow "should return latest interactions"
(match? {:status 200
:body [{:see-also-id see-also-id
:definition-id "clojure.core/disj"
:definition-id-to "clojure.core/dissoc"
:created-at string?}]}
(state-flow.server/request! {:method :get
:uri "/api/social/query/latest-interactions"})))

(flow "should not be able to delete if not allowed"
(match? {:status 403
:body "You not allowed to delete this see also."}
Expand Down Expand Up @@ -386,6 +431,38 @@
(state-flow.server/request! {:method :get
:uri "/api/social/author/delboni/github"})))

(flow "should return top authors"
(match? {:status 200
:body [{:author-id string?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic/me.jpg"
:created-at string?
:interactions 2}]}
(state-flow.server/request! {:method :get
:uri "/api/social/query/top-authors"})))

(flow "should return latest interactions"
(match? {:status 200
:body [{:example-id example-id
:definition-id "clojure.core/disj"
:body "my edited example about this function."
:created-at string?
:editors [{:author-id string?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic/me.jpg"
:created-at string?
:edited-at string?}
{:author-id string?
:login "delboni"
:account-source "github"
:avatar-url "https://my.pic/me.jpg"
:created-at string?
:edited-at string?}]}]}
(state-flow.server/request! {:method :get
:uri "/api/social/query/latest-interactions"})))

(flow "delete example revision part 1"
(state-flow.server/request! {:method :delete
:headers {"authorization" (str "Bearer " token)}
Expand Down
16 changes: 16 additions & 0 deletions test/integration/codes/clj/docs/backend/util/db/postgres.clj
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,19 @@
(->> database
(db/get-by-definition definition-id)
state-flow.api/return)))

(defn get-top-authors
[limit]
(flow "get top authors with their interactions sum"
[database (state-flow.api/get-state :database)]
(->> database
(db/get-top-authors limit)
state-flow.api/return)))

(defn get-latest-interactions
[limit]
(flow "get latest social interactions"
[database (state-flow.api/get-state :database)]
(->> database
(db/get-latest-interactions limit)
state-flow.api/return)))
Loading