1
0
mirror of https://github.com/fluencelabs/dashboard synced 2025-03-16 21:30:49 +00:00
This commit is contained in:
DieMyst 2020-11-23 11:07:07 +03:00
commit cac58e7111
33 changed files with 19349 additions and 0 deletions

44
elm.json Normal file

@ -0,0 +1,44 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"Chadtech/unique-list": "2.1.4",
"avh4/elm-color": "1.0.0",
"ccapndave/elm-flat-map": "1.2.0",
"elm/browser": "1.0.2",
"elm/bytes": "1.0.8",
"elm/core": "1.0.5",
"elm/file": "1.0.5",
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/json": "1.1.3",
"elm/random": "1.0.0",
"elm/svg": "1.0.1",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm-community/graph": "6.0.0",
"elm-community/intdict": "3.0.0",
"ivadzy/bbase64": "1.1.1",
"mdgriffith/elm-ui": "1.1.8",
"mpizenberg/elm-pointer-events": "4.0.2",
"noahzgordon/elm-color-extra": "1.0.2",
"rtfeldman/elm-iso8601-date-strings": "1.1.3"
},
"indirect": {
"avh4/elm-fifo": "1.0.4",
"elm/parser": "1.1.0",
"elm/regex": "1.0.0",
"elm/virtual-dom": "1.0.2",
"elm-explorations/test": "1.2.2",
"fredcy/elm-parseint": "2.0.1"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}

BIN
favicon.ico Normal file

Binary file not shown.

After

Width: 48px  |  Height: 48px  |  Size: 15 KiB

21
index.html Normal file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="favicon" type="image/ico" href="favicon.ico" />
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<title>Fluence Admin</title>
</head>
<body>
<script src="bundle.js"></script>
<div id="root"></div>
</body>
</html>

17502
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

41
package.json Normal file

@ -0,0 +1,41 @@
{
"name": "fluence-admin",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-serve --open",
"pack": "webpack"
},
"repository": {
"type": "git",
"url": "git+https://github.com/fluencelabs/fluence-admin.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/fluencelabs/fluence-admin/issues"
},
"homepage": "https://github.com/fluencelabs/fluence-admin#readme",
"dependencies": {
"fluence": "0.7.76"
},
"devDependencies": {
"clean-webpack-plugin": "3.0.0",
"copy-webpack-plugin": "^4.6.0",
"html-webpack-plugin": "^4.4.1",
"http-server": "^0.12.3",
"ts-loader": "^8.0.3",
"elm-webpack-loader": "6.0.1",
"elm-hot-webpack-loader": "1.1.7",
"source-map-loader": "1.1.2",
"typescript": "^4.0.2",
"webpack": "^4.44.2",
"webpack-cli": "3.3.11",
"webpack-dev-server": "3.11.0",
"create-elm-app": "4.2.24",
"replace-in-file": "^6.0.0",
"@babel/core": "^7.10.4",
"webpack-serve": "2.0.3"
}
}

10
src/Config.elm Normal file

@ -0,0 +1,10 @@
module Config exposing (..)
type alias Config =
{ peerId: String
, windowSize : { width : Int, height : Int }
}
type alias Flags =
Config

160
src/Ions/Background.elm Normal file

@ -0,0 +1,160 @@
module Ions.Background exposing (..)
import Element.Background exposing (color)
import Ions.Color as TC
black =
color TC.black
nearBlack =
color TC.nearBlack
darkGray =
color TC.darkGray
midGray =
color TC.midGray
gray =
color TC.gray
silver =
color TC.silver
lightSilver =
color TC.lightSilver
moonGray =
color TC.moonGray
lightGray =
color TC.lightGray
nearWhite =
color TC.nearWhite
white =
color TC.white
transparent =
color TC.transparent
blackAlpha k =
color <| TC.blackAlpha k
whiteAlpha k =
color <| TC.whiteAlpha k
darkRed =
color TC.darkRed
red =
color TC.red
lightRed =
color TC.lightRed
orange =
color TC.orange
gold =
color TC.gold
yellow =
color TC.yellow
lightYellow =
color TC.lightYellow
purple =
color TC.purple
lightPurple =
color TC.lightPurple
darkPink =
color TC.darkPink
hotPink =
color TC.hotPink
pink =
color TC.pink
lightPink =
color TC.lightPink
darkGreen =
color TC.darkGreen
green =
color TC.green
lightGreen =
color TC.lightGreen
navy =
color TC.navy
darkBlue =
color TC.darkBlue
blue =
color TC.blue
lightBlue =
color TC.lightBlue
lightestBlue =
color TC.lightestBlue
washedBlue =
color TC.washedBlue
washedGreen =
color TC.washedGreen
washedYellow =
color TC.washedYellow
washedRed =
color TC.washedRed

