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

Commit 076f39e

Browse files
authored
Merge pull request #223 from unisonweb/render-readme
Add support for a Namespace Readme
2 parents b5b5c5d + 4d477eb commit 076f39e

18 files changed

+610
-169
lines changed

src/Api.elm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module Api exposing
55
, find
66
, getDefinition
77
, list
8+
, namespace
89
, perform
910
, toRequest
1011
, toUrl
@@ -36,10 +37,19 @@ type Endpoint
3637
list : PerspectiveParams -> Maybe String -> Endpoint
3738
list perspectiveParams fqnOrHash =
3839
let
39-
namespace =
40+
namespace_ =
4041
Maybe.withDefault "." fqnOrHash
4142
in
42-
Endpoint [ "list" ] (string "namespace" namespace :: perspectiveParamsToQueryParams perspectiveParams)
43+
Endpoint [ "list" ] (string "namespace" namespace_ :: perspectiveParamsToQueryParams perspectiveParams)
44+
45+
46+
namespace : Perspective -> FQN -> Endpoint
47+
namespace perspective fqn =
48+
let
49+
queryParams =
50+
[ rootBranch (Perspective.codebaseHash perspective) ]
51+
in
52+
Endpoint [ "namespaces", FQN.toString fqn ] queryParams
4353

4454

4555
getDefinition : Perspective -> List String -> Endpoint

src/App.elm

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import Http
1616
import KeyboardShortcut
1717
import KeyboardShortcut.Key as Key exposing (Key(..))
1818
import KeyboardShortcut.KeyboardEvent as KeyboardEvent exposing (KeyboardEvent)
19+
import Namespace exposing (NamespaceDetails)
1920
import Perspective exposing (Perspective(..))
21+
import PerspectiveLanding
22+
import RemoteData
2023
import Route exposing (Route)
2124
import UI
2225
import UI.Button as Button
@@ -44,11 +47,13 @@ type alias Model =
4447
, route : Route
4548
, codebaseTree : CodebaseTree.Model
4649
, workspace : Workspace.Model
50+
, perspectiveLanding : PerspectiveLanding.Model
4751
, modal : Modal
4852
, keyboardShortcut : KeyboardShortcut.Model
4953
, env : Env
5054

51-
-- This is called "toggled" and not "hidden" because the behavior if toggling the sidebar on/off is inverse on mobile vs desktop
55+
-- This is called "toggled" and not "hidden" because the behavior of
56+
-- toggling the sidebar on/off is inverse on mobile vs desktop
5257
, sidebarToggled : Bool
5358
}
5459

@@ -67,10 +72,17 @@ init env route navKey =
6772
( codebaseTree, codebaseTreeCmd ) =
6873
CodebaseTree.init env
6974

75+
fetchNamespaceDetailsCmd =
76+
env.perspective
77+
|> fetchNamespaceDetails
78+
|> Maybe.map (Api.perform env.apiBasePath)
79+
|> Maybe.withDefault Cmd.none
80+
7081
model =
7182
{ navKey = navKey
7283
, route = route
7384
, workspace = workspace
85+
, perspectiveLanding = PerspectiveLanding.init
7486
, codebaseTree = codebaseTree
7587
, modal = NoModal
7688
, keyboardShortcut = KeyboardShortcut.init env.operatingSystem
@@ -82,6 +94,7 @@ init env route navKey =
8294
, Cmd.batch
8395
[ Cmd.map CodebaseTreeMsg codebaseTreeCmd
8496
, Cmd.map WorkspaceMsg workspaceCmd
97+
, fetchNamespaceDetailsCmd
8598
]
8699
)
87100

@@ -94,6 +107,7 @@ type Msg
94107
= LinkClicked Browser.UrlRequest
95108
| UrlChanged Url
96109
| ChangePerspective Perspective
110+
| FetchPerspectiveNamespaceDetailsFinished FQN (Result Http.Error NamespaceDetails)
97111
| Keydown KeyboardEvent
98112
| OpenDefinition Reference
99113
| ShowModal Modal
@@ -102,6 +116,7 @@ type Msg
102116
-- sub msgs
103117
| FinderMsg Finder.Msg
104118
| WorkspaceMsg Workspace.Msg
119+
| PerspectiveLandingMsg PerspectiveLanding.Msg
105120
| CodebaseTreeMsg CodebaseTree.Msg
106121
| KeyboardShortcutMsg KeyboardShortcut.Msg
107122

@@ -121,6 +136,25 @@ update msg ({ env } as model) =
121136
ChangePerspective perspective ->
122137
replacePerspective model perspective
123138

