diff --git a/frontend/index.js b/frontend/index.js index c7ba026..377328d 100644 --- a/frontend/index.js +++ b/frontend/index.js @@ -103,6 +103,39 @@ export async function search(dbarg, needle) { return queue; } + +export async function getFeedDetails(dbarg, feedid) { + let db = await dbarg; + let result = {}; + await db('exec', { + sql: `SELECT fd.home, + fd.description, + fd.language, + fd.image, + fd.author, + feeds.url + FROM feeds_details fd + JOIN feeds ON feeds.id = fd.feedid + WHERE feeds.id = $id`, + bind: {$id: feedid}, + callback: (msg) => { + if (msg.row) { + let [home,description,language,image,author,url] = msg.row; + result = { + id: feedid, + home: home, + description: description, + language: language, + image: image, + author: author, + url: url + } + } + } + }); + return result; +} + export async function getEntryDetails(dbarg, entryId, needle) { let db = await dbarg; let result; diff --git a/frontend/public/index.html b/frontend/public/index.html index 1073627..8a2ae0a 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -115,6 +115,32 @@ } } + .feed-details { + display: flex; + flex-direction: row; + justify-content: center; + } + .feed-details img { + max-width: 30%; + object-fit: contain; + } + .feed-bio { + font-size: 1.4em; + padding: 0 10; + display: flex; + flex-direction: column; + justify-content: space-between; + } + .feed-links { + display: flex; + justify-content: space-around; + } + @media (min-width: 1200px) { + .feed-details { + padding: 2em 5em; + } + } + div.episode { padding: 1.2em 0.5em; overflow: auto; /* needed for chrome, otherwise links would change the box layout */ @@ -184,6 +210,9 @@ Muh.getFeeds(db).then((fs) => { app.ports.receiveInitFeeds.send(fs); }); + app.ports.askForFeedDetails.subscribe((feedid) => { + Muh.getFeedDetails(db, feedid).then(app.ports.receiveFeedDetails.send); + }); app.ports.askForEntries.subscribe((feedid) => { Muh.getEntries(db, feedid).then(app.ports.receiveEntries.send); }); diff --git a/frontend/src/Main.elm b/frontend/src/Main.elm index 5c9e1e8..1d7cad7 100644 --- a/frontend/src/Main.elm +++ b/frontend/src/Main.elm @@ -2,8 +2,8 @@ port module Main exposing (..) import Browser import Filesize -import Html exposing (Html, a, article, details, div, footer, form, header, input, main_, span, summary, text, time) -import Html.Attributes exposing (attribute, autofocus, class, href, maxlength, minlength, placeholder, size, type_, value) +import Html exposing (Html, a, article, details, div, footer, form, header, img, input, main_, span, summary, text, time) +import Html.Attributes exposing (attribute, autofocus, class, href, maxlength, minlength, placeholder, size, src, type_, value) import Html.Events exposing (onClick, onInput, onSubmit, stopPropagationOn) import Json.Decode as JD import List.Extra @@ -49,6 +49,7 @@ type alias DbStats = type alias Feed = { id : Int , title : String + , details : Maybe FeedDetails , isSelected : Bool , isVisible : Bool , nEntries : Int @@ -56,6 +57,17 @@ type alias Feed = } +type alias FeedDetails = + { id : Int + , home : String + , description : String + , language : String + , image : String + , author : String + , url : String + } + + type alias Entry = { id : Int , feedid : Int @@ -87,6 +99,7 @@ type Msg | NewSearchResults (List NewEntry) | NewDbStats DbStats | NewError String + | NewFeedDetails FeedDetails type alias InitFeed = @@ -118,6 +131,9 @@ type alias QuestionEntryDetails = } +port askForFeedDetails : Int -> Cmd msg + + port askForEntryDetails : QuestionEntryDetails -> Cmd msg @@ -127,6 +143,9 @@ port askForEntries : Int -> Cmd msg port askForSearch : String -> Cmd msg +port receiveFeedDetails : (FeedDetails -> msg) -> Sub msg + + port receiveDbStats : (DbStats -> msg) -> Sub msg @@ -166,7 +185,7 @@ toEntry { id, feedid, title, date, url } = toFeed : InitFeed -> Feed toFeed { id, title, nEntries } = - { id = id, title = title, isSelected = False, isVisible = True, nEntries = nEntries, nResults = 0 } + { id = id, title = title, details = Nothing, isSelected = False, isVisible = True, nEntries = nEntries, nResults = 0 } toggleEntryDetails : Int -> List Entry -> List Entry @@ -250,7 +269,7 @@ update msg ({ feeds, entries, search, state } as model) = AskForEntries feedId -> case state of Idle -> - ( toggleSelectedFeed model feedId, askForEntries feedId ) + ( toggleSelectedFeed model feedId, Cmd.batch [ askForFeedDetails feedId, askForEntries feedId ] ) _ -> ( toggleSelectedFeed model feedId, Cmd.none ) @@ -283,6 +302,22 @@ update msg ({ feeds, entries, search, state } as model) = NewError _ -> ( { model | state = Error }, Cmd.none ) + NewFeedDetails ({ id } as feedDetails) -> + ( { model + | feeds = + List.map + (\feed -> + if feed.id == id && feed.details == Nothing then + { feed | details = Just feedDetails } + + else + feed + ) + feeds + } + , Cmd.none + ) + newSearchResults : Model -> List NewEntry -> Model newSearchResults model newEntries = @@ -379,6 +414,14 @@ viewFeed ({ title, id, isSelected } as feed) state now entries = _ -> feed.nEntries + + content = + case state of + Idle -> + viewFeedDetails feed :: viewFeedEntries id now entries + + _ -> + viewFeedEntries id now entries in article [ onClick (AskForEntries id) ] [ details [ open isSelected ] <| @@ -386,7 +429,31 @@ viewFeed ({ title, id, isSelected } as feed) state now entries = [ span [] [ text title ] , span [] [ text (" [" ++ fromInt count ++ "]") ] ] - :: viewFeedEntries id now entries + :: content + ] + + +viewFeedDetails : Feed -> Html Msg +viewFeedDetails { details } = + div + [ class "episode" + ] + [ div [ class "feed-details" ] <| + case details of + Nothing -> + [ text "..." ] + + Just feedDetails -> + [ img [ src feedDetails.image ] [] + , div [ class "feed-bio" ] + [ div [] [] + , text feedDetails.description + , div [ class "feed-links" ] + [ a [ href feedDetails.home ] [ text "Site" ] + , a [ href feedDetails.url ] [ text "RSS" ] + ] + ] + ] ] @@ -552,4 +619,5 @@ subscriptions _ = , receiveSearchResults NewSearchResults , receiveDbStats NewDbStats , receiveError NewError + , receiveFeedDetails NewFeedDetails ] diff --git a/jobs/go/src/feed.go b/jobs/go/src/feed.go index 920ba57..e524bbf 100644 --- a/jobs/go/src/feed.go +++ b/jobs/go/src/feed.go @@ -107,7 +107,9 @@ func (feed *Feed) Fetch() error { feed.Description = rawFeed.Description feed.Language = rawFeed.Language - feed.Image = rawFeed.Image.URL + if rawFeed.Image != nil { + feed.Image = rawFeed.Image.URL + } feed.Home = rawFeed.Link if len(rawFeed.Authors) > 0 { feed.Author = rawFeed.Authors[0].Name