300
src/Ions/Border.elm Normal file

@ -0,0 +1,300 @@
module Ions.Border exposing (..)
import Element
import Element.Border exposing (color, dotted, roundEach, rounded, widthEach, widthXY)
import Ions.Color as TC
import Ions.Size as S
type Side
= Left
| Right
| Top
| Bottom
| Sides
| TopBottom
| AllSides
type Corner
= Lefts
| Rights
| Tops
| Bottoms
| LeftTop
| RightTop
| LeftBottom
| RightBottom
| Diagonal
| CoDiagonal
| AllCorners
width : Int -> Side -> Element.Attribute msg
width w s =
case s of
Left ->
widthEach { bottom = 0, left = w, top = 0, right = 0 }
Right ->
widthEach { bottom = 0, left = 0, top = 0, right = w }
Top ->
widthEach { bottom = 0, left = 0, top = w, right = 0 }
Bottom ->
widthEach { bottom = w, left = 0, top = 0, right = 0 }
Sides ->
widthXY w 0
TopBottom ->
widthXY 0 w
AllSides ->
Element.Border.width w
radius : Int -> Corner -> Element.Attribute msg
radius w c =
case c of
Lefts ->
roundEach { topLeft = w, topRight = 0, bottomLeft = w, bottomRight = 0 }
Rights ->
roundEach { topLeft = 0, topRight = w, bottomLeft = 0, bottomRight = w }
Tops ->
roundEach { topLeft = w, topRight = w, bottomLeft = 0, bottomRight = 0 }
Bottoms ->
roundEach { topLeft = 0, topRight = 0, bottomLeft = w, bottomRight = w }
LeftTop ->
roundEach { topLeft = w, topRight = 0, bottomLeft = 0, bottomRight = 0 }
RightTop ->
roundEach { topLeft = 0, topRight = w, bottomLeft = 0, bottomRight = 0 }
LeftBottom ->
roundEach { topLeft = 0, topRight = 0, bottomLeft = w, bottomRight = 0 }
RightBottom ->
roundEach { topLeft = 0, topRight = 0, bottomLeft = w, bottomRight = w }
Diagonal ->
roundEach { topLeft = w, topRight = 0, bottomLeft = 0, bottomRight = w }
CoDiagonal ->
roundEach { topLeft = 0, topRight = w, bottomLeft = w, bottomRight = 0 }
AllCorners ->
rounded w
width0 =
width 0
width005 =
width <| S.baseRem 0.05
width1 =
width <| S.baseRem 0.125
width2 =
width <| S.baseRem 0.25
width3 =
width <| S.baseRem 0.5
width4 =
width <| S.baseRem 1
width5 =
width <| S.baseRem 2
radius0 =
rounded 0
radius1 =
rounded <| S.baseRem 0.125
radius2 =
rounded <| S.baseRem 0.25
radius3 =
rounded <| S.baseRem 0.5
radius4 =
rounded <| S.base
pill =
rounded 9999
black =
color TC.black
nearBlack =
color TC.nearBlack
darkGray =
color TC.darkGray
midGray =
color TC.midGray
gray =
color TC.gray
silver =
color TC.silver
lightSilver =
color TC.lightSilver
moonGray =
color TC.moonGray
lightGray =
color TC.lightGray
nearWhite =
color TC.nearWhite
white =
color TC.white
transparent =
color TC.transparent
blackAlpha k =
color <| TC.blackAlpha k
whiteAlpha k =
color <| TC.whiteAlpha k
darkRed =
color TC.darkRed
red =
color TC.red
lightRed =
color TC.lightRed
orange =
color TC.orange
gold =
color TC.gold
yellow =
color TC.yellow
lightYellow =
color TC.lightYellow
purple =
color TC.purple
lightPurple =
color TC.lightPurple
darkPink =
color TC.darkPink
hotPink =
color TC.hotPink
pink =
color TC.pink
lightPink =
color TC.lightPink
darkGreen =
color TC.darkGreen
green =
color TC.green
lightGreen =
color TC.lightGreen
navy =
color TC.navy
darkBlue =
color TC.darkBlue
blue =
color TC.blue
lightBlue =
color TC.lightBlue
lightestBlue =
color TC.lightestBlue
washedBlue =
color TC.washedBlue
washedGreen =
color TC.washedGreen
washedYellow =
color TC.washedYellow
washedRed =
color TC.washedRed

