Skip to content
This repository was archived by the owner on Jul 19, 2022. It is now read-only.

Commit c829da2

Browse files
authored
Merge pull request #293 from unisonweb/fetch-catalog
Catalog: Fetch catalog doc and projects and render
2 parents d4e5aa6 + adac694 commit c829da2

File tree

10 files changed

+627
-87
lines changed

10 files changed

+627
-87
lines changed

src/Api.elm

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Api exposing
1010
, perform
1111
, projects
1212
, toRequest
13+
, toTask
1314
, toUrl
1415
)
1516

@@ -20,6 +21,7 @@ import Json.Decode as Decode
2021
import Perspective exposing (Perspective(..))
2122
import Regex
2223
import Syntax
24+
import Task exposing (Task)
2325
import Url.Builder exposing (QueryParameter, absolute, int, string)
2426

2527

@@ -31,6 +33,11 @@ type Endpoint
3133
= Endpoint (List String) (List QueryParameter)
3234

3335

36+
toUrl : ApiBasePath -> Endpoint -> String
37+
toUrl (ApiBasePath basePath) (Endpoint paths queryParams) =
38+
absolute (basePath ++ paths) queryParams
39+
40+
3441
codebaseHash : Endpoint
3542
codebaseHash =
3643
Endpoint [ "list" ] [ string "namespace" "." ]
@@ -107,11 +114,6 @@ type ApiRequest a msg
107114
= ApiRequest Endpoint (Decode.Decoder a) (Result Http.Error a -> msg)
108115

109116

110-
toUrl : ApiBasePath -> Endpoint -> String
111-
toUrl (ApiBasePath basePath) (Endpoint paths queryParams) =
112-
absolute (basePath ++ paths) queryParams
113-
114-
115117
toRequest : Decode.Decoder a -> (Result Http.Error a -> msg) -> Endpoint -> ApiRequest a msg
116118
toRequest decoder toMsg endpoint =
117119
ApiRequest endpoint decoder toMsg
@@ -126,6 +128,46 @@ perform basePath (ApiRequest endpoint decoder toMsg) =
126128

127129

128130

131+
--- TASK ----------------------------------------------------------------------
132+
133+
134+
{-| TODO Perhaps this API should be merged into ApiRequest fully?? |
135+
-}
136+
toTask : ApiBasePath -> Decode.Decoder a -> Endpoint -> Task Http.Error a
137+
toTask basePath decoder endpoint =
138+
Http.task
139+
{ method = "GET"
140+
, headers = []
141+
, url = toUrl basePath endpoint
142+
, body = Http.emptyBody
143+
, resolver = Http.stringResolver (httpJsonBodyResolver decoder)
144+
, timeout = Nothing
145+
}
146+
147+
148+
httpJsonBodyResolver : Decode.Decoder a -> Http.Response String -> Result Http.Error a
149+
httpJsonBodyResolver decoder resp =
150+
case resp of
151+
Http.GoodStatus_ _ s ->
152+
Decode.decodeString decoder s
153+
|> Result.mapError (Decode.errorToString >> Http.BadBody)
154+
155+
Http.BadUrl_ s ->
156+
Err (Http.BadUrl s)
157+
158+
Http.Timeout_ ->
159+
Err Http.Timeout
160+
161+
Http.NetworkError_ ->
162+
Err Http.NetworkError
163+
164+
Http.BadStatus_ m s ->
165+
Decode.decodeString decoder s
166+
-- just trying; if our decoder understands the response body, great
167+
|> Result.mapError (\_ -> Http.BadStatus m.statusCode)
168+
169+
170+
129171
-- ERROR ----------------------------------------------------------------------
130172

131173

src/Hash.elm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Hash exposing
1313
, toShortString
1414
, toString
1515
, toUrlString
16+
, unsafeFromString
1617
, urlParser
1718
, urlPrefix
1819
)
@@ -94,6 +95,14 @@ fromString raw =
9495
Nothing
9596

9697

98+
{-| !! Don't use this function outside of testing. It provides no guarantees
99+
for the correctness of the Hash.
100+
-}
101+
unsafeFromString : String -> Hash
102+
unsafeFromString raw =
103+
Hash raw
104+
105+
97106
isRawHash : String -> Bool
98107
isRawHash str =
99108
String.startsWith prefix str || String.startsWith urlPrefix str

src/Project.elm

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,49 @@
11
module Project exposing (..)
22

3-
import FullyQualifiedName exposing (FQN)
4-
import Json.Decode as Decode
3+
import FullyQualifiedName as FQN exposing (FQN)
4+
import Hash exposing (Hash)
5+
import Json.Decode as Decode exposing (field, string)
56

