| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- module LinkedIn.JobsUnifiedTopCard where
- import Control.Alt
- import Prelude
- import Data.Either (Either(..), hush)
- import Data.Generic.Rep (class Generic)
- import Data.List.Types (NonEmptyList)
- import Data.Maybe (Maybe)
- import Data.Show.Generic (genericShow)
- import LinkedIn (DetachedNode(..))
- import LinkedIn.Types (ParseError(..), Parser)
- import LinkedIn.Utils (detachNonEmptyTextChild, parseDetachedNode, queryAndDetachMany, queryAndDetachOne, queryManyAndParse, queryOneAndParse)
- data JobsUnifiedTopCardElement a = JobsUnifiedTopCardElement {
- header :: a,
- primaryDescription :: TopCardPrimaryDescription a,
- insights :: Maybe (NonEmptyList (TopCardInsight a)),
- actions :: Maybe (NonEmptyList (TopCardAction a))
- }
- data TopCardPrimaryDescription a = TopCardPrimaryDescription {
- link :: a,
- text :: a,
- tvmText :: Maybe (NonEmptyList a)
- }
- data TopCardInsight a = TopCardInsight {
- icon :: a,
- content :: TopCardInsightContent a
- }
- data TopCardInsightContent a =
- TopCardInsightContentSingle a
- | TopCardInsightContentSecondary {primary :: a, secondary :: NonEmptyList (TopCardSecondaryInsight a)}
- | TopCardInsightContentButton a
- data TopCardSecondaryInsight a =
- TopCardSecondaryInsightNested a
- | TopCardSecondaryInsightPlain a
- -- External application : <button id="ember74" class="jobs-apply-button artdeco-button artdeco-button--3 artdeco-button--primary ember-view artdeco-button--icon-right" role="link">
- -- LinkedIn Applcation : <button id="ember115" class="jobs-apply-button artdeco-button artdeco-button--3 artdeco-button--primary ember-view" data-job-id="3786945580">
- data TopCardAction a = TopCardActionApplyButton a
- derive instance Generic (JobsUnifiedTopCardElement a) _
- derive instance Eq a => Eq (JobsUnifiedTopCardElement a)
- instance Show a => Show (JobsUnifiedTopCardElement a) where
- show = genericShow
- instance Functor JobsUnifiedTopCardElement where
- map f (JobsUnifiedTopCardElement {header, primaryDescription, insights, actions}) =
- JobsUnifiedTopCardElement {
- header: f header,
- primaryDescription: map f primaryDescription,
- insights: map (map (map f)) insights,
- actions: map (map (map f)) actions
- }
- derive instance Generic (TopCardPrimaryDescription a) _
- derive instance Eq a => Eq (TopCardPrimaryDescription a)
- instance Show a => Show (TopCardPrimaryDescription a) where
- show = genericShow
- instance Functor TopCardPrimaryDescription where
- map f (TopCardPrimaryDescription {link, text, tvmText}) =
- TopCardPrimaryDescription {link: f link, text: f text, tvmText: map (map f) tvmText}
- derive instance Generic (TopCardInsight a) _
- derive instance Eq a => Eq (TopCardInsight a)
- instance Show a => Show (TopCardInsight a) where
- show = genericShow
- instance Functor TopCardInsight where
- map f (TopCardInsight {icon, content}) =
- TopCardInsight {icon: f icon, content: map f content}
- derive instance Generic (TopCardInsightContent a) _
- derive instance Eq a => Eq (TopCardInsightContent a)
- instance Show a => Show (TopCardInsightContent a) where
- show = genericShow
- instance Functor TopCardInsightContent where
- map f (TopCardInsightContentSingle c) = TopCardInsightContentSingle (f c)
- map f (TopCardInsightContentSecondary {primary, secondary}) =
- TopCardInsightContentSecondary {primary: f primary, secondary: map (map f) secondary}
- map f (TopCardInsightContentButton c) = TopCardInsightContentButton (f c)
- derive instance Generic (TopCardSecondaryInsight a) _
- derive instance Eq a => Eq (TopCardSecondaryInsight a)
- instance Show a => Show (TopCardSecondaryInsight a) where
- show = genericShow
- instance Functor TopCardSecondaryInsight where
- map f (TopCardSecondaryInsightNested c) = TopCardSecondaryInsightNested (f c)
- map f (TopCardSecondaryInsightPlain c) = TopCardSecondaryInsightPlain (f c)
- derive instance Generic (TopCardAction a) _
- derive instance Eq a => Eq (TopCardAction a)
- instance Show a => Show (TopCardAction a) where
- show = genericShow
- instance Functor TopCardAction where
- map f (TopCardActionApplyButton c) = TopCardActionApplyButton (f c)
- parseTopCardAction :: Parser (TopCardAction DetachedNode)
- parseTopCardAction n = do
- self <- parseDetachedNode n
- pure $ ado
- s <- self
- in TopCardActionApplyButton s
- parseTopCardSecondaryInsight :: Parser (TopCardSecondaryInsight DetachedNode)
- parseTopCardSecondaryInsight n = do
- nested <- queryAndDetachOne ":scope span[aria-hidden=true]" n
- plain <- parseDetachedNode n
- pure $ case nested, plain of
- Right p@(DetachedElement _), _ -> Right $ TopCardSecondaryInsightNested p
- _, Right p@(DetachedElement _) -> Right $ TopCardSecondaryInsightPlain p
- _, _ -> Left TextNotFoundError
- parseTopCardInsightContent :: Parser (TopCardInsightContent DetachedNode)
- parseTopCardInsightContent n = do
- primary <- queryAndDetachOne ":scope > span:first-child span[aria-hidden=true]" n
- secondary <- queryManyAndParse
- ":scope > span.job-details-jobs-unified-top-card__job-insight-view-model-secondary"
- parseTopCardSecondaryInsight
- n
- self <- parseDetachedNode n
- pure $ case primary, secondary, self of
- _, _, Right b@(DetachedElement {tag: "BUTTON"}) -> Right $ TopCardInsightContentButton b
- Right p@(DetachedElement _), Right s, _ -> Right $ TopCardInsightContentSecondary {primary: p, secondary: s}
- _, _, Right el@(DetachedElement _) -> Right $ TopCardInsightContentSingle el
- _, _, _ -> Left TextNotFoundError
- parseTopCardInsight :: Parser (TopCardInsight DetachedNode)
- parseTopCardInsight n = do
- icon <- queryAndDetachOne ":scope li-icon" n
- svg <- queryAndDetachOne ":scope svg" n
- content <- queryOneAndParse ":scope > span" parseTopCardInsightContent n
- actionButton <- queryOneAndParse ":scope > button" parseTopCardInsightContent n
- pure $ ado
- i <- icon <|> svg
- c <- content <|> actionButton
- in TopCardInsight {icon: i, content: c}
- parseTopCardPrimaryDescription :: Parser (TopCardPrimaryDescription DetachedNode)
- parseTopCardPrimaryDescription n = do
- link <- queryAndDetachOne ":scope > a" n
- text <- detachNonEmptyTextChild n
- tvmText <- queryAndDetachMany "span.tvm__text" n
- pure $ ado
- l <- link
- t <- text
- in TopCardPrimaryDescription {link: l, text: t, tvmText: hush tvmText}
- parseJobsUnifiedTopCardElement :: Parser (JobsUnifiedTopCardElement DetachedNode)
- parseJobsUnifiedTopCardElement n = do
- h1 <- queryAndDetachOne "h1.job-details-jobs-unified-top-card__job-title" n
- primary <- queryOneAndParse
- "div.job-details-jobs-unified-top-card__primary-description-container > div"
- parseTopCardPrimaryDescription
- n
- insights <- queryManyAndParse
- "li.job-details-jobs-unified-top-card__job-insight"
- parseTopCardInsight
- n
- actions <- queryManyAndParse
- ".mt5 button"
- parseTopCardAction
- n
- pure $ ado
- h <- h1
- p <- primary
- in JobsUnifiedTopCardElement {
- header: h,
- primaryDescription: p,
- insights: hush insights,
- actions: hush actions
- }
- toHeader ∷ forall a. JobsUnifiedTopCardElement a → a
- toHeader (JobsUnifiedTopCardElement {header}) = header
- toPrimaryDescriptionLink ∷ forall a. JobsUnifiedTopCardElement a → a
- toPrimaryDescriptionLink (JobsUnifiedTopCardElement {
- primaryDescription: TopCardPrimaryDescription {link}
- }) = link
- toPrimaryDescriptionText ∷ forall a. JobsUnifiedTopCardElement a → a
- toPrimaryDescriptionText (JobsUnifiedTopCardElement {
- primaryDescription: TopCardPrimaryDescription {text}
- }) = text
|