165
src/Ions/Color.elm Normal file

@ -0,0 +1,165 @@
module Ions.Color exposing (..)
import Element exposing (rgba255)
import Html.Attributes exposing (style)
import Ions.Color.Extra exposing (hexToColor)
easeIn =
Element.htmlAttribute <| style "transition" "color .15s ease-in"
black =
hexToColor "#000"
nearBlack =
hexToColor "#111"
darkGray =
hexToColor "#333"
midGray =
hexToColor "#555"
gray =
hexToColor "#777"
silver =
hexToColor "#999"
lightSilver =
hexToColor "#aaa"
moonGray =
hexToColor "#ccc"
lightGray =
hexToColor "#eee"
nearWhite =
hexToColor "#f4f4f4"
white =
hexToColor "#fff"
transparent =
rgba255 0 0 0 0
blackAlpha k =
rgba255 0 0 0 (k / 1000)
whiteAlpha k =
rgba255 255 255 255 (k / 1000)
darkRed =
hexToColor "#e7040f"
red =
hexToColor "#ff4136"
lightRed =
hexToColor "#ff725c"
orange =
hexToColor "#ff6300"
gold =
hexToColor "#ffb700"
yellow =
hexToColor "#ffde37"
lightYellow =
hexToColor "#fbf1a9"
purple =
hexToColor "#5e2ca5"
lightPurple =
hexToColor "#a463f2"
darkPink =
hexToColor "#d5008f"
hotPink =
hexToColor "#ff41b4"
pink =
hexToColor "#ff80cc"
lightPink =
hexToColor "#ffa3d7"
darkGreen =
hexToColor "#137752"
green =
hexToColor "#19a974"
lightGreen =
hexToColor "#9eebcf"
navy =
hexToColor "#001b44"
darkBlue =
hexToColor "#00449e"
blue =
hexToColor "#357edd"
lightBlue =
hexToColor "#96ccff"
lightestBlue =
hexToColor "#cdecff"
washedBlue =
hexToColor "#f6fffe"
washedGreen =
hexToColor "#e8fdf5"
washedYellow =
hexToColor "#fffceb"
washedRed =
hexToColor "#ffdfdf"

25
src/Ions/Color/Extra.elm Normal file

@ -0,0 +1,25 @@
module Ions.Color.Extra exposing (colorToHex, hexToColor)
import Color
import Color.Convert
import Element
toColor : Element.Color -> Color.Color
toColor =
Element.toRgb >> (\c -> Color.rgba c.red c.green c.blue c.alpha)
fromColor : Color.Color -> Element.Color
fromColor =
Color.toRgba >> (\c -> Element.rgba c.red c.green c.blue c.alpha)
colorToHex : Element.Color -> String
colorToHex =
toColor >> Color.Convert.colorToHex
hexToColor : String -> Element.Color
hexToColor =
Color.Convert.hexToColor >> Result.withDefault (Color.rgb 0 0 0) >> fromColor

201
src/Ions/Font.elm Normal file

