WorkExperience.purs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. module LinkedIn.Profile.WorkExperience where
  2. import LinkedIn.UIElements.Parser
  3. import Prelude
  4. import Data.Either (Either(..), hush, note)
  5. import Data.Generic.Rep (class Generic)
  6. import Data.List (List(..))
  7. import Data.List as L
  8. import Data.List.NonEmpty (NonEmptyList)
  9. import Data.List.NonEmpty as NEL
  10. import Data.Maybe (Maybe(..))
  11. import Data.Show.Generic (genericShow)
  12. import LinkedIn (DetachedNode(..))
  13. import LinkedIn.ArtDecoCard (ArtDecoCardElement(..), ArtDecoCenter(..), ArtDecoCenterContent(..), ArtDecoCenterHeader(..), ArtDecoPvsEntity(..), ArtDecoPvsEntitySubComponent(..))
  14. import LinkedIn.UIElements.Types (Duration, TimeSpan, UIElement(..))
  15. import Parsing (ParseError, runParser)
  16. data WorkExperience = WorkExperience {
  17. position :: String,
  18. company :: Maybe String,
  19. contractType :: Maybe String,
  20. timeSpan :: Maybe TimeSpan,
  21. duration :: Maybe Duration,
  22. description :: Maybe String
  23. }
  24. derive instance Generic WorkExperience _
  25. instance Show WorkExperience where
  26. show = genericShow
  27. fromUI ∷ ArtDecoCardElement → Either String WorkExperience
  28. fromUI (ArtDecoCardElement {
  29. pvs_entity: ArtDecoPvsEntity {
  30. center: ArtDecoCenter {
  31. header: ArtDecoCenterHeader {
  32. bold: bold,
  33. normal,
  34. light
  35. },
  36. content: ArtDecoCenterContent subComponents
  37. }
  38. }
  39. }) = ado
  40. position <- extractPosition bold'
  41. in
  42. WorkExperience {
  43. position,
  44. company: maybeExtractFromMaybe extractCompany normal',
  45. contractType: maybeExtractFromMaybe extractContractType normal',
  46. timeSpan: hush $ extractTimeSpan light',
  47. duration: hush $ extractDuration light',
  48. description: hush $ extractDescription content'
  49. } where
  50. bold' = toUIElement bold
  51. content' :: List (Either ParseError UIElement)
  52. content' = map toUIElement subC
  53. where subC = NEL.catMaybes $ map (\(ArtDecoPvsEntitySubComponent c) -> c) subComponents :: List (DetachedNode)
  54. normal' :: Maybe (Either ParseError UIElement)
  55. normal' = toUIElement <$> normal
  56. light' :: Maybe (NonEmptyList (Either ParseError UIElement))
  57. light' = (map toUIElement) <$> light
  58. extractPosition ∷ Either ParseError UIElement → Either String String
  59. extractPosition bold = case bold of
  60. Right (UIPlainText str) -> Right str
  61. _ -> Left "No position"
  62. maybeExtractFromMaybe ∷
  63. ∀ a. (Either ParseError UIElement → Either String a)
  64. → Maybe (Either ParseError UIElement)
  65. → Maybe a
  66. maybeExtractFromMaybe extract maybeNode = hush $ (extract <=< note "silent fail") maybeNode
  67. extractCompany ∷ Either ParseError UIElement → Either String String
  68. extractCompany = case _ of
  69. Right (UIPlainText str) -> Right str
  70. Right (UIDotSeparated (UIPlainText str) _) -> Right str
  71. _ -> Left "No company"
  72. extractContractType ∷ Either ParseError UIElement → Either String String
  73. extractContractType = case _ of
  74. Right (UIDotSeparated _ (UIPlainText str)) -> Right str
  75. _ -> Left "No company"
  76. extractTimeSpan ∷ Maybe (NonEmptyList (Either ParseError UIElement)) → Either String TimeSpan
  77. extractTimeSpan light = case light of
  78. Just l -> note "No timespan" $ NEL.findMap getTimeSpan l
  79. Nothing -> Left "No timespan"
  80. where
  81. getTimeSpan (Right (UIDotSeparated (UITimeSpan s) _)) = Just s
  82. getTimeSpan _ = Nothing
  83. extractDuration ∷ Maybe (NonEmptyList (Either ParseError UIElement)) → Either String Duration
  84. extractDuration light = case light of
  85. Just l -> note "No duration" $ NEL.findMap getDuration l
  86. Nothing -> Left "No duration"
  87. where
  88. getDuration (Right (UIDotSeparated _ (UIDuration d))) = Just d
  89. getDuration _ = Nothing
  90. extractDescription ∷ List (Either ParseError UIElement) → Either String String
  91. extractDescription Nil = Left "no description"
  92. extractDescription cs = case L.head cs of
  93. Just (Right (UIPlainText d)) -> Right d
  94. _ -> Left "No description"
  95. toUIElement ∷ DetachedNode → Either ParseError UIElement
  96. toUIElement (DetachedElement {content}) = runParser content uiElementP
  97. toUIElement (DetachedComment str) = runParser str uiElementP
  98. toUIElement (DetachedText str) = runParser str uiElementP