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

Commit b5ae8e3

Browse files
authored
Merge pull request #278 from unisonweb/download-modal-2
Add DownloadModal with click to copy
2 parents 53ef0dd + 2524205 commit b5ae8e3

File tree

14 files changed

+312
-36
lines changed

14 files changed

+312
-36
lines changed

src/App.elm

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Env.AppContext as AppContext exposing (AppContext(..))
1010
import Finder
1111
import Finder.SearchOptions as SearchOptions
1212
import FullyQualifiedName as FQN exposing (FQN)
13-
import Html exposing (Html, a, div, h1, h2, h3, header, nav, p, section, span, strong, text)
13+
import Html exposing (Html, a, div, h1, h2, h3, nav, p, section, span, strong, text)
1414
import Html.Attributes exposing (class, classList, href, id, rel, target, title)
1515
import Html.Events exposing (onClick)
1616
import Http
@@ -27,6 +27,7 @@ import UI.AppHeader as AppHeader
2727
import UI.Banner as Banner
2828
import UI.Button as Button
2929
import UI.Click as Click exposing (Click(..))
30+
import UI.CopyField as CopyField
3031
import UI.Icon as Icon
3132
import UI.Modal as Modal
3233
import UI.Sidebar as Sidebar
@@ -47,6 +48,7 @@ type Modal
4748
| HelpModal
4849
| ReportBugModal
4950
| PublishModal
51+
| DownloadModal FQN
5052

5153

5254
type alias Model =
@@ -499,8 +501,8 @@ viewAppHeader model =
499501
}
500502

501503