@ -0,0 +1,201 @@
module Ions.Font exposing (..)
import Element.Font exposing (color, size)
import Ions.Color as TC
import Ions.Size as S
sansSerif =
Element.Font.family <| List.map Element.Font.typeface [ "-apple-system", "BlinkMacSystemFont", "avenir next", "avenir", "helvetica neue", "helvetica", "ubuntu", "roboto", "noto", "segoe ui", "arial", "sans-serif" ]
code =
Element.Font.family <| List.map Element.Font.typeface [ "Consolas", "monaco", "monospace" ]
baseSize =
size S.base
size1 =
size <| S.baseRem 3
size2 =
size <| S.baseRem 2.25
size3 =
size <| S.baseRem 1.5
size4 =
size <| S.baseRem 1.25
size5 =
size <| S.baseRem 1
size6 =
size <| S.baseRem 0.875
size7 =
size <| S.baseRem 0.75
black =
color TC.black
nearBlack =
color TC.nearBlack
darkGray =
color TC.darkGray
midGray =
color TC.midGray
gray =
color TC.gray
silver =
color TC.silver
lightSilver =
color TC.lightSilver
moonGray =
color TC.moonGray
lightGray =
color TC.lightGray
nearWhite =
color TC.nearWhite
white =
color TC.white
transparent =
color TC.transparent
blackAlpha k =
color <| TC.blackAlpha k
whiteAlpha k =
color <| TC.whiteAlpha k
darkRed =
color TC.darkRed
red =
color TC.red
lightRed =
color TC.lightRed
orange =
color TC.orange
gold =
color TC.gold
yellow =
color TC.yellow
lightYellow =
color TC.lightYellow
purple =
color TC.purple
lightPurple =
color TC.lightPurple
darkPink =
color TC.darkPink
hotPink =
color TC.hotPink
pink =
color TC.pink
lightPink =
color TC.lightPink
darkGreen =
color TC.darkGreen
green =
color TC.green
lightGreen =
color TC.lightGreen
navy =
color TC.navy
darkBlue =
color TC.darkBlue
blue =
color TC.blue
lightBlue =
color TC.lightBlue
lightestBlue =
color TC.lightestBlue
washedBlue =
color TC.washedBlue
washedGreen =
color TC.washedGreen
washedYellow =
color TC.washedYellow
washedRed =
color TC.washedRed

36
src/Ions/Size.elm Normal file

@ -0,0 +1,36 @@
module Ions.Size exposing (..)
import Element exposing (Attribute, fill, maximum, width)
base =
16
proportion =
0.95
proportionPx : Int -> Int
proportionPx n =
round <| base * (proportion ^ toFloat n)
baseRem : Float -> Int
baseRem k =
round <| k * base
measure : Attribute msg
measure =
width <| maximum (30 * base) <| fill
measureWide : Attribute msg
measureWide =
width <| maximum (34 * base) <| fill
measureNarrow : Attribute msg
measureNarrow =
width <| maximum (20 * base) <| fill

43
src/Main.elm Normal file

@ -0,0 +1,43 @@
module Main exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Browser exposing (Document)
import Config exposing (Flags)
import Model exposing (Model, emptyModel)
import Msg exposing (Msg)
import Subscriptions exposing (subscriptions)
import Update exposing (update)
import View exposing (view)
main =
Browser.document
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
init : Flags -> ( Model, Cmd Msg )
init flags =
let
( em, initCmd ) =
emptyModel flags
in
( em, initCmd )

1
src/Main.elm.d.ts vendored Normal file

@ -0,0 +1 @@
export const Elm: any

45
src/Model.elm Normal file

@ -0,0 +1,45 @@
module Model exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Config exposing (Config)
import Element
import Msg exposing (Msg(..))
import Screen.Model as Screen
type alias Model =
{ peerId : String
, screen : Screen.Model
}
emptyModel : Config -> ( Model, Cmd Msg )
emptyModel config =
let
device =
Element.classifyDevice config.windowSize
emptyScreen =
{ device = device, screenSize = config.windowSize }
in
( { peerId = config.peerId
, screen = emptyScreen
}
, Cmd.none
)

5
src/Msg.elm Normal file

@ -0,0 +1,5 @@
module Msg exposing (..)
import Screen.Msg
type Msg = NoOp
| ScreenMsg Screen.Msg.Msg

144
src/Palette.elm Normal file

@ -0,0 +1,144 @@
module Palette exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Element exposing (Element, el, inFront, padding, paddingXY, text)
import Element.Font as Font
import Element.Region as Region
import Html exposing (Html)
import Ions.Background as BG
import Ions.Border as B
import Ions.Color as C
import Ions.Font as F
import Ions.Size as S
import Screen.Model exposing (isNarrow)
accentFontColor =
F.darkRed
letterSpacing =
Font.letterSpacing 1.7
accentButton =
[ F.white, BG.darkRed ]
blockBackground =
BG.nearWhite
blockTitle inside =
el [ fillWidth, accentFontColor, letterSpacing, Font.bold, Element.paddingXY 0 <| S.baseRem 1 ] <| inside
link : String -> String -> Element msg
link url label =
Element.link
linkStyle
{ url = url, label = Element.text label }
newTabLink : String -> String -> Element msg
newTabLink url label =
Element.newTabLink
linkStyle
{ url = url, label = Element.text label }
linkStyle =
[ accentFontColor, C.easeIn, Font.underline ]
h1 txt =
el
[ Region.heading 1
, F.size2
, Font.semiBold
, Element.paddingXY 0 (S.baseRem 0.67)
, F.code
, accentFontColor
]
<|
Element.text txt
fillWidth =
Element.width Element.fill
limitLayoutWidth =
Element.width (Element.fill |> Element.maximum (S.baseRem 48))
layoutBlock screen =
[ Element.centerX
, limitLayoutWidth
, Element.paddingXY
(S.baseRem
(if isNarrow screen then
2
else
4
)
)
(S.baseRem 1)
]
pSpacing =
Element.spacing <| S.baseRem 0.5
shortHashRaw size hash =
String.concat
[ String.left size hash
, "..."
, String.right (size - 1) hash
]
shortHashEl size hash =
let
sh =
shortHashRaw size hash
in
Element.el
[ B.nearBlack
, F.code
]
<|
Element.text sh
shortHash hash =
shortHashEl 6 hash
mediumHash hash =
shortHashEl 12 hash
showHash hash =
Element.el
[ B.nearBlack
, F.code
]
<|
Element.text hash