67

78
type Owner
89
= Owner String
910

1011

1112
type alias Project a =
12-
{ a | owner : Owner, name : FQN }
13+
{ a | owner : Owner, name : FQN, hash : Hash }
1314

1415

1516
type alias ProjectListing =
1617
Project {}
1718

1819

20+
slug : Project a -> FQN
21+
slug project =
22+
FQN.cons (ownerToString project.owner) project.name
23+
24+
1925
ownerToString : Owner -> String
2026
ownerToString (Owner o) =
2127
o
2228

2329

24-
decodeList : Decode.Decoder (List ProjectListing)
25-
decodeList =
26-
Decode.succeed []
30+
31+
-- Decode
32+
33+
34+
decodeListing : Decode.Decoder ProjectListing
35+
decodeListing =
36+
let
37+
mk owner name hash =
38+
{ owner = owner, name = name, hash = hash }
39+
in
40+
Decode.map3
41+
mk
42+
(field "owner" (Decode.map Owner string))
43+
(field "name" FQN.decode)
44+
(field "hash" Hash.decode)
45+
46+
47+
decodeListings : Decode.Decoder (List ProjectListing)
48+
decodeListings =
49+
Decode.list decodeListing

src/UnisonShare/App.elm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ init env route navKey =
7676
|> Maybe.map (Api.perform env.apiBasePath)
7777
|> Maybe.withDefault Cmd.none
7878

79-
( catalog, _ ) =
79+
( catalog, catalogCmd ) =
8080
Catalog.init env
8181

8282
model =
@@ -96,6 +96,7 @@ init env route navKey =
9696
, Cmd.batch
9797
[ Cmd.map CodebaseTreeMsg codebaseTreeCmd
9898
, Cmd.map WorkspaceMsg workspaceCmd
99+
, Cmd.map CatalogMsg catalogCmd
99100
, fetchNamespaceDetailsCmd
100101
]
101102
)
@@ -153,7 +154,7 @@ update msg ({ env } as model) =
153154
( catalog, cmd ) =
154155
Catalog.init model.env
155156
in
156-
( { model | catalog = catalog }, Cmd.map CatalogMsg cmd )
157+
( { model2 | catalog = catalog }, Cmd.map CatalogMsg cmd )
157158

158159
Route.Definition params ref ->
159160
let

src/UnisonShare/Catalog.elm

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
module UnisonShare.Catalog exposing (..)
2+
3+
import Dict exposing (Dict)
4+
import FullyQualifiedName as FQN
5+
import Json.Decode as Decode
6+
import Project exposing (ProjectListing)
7+
import UnisonShare.Catalog.CatalogMask as CatalogMask exposing (CatalogMask)
8+
9+
10+
type Catalog
11+
= Catalog (Dict String (List ProjectListing))
12+
13+
14+
15+
-- CREATE
16+
17+
18+
empty : Catalog
19+
empty =
20+
Catalog Dict.empty
21+
22+
23+
catalog : CatalogMask -> List ProjectListing -> Catalog
24+
catalog mask projectListings_ =
25+
let
26+
catalog_ project ((Catalog dict) as acc) =
27+
let
28+
projectName =
29+
project
30+
|> Project.slug
31+
|> FQN.toString
32+
33+
categoryName =
34+
CatalogMask.categoryOf projectName mask
35+
36+
set old =
37+
case old of
38+
Just ps ->
39+
Just (ps ++ [ project ])
40+
41+
Nothing ->
42+
Just [ project ]
43+
in
44+
case categoryName of
45+
Just c ->
46+
Catalog (Dict.update c set dict)
47+
48+
Nothing ->
49+
acc
50+
in
51+
List.foldl catalog_ empty projectListings_
52+
53+
54+
55+
-- HELPERS
56+
57+
58+
isEmpty : Catalog -> Bool
59+
isEmpty (Catalog dict) =
60+
Dict.isEmpty dict
61+
62+
63+
categories : Catalog -> List String
64+
categories (Catalog dict) =
65+
Dict.keys dict
66+
67+
68+
projectListings : Catalog -> List ProjectListing
69+
projectListings (Catalog dict) =
70+
List.concat (Dict.values dict)
71+
72+
73+
toList : Catalog -> List ( String, List ProjectListing )
74+
toList (Catalog dict) =
75+
Dict.toList dict
76+
77+
78+
79+
-- DECODE
80+
81+
82+
decodeCatalogMask : Decode.Decoder CatalogMask
83+
decodeCatalogMask =
84+
CatalogMask.decode

0 commit comments

Comments
 (0)