502-
viewPerspective : Env -> Html Msg
503-
viewPerspective env =
504+
viewSidebarHeader : Env -> Html Msg
505+
viewSidebarHeader env =
504506
case env.perspective of
505507
Codebase _ ->
506508
UI.nothing
@@ -513,11 +515,27 @@ viewPerspective env =
513515
-- thats quite involved...
514516
isOverflowing =
515517
fqn |> FQN.toString |> String.length |> (\l -> l > 20)
518+
519+
download =
520+
case env.appContext of
521+
UnisonShare ->
522+
Button.iconThenLabel (ShowModal (DownloadModal fqn)) Icon.download "Download latest version"
523+
|> Button.small
524+
|> Button.view
525+
|> List.singleton
526+
|> Sidebar.headerItem []
527+
528+
Ucm ->
529+
UI.nothing
516530
in
517-
header
518-
[ classList [ ( "perspective", True ), ( "is-overflowing", isOverflowing ) ] ]
519-
[ UI.namespaceSlug
520-
, h2 [ class "namespace" ] [ FQN.view fqn ]
531+
Sidebar.header
532+
[ Sidebar.headerItem
533+
[ classList [ ( "is-overflowing", isOverflowing ) ] ]
534+
[ UI.namespaceSlug
535+
, h2 [ class "namespace" ] [ FQN.view fqn ]
536+
]
537+
, download
538+
, UI.divider
521539
]
522540

523541

@@ -588,7 +606,7 @@ viewMainSidebar model =
588606
Sidebar.view
589607
[ viewMainSidebarCollapseButton model
590608
, div [ class "expanded-content" ]
591-
[ viewPerspective model.env
609+
[ viewSidebarHeader model.env
592610
, div [ class "sidebar-scroll-area" ]
593611
[ sidebarContent
594612
, Sidebar.section
@@ -622,6 +640,33 @@ viewMainSidebar model =
622640
]
623641

624642

643+
viewDownloadModal : FQN -> Html Msg
644+
viewDownloadModal fqn =
645+
let
646+
prettyName =
647+
FQN.toString fqn
648+
649+
unqualified =
650+
FQN.unqualifiedName fqn
651+
652+
pullCommand =
653+
"pull git@github.com:unisonweb/share.git:." ++ prettyName ++ " ." ++ unqualified
654+
655+
content =
656+
Modal.Content
657+
(section
658+
[]
659+
[ p [] [ text "Download ", UI.bold prettyName, text " by pulling the namespace from Unison Share into a namespace in your local codebase:" ]
660+
, CopyField.copyField (\_ -> CloseModal) pullCommand |> CopyField.withPrefix ".>" |> CopyField.view
661+
, div [ class "hint" ] [ text "Copy and paste this command into UCM." ]
662+
]
663+
)
664+
in
665+
Modal.modal "download-modal" CloseModal content
666+
|> Modal.withHeader ("Download " ++ prettyName)
667+
|> Modal.view
668+
669+
625670
viewHelpModal : OperatingSystem -> KeyboardShortcut.Model -> Html Msg
626671
viewHelpModal os keyboardShortcut =
627672
let
@@ -771,6 +816,9 @@ viewModal model =
771816
ReportBugModal ->
772817
viewReportBugModal model.env.appContext
773818

819+
DownloadModal fqn ->
820+
viewDownloadModal fqn
821+
774822

775823
viewAppLoading : AppContext -> Html msg
776824
viewAppLoading appContext =

src/UI.elm

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module UI exposing (..)
22

3-
import Html exposing (Attribute, Html, code, div, hr, pre, span, text)
3+
import Html exposing (Attribute, Html, code, div, hr, pre, span, strong, text)
44
import Html.Attributes exposing (class)
55
import Html.Events exposing (onClick)
66
import UI.Icon as Icon
@@ -11,6 +11,11 @@ codeBlock attrs code_ =
1111
pre attrs [ code [] [ code_ ] ]
1212

1313

14+
bold : String -> Html msg
15+
bold text_ =
16+
strong [] [ text text_ ]
17+
18+
1419
inlineCode : List (Attribute msg) -> Html msg -> Html msg
1520
inlineCode attrs code_ =
1621
code (class "inline-code" :: attrs) [ code_ ]
@@ -60,7 +65,7 @@ emptyStateMessage message =
6065

6166
divider : Html msg
6267
divider =
63-
hr [] []
68+
hr [ class "divider" ] []
6469

6570

6671
charWidth : Int -> String

src/UI/CopyField.elm

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
module UI.CopyField exposing (..)
2+
3+
import Html exposing (Html, button, div, input, node, text)
4+
import Html.Attributes exposing (attribute, class, readonly, type_, value)
5+
import UI
6+
import UI.Icon as Icon
7+
8+
9+
type alias CopyField msg =
10+
{ prefix : Maybe String
11+
, toCopy : String
12+
, onCopy : String -> msg
13+
}
14+
15+
16+
copyField : (String -> msg) -> String -> CopyField msg
17+
copyField onCopy toCopy =
18+
{ prefix = Nothing, toCopy = toCopy, onCopy = onCopy }
19+
20+
21+
withPrefix : String -> CopyField msg -> CopyField msg
22+
withPrefix prefix field =
23+
{ field | prefix = Just prefix }
24+
25+
26+
withToCopy : String -> CopyField msg -> CopyField msg
27+
withToCopy toCopy field =
28+
{ field | toCopy = toCopy }
29+
30+
31+
view : CopyField msg -> Html msg
32+
view field =
33+
let
34+
prefix =
35+
field.prefix
36+
|> Maybe.map (\p -> div [ class "copy-field-prefix" ] [ text p ])
37+
|> Maybe.withDefault UI.nothing
38+
in
39+
div [ class "copy-field" ]
40+
[ div [ class "copy-field-field" ]
41+
[ prefix
42+
, div
43+
[ class "copy-field-input" ]
44+
[ input
45+
[ type_ "text"
46+
, class "copy-field-to-copy"
47+
, value field.toCopy
48+
, readonly True
49+
]
50+
[]
51+
]
52+
]
53+
, copyButton field.toCopy
54+
]
55+
56+
57+
58+
-- HELPERS --------------------------------------------------------------------
59+
60+
61+
{-| We're not using UI.Button here since a click handler is added from
62+
the webcomponent in JS land.
63+
-}
64+
copyButton : String -> Html msg
65+
copyButton toCopy =
66+
node "copy-on-click"
67+
[ attribute "text" toCopy ]
68+
[ button [ class "button contained default" ] [ Icon.view Icon.clipboard ]
69+
]

src/UI/CopyOnClick.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// <copy-on-click text="text-to-copy">
2+
// clickable content
3+
// </copy-on-click>
4+
//
5+
// Use from Elm with an Icon:
6+
// node "copy-on-click" [ ] [ UI.Icon.view UI.Icon.clipboard ]
7+
class CopyOnClick extends HTMLElement {
8+
constructor() {
9+
super();
10+
}
11+
12+
connectedCallback() {
13+
this.addEventListener("click", () => {
14+
const text = this.getAttribute("text");
15+
16+
// writeText returns a promise with success/failure that we should
17+
// probably do something with...
18+
navigator.clipboard.writeText(text);
19+
});
20+
}
21+
22+
static get observedAttributes() {
23+
return ["text"];
24+
}
25+
}
26+
27+
customElements.define("copy-on-click", CopyOnClick);

src/UI/Icon.elm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,12 @@ tagsOutlined =
370370
, path [ fill "currentColor", fillRule "evenodd", d "M8.62836 2.16552C8.81309 1.96026 9.12923 1.94362 9.33449 2.12835L13.6332 5.99715C14.2238 6.52872 14.2974 7.42865 13.801 8.04914L10.3904 12.3123C10.2179 12.528 9.90329 12.5629 9.68766 12.3904C9.47203 12.2179 9.43707 11.9033 9.60957 11.6877L13.0201 7.42444C13.1856 7.21761 13.1611 6.91763 12.9642 6.74045L8.66552 2.87165C8.46027 2.68692 8.44363 2.37077 8.62836 2.16552Z" ] []
371371
, circle [ cx "4", cy "5", r "1.5", stroke "currentColor", fill "transparent" ] []
372372
]
373+
374+
375+
clipboard : Icon msg
376+
clipboard =
377+
Icon "clipboard"
378+
[]
379+
[ path [ fill "currentColor", fillRule "evenodd", d "M8 2.25C8 2.11193 7.88807 2 7.75 2H6.25C6.11193 2 6 2.11193 6 2.25V2.75C6 2.88807 6.11193 3 6.25 3H7.75C7.88807 3 8 2.88807 8 2.75V2.25ZM6 1C5.44772 1 5 1.44772 5 2V3C5 3.55228 5.44772 4 6 4H8C8.55228 4 9 3.55228 9 3V2C9 1.44772 8.55228 1 8 1H6Z" ] []
380+
, path [ fill "currentColor", fillRule "evenodd", d "M3 2.5C3 2.22386 3.22386 2 3.5 2C3.77614 2 4 2.22386 4 2.5V10.5C4 10.7761 4.22386 11 4.5 11H9.5C9.77614 11 10 10.7761 10 10.5V2.5C10 2.22386 10.2239 2 10.5 2C10.7761 2 11 2.22386 11 2.5V11C11 11.5523 10.5523 12 10 12H4C3.44772 12 3 11.5523 3 11V2.5Z" ] []
381+
]

src/UI/Sidebar.elm

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
module UI.Sidebar exposing (..)
22

3-
import Html exposing (Html, a, aside, h3, label, text)
3+
import Html exposing (Attribute, Html, a, aside, div, h3, label, text)
44
import Html.Attributes exposing (class, id)
55
import Html.Events exposing (onClick)
66

77

8+
header : List (Html msg) -> Html msg
9+
header content =
10+
Html.header [ class "sidebar-header" ] content
11+
12+
13+
headerItem : List (Attribute msg) -> List (Html msg) -> Html msg
14+
headerItem attrs content =
15+
div (attrs ++ [ class "sidebar-header-item" ]) content
16+
17+
818
section : String -> List (Html msg) -> Html msg
919
section label content =
1020
Html.section [ class "sidebar-section" ]
11-
(header label :: content)
21+
(sectionTitle label :: content)
1222

1323

14-
header : String -> Html msg
15-
header label =
16-
h3 [ class "sidebar-header" ] [ text label ]
24+
sectionTitle : String -> Html msg
25+
sectionTitle label =
26+
h3 [ class "sidebar-section-title" ] [ text label ]
1727

1828

1929
item : msg -> String -> Html msg

0 commit comments

Comments
 (0)