19
src/Screen/Model.elm Normal file

@ -0,0 +1,19 @@
module Screen.Model exposing (..)
import Element exposing (Device)
type alias Model =
{ device : Device
, screenSize : { width : Int, height : Int }
}
isMedium : Model -> Bool
isMedium screen =
screen.screenSize.width < 860
isNarrow : Model -> Bool
isNarrow screen =
screen.screenSize.width < 500

8
src/Screen/Msg.elm Normal file

@ -0,0 +1,8 @@
module Screen.Msg exposing (..)
import Element exposing (Device)
type Msg
= NoOp
| WindowResized Device Int Int

@ -0,0 +1,11 @@
module Screen.Subscriptions exposing (..)
import Browser.Events exposing (onResize)
import Element
import Screen.Msg exposing (Msg(..))
subscriptions =
onResize <|
\width height ->
WindowResized (Element.classifyDevice { width = width, height = height }) width height

14
src/Screen/Update.elm Normal file

@ -0,0 +1,14 @@
module Screen.Update exposing (..)
import Screen.Model exposing (Model)
import Screen.Msg exposing (Msg(..))
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
WindowResized dc width height ->
( { model | device = dc, screenSize = { width = width, height = height } }, Cmd.none )
NoOp ->
( model, Cmd.none )

28
src/Subscriptions.elm Normal file

@ -0,0 +1,28 @@
module Subscriptions exposing (subscriptions)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Model exposing (Model)
import Msg exposing (Msg(..))
import Screen.Subscriptions
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ Screen.Subscriptions.subscriptions |> Sub.map ScreenMsg
]

32
src/Update.elm Normal file

@ -0,0 +1,32 @@
module Update exposing (update)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Model exposing (Model)
import Msg exposing (..)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
NoOp ->
( model, Cmd.none )
ScreenMsg m ->
( model, Cmd.none )

24
src/Utils.elm Normal file

@ -0,0 +1,24 @@
module Utils exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Task
run : msg -> Cmd msg
run m =
Task.perform (always m) (Task.succeed ())

51
src/Utils/ArrayExtras.elm Normal file

@ -0,0 +1,51 @@
module Utils.ArrayExtras exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Array exposing (Array, append, empty, filter, foldr, fromList, get, push, toList)
import Utils.MaybeExtras exposing (nonEmpty)
find : (a -> Bool) -> Array a -> Maybe a
find f l =
l |> filter f |> get 0
contains : (a -> Bool) -> Array a -> Bool
contains f l =
nonEmpty (find f l)
reverse : Array a -> Array a
reverse ar =
fromList (List.reverse (toList ar))
flatMaybes : Array (Maybe a) -> Array a
flatMaybes ar =
ar
|> foldr
(\m ->
\a ->
case m of
Just el ->
append a (fromList [ el ])
Nothing ->
a
)
empty

30
src/Utils/ListExtras.elm Normal file

@ -0,0 +1,30 @@
module Utils.ListExtras exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import List exposing (filter, head)
import Utils.MaybeExtras exposing (nonEmpty)
find : (a -> Bool) -> List a -> Maybe a
find f l =
l |> filter f |> head
contains : (a -> Bool) -> List a -> Bool
contains f l =
nonEmpty (find f l)

32
src/Utils/MaybeExtras.elm Normal file

@ -0,0 +1,32 @@
module Utils.MaybeExtras exposing (..)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
isEmpty : Maybe a -> Bool
isEmpty maybe =
case maybe of
Just _ ->
False
Nothing ->
True
nonEmpty : Maybe a -> Bool
nonEmpty m =
not <| isEmpty m

