add: Task Status
This commit is contained in:
@@ -7,8 +7,10 @@
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
|
||||
"andrewMacmurray/elm-delay": "4.0.0",
|
||||
"elm/browser": "1.0.2",
|
||||
"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",
|
||||
@@ -17,7 +19,6 @@
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,15 +2,13 @@ module Files exposing (..)
|
||||
|
||||
import Debug exposing (toString)
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Element.Input as Input
|
||||
import Element.Region as Region
|
||||
import Globals exposing (apiFiles)
|
||||
import Http
|
||||
import Json.Decode exposing (Decoder, int, list, string, succeed)
|
||||
import Json.Decode.Pipeline exposing (required)
|
||||
import String exposing (left)
|
||||
|
||||
|
||||
type alias File =
|
||||
@@ -100,7 +98,7 @@ update msg model =
|
||||
queryFiles : Cmd Msg
|
||||
queryFiles =
|
||||
Http.get
|
||||
{ url = "http://127.0.0.1/api/files"
|
||||
{ url = apiFiles
|
||||
, expect = Http.expectJson QueryRequestResult queueDecoder
|
||||
}
|
||||
|
||||
|
||||
21
Modules/Website/src/Globals.elm
Normal file
21
Modules/Website/src/Globals.elm
Normal file
@@ -0,0 +1,21 @@
|
||||
module Globals exposing (..)
|
||||
|
||||
|
||||
api : String
|
||||
api =
|
||||
"http://127.0.0.1/api/"
|
||||
|
||||
|
||||
apiEndpoint : String -> String
|
||||
apiEndpoint path =
|
||||
String.concat [ api, path ]
|
||||
|
||||
|
||||
apiStatus : String -> String
|
||||
apiStatus id = String.concat [apiEndpoint "status/", id]
|
||||
|
||||
apiDownloadFile : String -> String
|
||||
apiDownloadFile id = String.concat [apiEndpoint "file/", id]
|
||||
|
||||
apiFiles : String
|
||||
apiFiles = apiEndpoint "files"
|
||||
@@ -8,7 +8,8 @@ import Element.Region as Region
|
||||
import Files
|
||||
import Html exposing (Html)
|
||||
import MainPage
|
||||
import Route exposing (Route)
|
||||
import Route exposing (Route(..))
|
||||
import Status
|
||||
import Url exposing (Url)
|
||||
|
||||
|
||||
@@ -23,12 +24,7 @@ type Page
|
||||
= NotFound
|
||||
| Home MainPage.Model
|
||||
| FilesPage Files.Model
|
||||
|
||||
|
||||
|
||||
--initModel : Model
|
||||
--initModel =
|
||||
-- PageMain MainPage.initModel
|
||||
| StatusPage Status.Model
|
||||
|
||||
|
||||
init : () -> Url -> Nav.Key -> ( Model, Cmd Msg )
|
||||
@@ -64,6 +60,13 @@ initCurrentPage ( model, existingCmds ) =
|
||||
Files.init
|
||||
in
|
||||
( FilesPage pageModel, Cmd.map FilesPageMsg pageCmd )
|
||||
|
||||
Route.Status file ->
|
||||
let
|
||||
( pageModel, pageCmd ) =
|
||||
Status.init file
|
||||
in
|
||||
( StatusPage pageModel, Cmd.map StatusPageMsg pageCmd )
|
||||
in
|
||||
( { model | page = currentPage }
|
||||
, Cmd.batch [ existingCmds, mappedPageCmds ]
|
||||
@@ -79,6 +82,7 @@ type Msg
|
||||
| UrlChanged Url
|
||||
| HomePageMsg MainPage.Msg
|
||||
| FilesPageMsg Files.Msg
|
||||
| StatusPageMsg Status.Msg
|
||||
|
||||
|
||||
|
||||
@@ -91,7 +95,7 @@ update msg model =
|
||||
( HomePageMsg subMsg, Home pageModel ) ->
|
||||
let
|
||||
( updatePageModel, updateCmd ) =
|
||||
MainPage.update subMsg pageModel
|
||||
MainPage.update model.navKey subMsg pageModel
|
||||
in
|
||||
( { model | page = Home updatePageModel }
|
||||
, Cmd.map HomePageMsg updateCmd
|
||||
@@ -106,6 +110,15 @@ update msg model =
|
||||
, Cmd.map FilesPageMsg updateCmd
|
||||
)
|
||||
|
||||
( StatusPageMsg subMsg, StatusPage pageModel ) ->
|
||||
let
|
||||
( updatePageModel, updateCmd ) =
|
||||
Status.update subMsg pageModel
|
||||
in
|
||||
( { model | page = StatusPage updatePageModel }
|
||||
, Cmd.map StatusPageMsg updateCmd
|
||||
)
|
||||
|
||||
( LinkClicked urlRequest, _ ) ->
|
||||
case urlRequest of
|
||||
Browser.Internal url ->
|
||||
@@ -141,6 +154,9 @@ view model =
|
||||
FilesPage pageModel ->
|
||||
Files.view pageModel |> Element.map FilesPageMsg
|
||||
|
||||
StatusPage pageModel ->
|
||||
Status.view pageModel |> Element.map StatusPageMsg
|
||||
|
||||
_ ->
|
||||
el
|
||||
[ Region.heading 1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
module MainPage exposing (Model, Msg, initModel, update, view)
|
||||
|
||||
import Browser.Navigation as Nav
|
||||
import Color exposing (..)
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
@@ -7,13 +8,11 @@ import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Element.Input as Input
|
||||
import Element.Region as Region
|
||||
import Html exposing (form)
|
||||
import Http
|
||||
import Json.Decode exposing (Decoder, int, string, succeed)
|
||||
import Json.Decode.Pipeline exposing (required)
|
||||
import Json.Encode as Encode
|
||||
import List exposing (map3)
|
||||
import Tuple exposing (mapBoth)
|
||||
import Html exposing (form)
|
||||
|
||||
|
||||
type alias Form =
|
||||
@@ -53,13 +52,21 @@ type AudioFormats
|
||||
| AAC
|
||||
| WAV
|
||||
|
||||
|
||||
audioFormatName : AudioFormats -> String
|
||||
audioFormatName format =
|
||||
case format of
|
||||
MP3 -> "mp3"
|
||||
OPUS -> "opus"
|
||||
AAC -> "aac"
|
||||
WAV -> "wav"
|
||||
MP3 ->
|
||||
"mp3"
|
||||
|
||||
OPUS ->
|
||||
"opus"
|
||||
|
||||
AAC ->
|
||||
"aac"
|
||||
|
||||
WAV ->
|
||||
"wav"
|
||||
|
||||
|
||||
type VideoFormats
|
||||
@@ -68,38 +75,54 @@ type VideoFormats
|
||||
| OGG
|
||||
| WEBM
|
||||
|
||||
|
||||
videoFormatName : VideoFormats -> String
|
||||
videoFormatName format =
|
||||
case format of
|
||||
FLV -> "flv"
|
||||
MP4 -> "mp4"
|
||||
OGG -> "ogg"
|
||||
WEBM -> "wav"
|
||||
FLV ->
|
||||
"flv"
|
||||
|
||||
MP4 ->
|
||||
"mp4"
|
||||
|
||||
OGG ->
|
||||
"ogg"
|
||||
|
||||
WEBM ->
|
||||
"webm"
|
||||
|
||||
|
||||
type Format
|
||||
= Auto
|
||||
| AudioFormat AudioFormats
|
||||
| VideoFormat VideoFormats
|
||||
|
||||
|
||||
formatName : Format -> String
|
||||
formatName format =
|
||||
case format of
|
||||
Auto -> "Auto"
|
||||
AudioFormat audio -> audioFormatName audio
|
||||
VideoFormat video -> videoFormatName video
|
||||
Auto ->
|
||||
"Auto"
|
||||
|
||||
AudioFormat audio ->
|
||||
audioFormatName audio
|
||||
|
||||
VideoFormat video ->
|
||||
videoFormatName video
|
||||
|
||||
|
||||
|
||||
-- -- Request -- --
|
||||
|
||||
|
||||
type alias PostFormResponse =
|
||||
{ id : Int, status : String }
|
||||
{ id : String, status : String }
|
||||
|
||||
|
||||
formDecoder : Decoder PostFormResponse
|
||||
formDecoder =
|
||||
succeed PostFormResponse
|
||||
|> required "id" int
|
||||
|> required "file_id" string
|
||||
|> required "status" string
|
||||
|
||||
|
||||
@@ -115,8 +138,9 @@ formPostEncoder form =
|
||||
[]
|
||||
, if form.format == Auto then
|
||||
[]
|
||||
else
|
||||
[( "format", Encode.string <| formatName form.format )]
|
||||
|
||||
else
|
||||
[ ( "format", Encode.string <| formatName form.format ) ]
|
||||
]
|
||||
|
||||
|
||||
@@ -124,8 +148,8 @@ formPostEncoder form =
|
||||
-- -- Update -- --
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
update msg model =
|
||||
update : Nav.Key -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update navKey msg model =
|
||||
case msg of
|
||||
UpdateForm new_form ->
|
||||
( { model | form = new_form }, Cmd.none )
|
||||
@@ -151,13 +175,20 @@ update msg model =
|
||||
( { model | form = new_form }, Cmd.none )
|
||||
|
||||
PostForm form ->
|
||||
( model
|
||||
, Http.post
|
||||
{ url = "http://127.0.0.1/api/add"
|
||||
, body = Http.jsonBody (formPostEncoder form)
|
||||
, expect = Http.expectJson PostResult formDecoder
|
||||
}
|
||||
)
|
||||
if not (String.isEmpty form.url) then
|
||||
( model
|
||||
, Http.post
|
||||
{ url = "http://127.0.0.1/api/add"
|
||||
, body = Http.jsonBody (formPostEncoder form)
|
||||
, expect = Http.expectJson PostResult formDecoder
|
||||
}
|
||||
)
|
||||
|
||||
else
|
||||
( model, Cmd.none )
|
||||
|
||||
PostResult (Ok data) ->
|
||||
( model, Nav.pushUrl navKey <| String.concat [ "/status/", data.id ] )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
@@ -254,6 +285,7 @@ formatButton position label state =
|
||||
, Border.roundEach corners
|
||||
, Border.widthEach borders
|
||||
, Border.color color.blue
|
||||
, width (px 80)
|
||||
, Background.color <|
|
||||
if state == Input.Selected then
|
||||
color.lightBlue
|
||||
@@ -269,6 +301,7 @@ formatButton position label state =
|
||||
formatOption format position =
|
||||
Input.optionWith format <| formatButton position <| formatName format
|
||||
|
||||
|
||||
view : Model -> Element Msg
|
||||
view model =
|
||||
Element.column
|
||||
@@ -287,15 +320,6 @@ view model =
|
||||
(text "localTube")
|
||||
, Input.text
|
||||
[ spacing 12
|
||||
, below
|
||||
(el
|
||||
[ Font.color color.red
|
||||
, Font.size 14
|
||||
, alignRight
|
||||
, moveDown 6
|
||||
]
|
||||
(text "This one is wrong")
|
||||
)
|
||||
]
|
||||
{ text = model.form.url
|
||||
, placeholder = Just (Input.placeholder [] (text "http://youtube.com"))
|
||||
@@ -325,17 +349,17 @@ view model =
|
||||
List.concat
|
||||
[ [ Input.optionWith Auto <| formatButton First "Auto" ]
|
||||
, if model.form.audio_only then
|
||||
[ formatOption (AudioFormat MP3) Mid
|
||||
, formatOption (AudioFormat OPUS) Mid
|
||||
, formatOption (AudioFormat AAC) Mid
|
||||
, formatOption (AudioFormat WAV) Last
|
||||
[ formatOption (AudioFormat MP3) Mid
|
||||
, formatOption (AudioFormat OPUS) Mid
|
||||
, formatOption (AudioFormat AAC) Mid
|
||||
, formatOption (AudioFormat WAV) Last
|
||||
]
|
||||
|
||||
else
|
||||
[ formatOption (VideoFormat FLV) Mid
|
||||
, formatOption (VideoFormat MP4) Mid
|
||||
, formatOption (VideoFormat OGG) Mid
|
||||
, formatOption (VideoFormat WEBM)Last
|
||||
[ formatOption (VideoFormat FLV) Mid
|
||||
, formatOption (VideoFormat MP4) Mid
|
||||
, formatOption (VideoFormat OGG) Mid
|
||||
, formatOption (VideoFormat WEBM) Last
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ type Route
|
||||
= NotFound
|
||||
| Home
|
||||
| Files
|
||||
| Status String
|
||||
|
||||
|
||||
parseUrl : Url -> Route
|
||||
@@ -25,4 +26,5 @@ matchRoute =
|
||||
oneOf
|
||||
[ map Home top
|
||||
, map Files (s "files")
|
||||
, map Status (s "status" </> string)
|
||||
]
|
||||
|
||||
232
Modules/Website/src/Status.elm
Normal file
232
Modules/Website/src/Status.elm
Normal file
@@ -0,0 +1,232 @@
|
||||
module Status exposing (Model, Msg, init, queryStatus, update, view)
|
||||
|
||||
import Color exposing (color)
|
||||
import Debug exposing (toString)
|
||||
import Delay
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Element.Input as Input
|
||||
import File.Download exposing (url)
|
||||
import Files exposing (Msg(..))
|
||||
import Globals exposing (apiDownloadFile, apiStatus)
|
||||
import Http
|
||||
import Json.Decode exposing (Decoder, int, list, string, succeed)
|
||||
import Json.Decode.Pipeline exposing (optional, required)
|
||||
import Route exposing (Route(..))
|
||||
import String exposing (right)
|
||||
import Task
|
||||
|
||||
|
||||
|
||||
-- Messages
|
||||
|
||||
|
||||
type Msg
|
||||
= Reload
|
||||
| StatusRequestResult (Result Http.Error StatusResponse)
|
||||
| Download String
|
||||
|
||||
|
||||
|
||||
-- Model
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ file_id : String
|
||||
, status : Maybe Status
|
||||
}
|
||||
|
||||
|
||||
init : String -> ( Model, Cmd Msg )
|
||||
init file_id =
|
||||
( { file_id = file_id, status = Nothing }, send Reload )
|
||||
|
||||
|
||||
|
||||
-- Request
|
||||
|
||||
|
||||
type alias File =
|
||||
{ format : String
|
||||
, filename : String
|
||||
, timestamp : Int
|
||||
}
|
||||
|
||||
|
||||
type alias Status =
|
||||
{ file : Maybe File
|
||||
, name : String
|
||||
, source : String
|
||||
, status : String
|
||||
, status_id : Int
|
||||
, format : String
|
||||
, timestamp : Int
|
||||
, id : String
|
||||
}
|
||||
|
||||
|
||||
type alias StatusResponse =
|
||||
{ status : Status }
|
||||
|
||||
|
||||
fileDecoder : Decoder File
|
||||
fileDecoder =
|
||||
succeed File
|
||||
|> required "format" string
|
||||
|> required "name" string
|
||||
|> required "timestamp" int
|
||||
|
||||
|
||||
statusDecoder : Decoder Status
|
||||
statusDecoder =
|
||||
succeed Status
|
||||
|> optional "file" (Json.Decode.map Just fileDecoder) Nothing
|
||||
|> required "name" string
|
||||
|> required "source" string
|
||||
|> required "status" string
|
||||
|> required "status_id" int
|
||||
|> required "task_file_type" string
|
||||
|> required "timestamp" int
|
||||
|> required "id" string
|
||||
|
||||
|
||||
statusResponseDecoder : Decoder StatusResponse
|
||||
statusResponseDecoder =
|
||||
succeed StatusResponse
|
||||
|> required "status" statusDecoder
|
||||
|
||||
|
||||
queryStatus : String -> Cmd Msg
|
||||
queryStatus id =
|
||||
Http.get
|
||||
{ url = apiStatus id
|
||||
, expect = Http.expectJson StatusRequestResult statusResponseDecoder
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- Update
|
||||
|
||||
|
||||
cardShadow : Attr decorative msg
|
||||
cardShadow =
|
||||
Border.shadow
|
||||
{ offset = ( 0, 4 )
|
||||
, size = 4
|
||||
, blur = 8
|
||||
, color = rgba 0 0 0 0.2
|
||||
}
|
||||
|
||||
|
||||
cardShadowOver : Attr decorative msg
|
||||
cardShadowOver =
|
||||
Border.shadow
|
||||
{ offset = ( 0, 4 )
|
||||
, size = 8
|
||||
, blur = 16
|
||||
, color = rgba 0 0 0 0.2
|
||||
}
|
||||
|
||||
|
||||
card : List (Attribute msg) -> Element msg -> Element msg
|
||||
card attr element =
|
||||
el
|
||||
(List.concat
|
||||
[ attr
|
||||
, [ Border.rounded 15, cardShadow, mouseOver [ cardShadowOver ], padding 20 ]
|
||||
]
|
||||
)
|
||||
element
|
||||
|
||||
|
||||
innerCard : List (Attribute msg) -> Element msg -> Element msg
|
||||
innerCard attr element =
|
||||
el
|
||||
(List.concat
|
||||
[ attr
|
||||
, [ Border.roundEach { topLeft = 15, topRight = 15, bottomLeft = 15, bottomRight = 15 }, padding 5 ]
|
||||
]
|
||||
)
|
||||
element
|
||||
|
||||
|
||||
send : msg -> Cmd msg
|
||||
send msg =
|
||||
Task.succeed msg
|
||||
|> Task.perform identity
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
Reload ->
|
||||
( model, queryStatus model.file_id )
|
||||
|
||||
StatusRequestResult (Ok res) ->
|
||||
( { model | status = Just res.status }, Delay.after 1000 Reload )
|
||||
|
||||
StatusRequestResult _ ->
|
||||
( { model | status = Nothing }, Cmd.none )
|
||||
|
||||
Download file_id ->
|
||||
( model, url <| apiDownloadFile file_id )
|
||||
|
||||
|
||||
|
||||
-- View
|
||||
--Just (Download.
|
||||
|
||||
|
||||
statusView : Status -> Element Msg
|
||||
statusView status =
|
||||
card [ width fill, height shrink ]
|
||||
(Element.column
|
||||
[ width fill ]
|
||||
[ row [ width fill, height <| px 40 ]
|
||||
[ el [ Font.size 28, alignLeft ] <| text status.name
|
||||
, el [ Font.size 28, alignRight ] <| text (String.concat [ "[", status.status, "]" ])
|
||||
]
|
||||
, link [ Font.bold, Font.underline, Font.color color.blue, Font.size 16, padding 2 ]
|
||||
{ url = status.source, label = text status.source }
|
||||
, el [ height <| px 10 ] none
|
||||
, case status.file of
|
||||
Just file ->
|
||||
innerCard [ width fill, height shrink, Background.color color.grey ] <|
|
||||
row [ width fill, spacing 20 ]
|
||||
[ Input.button
|
||||
[ Background.color color.blue
|
||||
, Font.color color.white
|
||||
, Border.color color.red
|
||||
, paddingXY 32 16
|
||||
, Border.rounded 15
|
||||
]
|
||||
{ onPress = Just <| Download status.id
|
||||
, label = Element.text "Download"
|
||||
}
|
||||
, el [ Font.size 16 ] <| text file.filename
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
Element.none
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
view : Model -> Element Msg
|
||||
view model =
|
||||
Element.column
|
||||
[ width (px 800)
|
||||
, height shrink
|
||||
, centerX
|
||||
, centerY
|
||||
, spacing 36
|
||||
]
|
||||
[ case model.status of
|
||||
Just status ->
|
||||
statusView status
|
||||
|
||||
Nothing ->
|
||||
Element.text "Test"
|
||||
]
|
||||
Reference in New Issue
Block a user