139+
FetchPerspectiveNamespaceDetailsFinished fqn details ->
140+
let
141+
perspective =
142+
case env.perspective of
143+
Namespace p ->
144+
if FQN.equals p.fqn fqn then
145+
Namespace { p | details = RemoteData.fromResult details }
146+
147+
else
148+
env.perspective
149+
150+
_ ->
151+
env.perspective
152+
153+
nextEnv =
154+
{ env | perspective = perspective }
155+
in
156+
( { model | env = nextEnv }, Cmd.none )
157+
124158
Keydown event ->
125159
keydown model event
126160

@@ -150,6 +184,24 @@ update msg ({ env } as model) =
150184
in
151185
( model3, Cmd.batch [ cmd, Cmd.map WorkspaceMsg wCmd ] )
152186

187+
PerspectiveLandingMsg rMsg ->
188+
let
189+
( perspectiveLanding, outMsg ) =
190+
PerspectiveLanding.update rMsg model.perspectiveLanding
191+
192+
model2 =
193+
{ model | perspectiveLanding = perspectiveLanding }
194+
in
195+
case outMsg of
196+
PerspectiveLanding.OpenDefinition ref ->
197+
openDefinition model2 ref
198+
199+
PerspectiveLanding.ShowFinderRequest ->
200+
showFinder model2 Nothing
201+
202+
PerspectiveLanding.None ->
203+
( model2, Cmd.none )
204+
153205
CodebaseTreeMsg cMsg ->
154206
let
155207
( codebaseTree, cCmd, outMsg ) =
@@ -231,9 +283,19 @@ replacePerspective ({ env } as model) perspective =
231283

232284
changeRouteCmd =
233285
Route.replacePerspective model.navKey (Perspective.toParams perspective) model.route
286+
287+
fetchNamespaceDetailsCmd =
288+
perspective
289+
|> fetchNamespaceDetails
290+
|> Maybe.map (Api.perform env.apiBasePath)
291+
|> Maybe.withDefault Cmd.none
234292
in
235293
( { model | env = newEnv, codebaseTree = codebaseTree }
236-
, Cmd.batch [ Cmd.map CodebaseTreeMsg codebaseTreeCmd, changeRouteCmd ]
294+
, Cmd.batch
295+
[ Cmd.map CodebaseTreeMsg codebaseTreeCmd
296+
, changeRouteCmd
297+
, fetchNamespaceDetailsCmd
298+
]
237299
)
238300

239301

@@ -310,6 +372,27 @@ showFinder model withinNamespace =
310372
( { model | modal = FinderModal fm }, Cmd.map FinderMsg fcmd )
311373

312374

375+
376+
-- EFFECTS
377+
378+
379+
fetchNamespaceDetails : Perspective -> Maybe (Api.ApiRequest NamespaceDetails Msg)
380+
fetchNamespaceDetails perspective =
381+
case perspective of
382+
Namespace { fqn } ->
383+
fqn
384+
|> Api.namespace perspective
385+
|> Api.toRequest Namespace.decodeDetails (FetchPerspectiveNamespaceDetailsFinished fqn)
386+
|> Just
387+
388+
_ ->
389+
Nothing
390+
391+
392+
393+
-- SUBSCRIPTIONS
394+
395+
313396
subscriptions : Model -> Sub Msg
314397
subscriptions model =
315398
Sub.batch
@@ -609,13 +692,25 @@ view model =
609692