81
src/View.elm Normal file

@ -0,0 +1,81 @@
module View exposing (view)
{-| Copyright 2020 Fluence Labs Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
import Browser exposing (Document)
import Element exposing (Element, centerX, column, el, height, inFront, padding, paragraph, row, spacing, text)
import Element.Font as Font
import Html exposing (Html)
import Ions.Background as BG
import Ions.Font as F
import Ions.Size as S
import Model exposing (Model)
import Msg exposing (..)
import Palette exposing (fillWidth, layoutBlock, limitLayoutWidth, pSpacing)
import Screen.Model as Screen
view : Model -> Document Msg
view model =
{ title = title model, body = [ body model ] }
title : Model -> String
title m =
"Admin"
body : Model -> Html Msg
body model =
layout model.screen <|
List.concat
[
]
header : Screen.Model -> List (Element Msg)
header screenI =
[ column (layoutBlock screenI ++ [ spacing (S.baseRem 1.125) ])
[ row
[ fillWidth ]
[ paragraph [ Font.italic, F.gray, pSpacing ] <|
[ text "Fluence Admin" ]
]
, el [ height <| Element.px <| S.baseRem 0.5 ] Element.none
]
]
layout : Screen.Model -> List (Element Msg) -> Html Msg
layout screen elms =
Element.layout
[ F.size6
, F.sansSerif
, Element.padding (S.baseRem 1)
, Element.centerX
, BG.lightGray
, inFront <| column [ fillWidth, centerX, BG.white, limitLayoutWidth ] (header screen)
]
<|
Element.column
[ Element.centerX
, fillWidth
, limitLayoutWidth
, BG.white
, padding 20
]
elms

46
src/index.ts Normal file

@ -0,0 +1,46 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Elm} from './Main.elm';
import * as serviceWorker from './serviceWorker';
import {peerIdToSeed, seedToPeerId} from "fluence/dist/seed";
function genFlags(peerId: string): any {
return {
peerId: peerId,
windowSize: {
width: window.innerWidth,
height: window.innerHeight,
}
}
}
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
function test() {
console.log("test")
}
declare global {
interface Window {
test: any;
}
}
window.test = test;

10
src/main.css Normal file

@ -0,0 +1,10 @@
/*
elm-hot creates an additional div wrapper around the app to make HMR possible.
This could break styling in development mode if you are using Elm UI.
More context in the issue:
https://github.com/halfzebra/create-elm-app/issues/320
*/
[data-elm-hot="true"] {
height: inherit;
}

135
src/serviceWorker.js Normal file

@ -0,0 +1,135 @@
// This optional code is used to register a service worker.
// register() is not called by default.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to
// opt-in, read https://bit.ly/CRA-PWA
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://bit.ly/CRA-PWA'
);
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null && contentType.indexOf('javascript') === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}

28
tsconfig.json Normal file

@ -0,0 +1,28 @@
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"inlineSources": true,
"noImplicitAny": true,
"strictFunctionTypes": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"pretty": true,
"target": "es2018",
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"strict": true,
"strictNullChecks": false,
"esModuleInterop": true,
"declarationMap": true,
"baseUrl": ".",
"allowJs": true
},
"exclude": [
"node_modules",
"dist",
"bundle"
],
"include": ["src/**/*"]
}

57
webpack.config.js Normal file

@ -0,0 +1,57 @@
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
entry: {
app: ['./src/index.ts']
},
resolve: {
extensions: ['.js', '.ts', ".elm"]
},
devServer: {
contentBase: './bundle',
hot: false,
inline: false,
},
devtool: "eval-source-map",
module: {
rules: [
{
test: /\.html$/,
exclude: /node_modules/,
loader: "file-loader?name=[name].[ext]"
},
{
test: [/\.elm$/],
exclude: [/elm-stuff/, /node_modules/],
use: [
{ loader: "elm-hot-webpack-loader" },
{
loader: "elm-webpack-loader",
options:
{ debug: false, forceWatch: true }
}
]
},
{ test: /\.ts$/, loader: "ts-loader" },
{
test: /\.(png)$/,
loader: 'file-loader',
}
]
},
mode: "development",
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'bundle')
},
plugins: [
new CopyWebpackPlugin([{
from: './*.html'
}]),
new CopyWebpackPlugin([{
from: './images/*.png'
}])
]
};