610693
Ucm ->
611694
"Unison Local"
695+
696+
page =
697+
case model.route of
698+
Route.Perspective _ ->
699+
Html.map PerspectiveLandingMsg
700+
(PerspectiveLanding.view
701+
model.env
702+
model.perspectiveLanding
703+
)
704+
705+
Route.Definition _ _ ->
706+
Html.map WorkspaceMsg (Workspace.view model.workspace)
612707
in
613708
{ title = title_
614709
, body =
615710
[ div [ id "app", classList [ ( "sidebar-toggled", model.sidebarToggled ) ] ]
616711
[ viewMainHeader model
617712
, viewMainSidebar model
618-
, div [ id "main-content" ] [ Html.map WorkspaceMsg (Workspace.view model.env model.workspace) ]
713+
, div [ id "main-content" ] [ page ]
619714
, viewModal model
620715
]
621716
]

src/Definition/Readme.elm

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module Definition.Readme exposing (..)
2+
3+
import Definition.Doc as Doc exposing (Doc, DocFoldToggles, FoldId)
4+
import Definition.Reference exposing (Reference)
5+
import Html exposing (Html, div, header, text)
6+
import Html.Attributes exposing (class)
7+
import Json.Decode as Decode
8+
import UI.Icon as Icon
9+
10+
11+
{-| Represent the Readme Doc definition of a namespace. This is typically
12+
rendered slightly different than other docs when viewed from a Namespace
13+
landing page point of view.
14+
-}
15+
type Readme
16+
= Readme Doc
17+
18+
19+
20+
-- VIEW
21+
22+
23+
view :
24+
(Reference -> msg)
25+
-> (FoldId -> msg)
26+
-> DocFoldToggles
27+
-> Readme
28+
-> Html msg
29+
view refToMsg toggleFoldMsg docFoldToggles (Readme doc) =
30+
div [ class "readme" ]
31+
[ header [] [ Icon.view Icon.doc, text "README" ]
32+
, Doc.view refToMsg toggleFoldMsg docFoldToggles doc
33+
]
34+
35+
36+
37+
-- DECODE
38+
39+
40+
decode : Decode.Decoder Readme
41+
decode =
42+
Decode.map Readme Doc.decode

src/Namespace.elm

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module Namespace exposing (..)
2+
3+
import Definition.Readme as Readme exposing (Readme)
4+
import FullyQualifiedName as FQN exposing (FQN)
5+
import Hash exposing (Hash)
6+
import Json.Decode as Decode exposing (field, maybe)
7+
8+
9+
type Namespace a
10+
= Namespace FQN Hash a
11+
12+
13+
type alias NamespaceDetailsFields =
14+
{ readme : Maybe Readme }
15+
16+
17+
type alias NamespaceDetails =
18+
Namespace NamespaceDetailsFields
19+
20+
21+
22+
-- Helpers --------------------------------------------------------------------
23+
24+
25+
fqn : Namespace a -> FQN
26+
fqn (Namespace fqn_ _ _) =
27+
fqn_
28+
29+
30+
hash : Namespace a -> Hash
31+
hash (Namespace _ h _) =
32+
h
33+
34+
35+
readme : NamespaceDetails -> Maybe Readme
36+
readme (Namespace _ _ details) =
37+
details.readme
38+
39+
40+
41+
-- Decode ---------------------------------------------------------------------
42+
43+
44+
decodeDetails : Decode.Decoder NamespaceDetails
45+
decodeDetails =
46+
let
47+
makeDetails fqn_ hash_ readme_ =
48+
Namespace fqn_ hash_ { readme = readme_ }
49+
in
50+
Decode.map3 makeDetails
51+
(field "fqn" FQN.decode)
52+
(field "hash" Hash.decode)
53+
(maybe (field "readme" Readme.decode))

src/Perspective.elm

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ module Perspective exposing (..)
33
import FullyQualifiedName as FQN exposing (FQN)
44
import Hash exposing (Hash)
55
import Json.Decode as Decode exposing (field)
6+
import Namespace exposing (NamespaceDetails)
7+
import RemoteData exposing (RemoteData(..), WebData)
68

79

810
type Perspective
911
= Codebase Hash
10-
| Namespace { codebaseHash : Hash, fqn : FQN }
12+
| Namespace
13+
{ codebaseHash : Hash
14+
, fqn : FQN
15+
, details : WebData NamespaceDetails
16+
}
1117

1218

1319
toNamespacePerspective : Perspective -> FQN -> Perspective
1420
toNamespacePerspective perspective fqn_ =
15-
Namespace { codebaseHash = codebaseHash perspective, fqn = fqn_ }
21+
Namespace { codebaseHash = codebaseHash perspective, fqn = fqn_, details = NotAsked }
1622

1723

1824
codebaseHash : Perspective -> Hash
@@ -58,7 +64,7 @@ fromParams params =
5864
Just (Codebase h)
5965

6066
ByNamespace (Absolute h) fqn_ ->
61-
Just (Namespace { codebaseHash = h, fqn = fqn_ })
67+
Just (Namespace { codebaseHash = h, fqn = fqn_, details = NotAsked })
6268

6369

6470

@@ -74,7 +80,7 @@ decode perspectiveParams =
7480
Codebase codebaseHash_
7581

7682
ByNamespace _ fqn_ ->
77-
Namespace { codebaseHash = codebaseHash_, fqn = fqn_ }
83+
Namespace { codebaseHash = codebaseHash_, fqn = fqn_, details = NotAsked }
7884
in
7985
Decode.map make (field "namespaceListingHash" Hash.decode)
8086

0 commit comments

Comments
 (0)