mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
Basic ui for addons
This commit is contained in:
@ -18,6 +18,14 @@ module Api exposing
|
|||||||
, addShare
|
, addShare
|
||||||
, addTag
|
, addTag
|
||||||
, addTagsMultiple
|
, addTagsMultiple
|
||||||
|
, addonRunConfigDelete
|
||||||
|
, addonRunConfigGet
|
||||||
|
, addonRunConfigSet
|
||||||
|
, addonRunExistingItem
|
||||||
|
, addonsDelete
|
||||||
|
, addonsGetAll
|
||||||
|
, addonsInstall
|
||||||
|
, addonsUpdate
|
||||||
, attachmentPreviewURL
|
, attachmentPreviewURL
|
||||||
, bookmarkNameExists
|
, bookmarkNameExists
|
||||||
, cancelJob
|
, cancelJob
|
||||||
@ -211,6 +219,11 @@ module Api exposing
|
|||||||
, versionInfo
|
, versionInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import Api.Model.AddonList exposing (AddonList)
|
||||||
|
import Api.Model.AddonRegister exposing (AddonRegister)
|
||||||
|
import Api.Model.AddonRunConfig exposing (AddonRunConfig)
|
||||||
|
import Api.Model.AddonRunConfigList exposing (AddonRunConfigList)
|
||||||
|
import Api.Model.AddonRunExistingItem exposing (AddonRunExistingItem)
|
||||||
import Api.Model.AttachmentMeta exposing (AttachmentMeta)
|
import Api.Model.AttachmentMeta exposing (AttachmentMeta)
|
||||||
import Api.Model.AuthResult exposing (AuthResult)
|
import Api.Model.AuthResult exposing (AuthResult)
|
||||||
import Api.Model.BasicResult exposing (BasicResult)
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
@ -3156,6 +3169,99 @@ shareDownloadAllLink flags id =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Addons
|
||||||
|
|
||||||
|
|
||||||
|
addonsGetAll : Flags -> (Result Http.Error AddonList -> msg) -> Cmd msg
|
||||||
|
addonsGetAll flags receive =
|
||||||
|
Http2.authGet
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/archive"
|
||||||
|
, account = getAccount flags
|
||||||
|
, expect = Http.expectJson receive Api.Model.AddonList.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonsDelete : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
addonsDelete flags addonId receive =
|
||||||
|
Http2.authDelete
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/archive/" ++ addonId
|
||||||
|
, account = getAccount flags
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonsInstall : Flags -> AddonRegister -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
addonsInstall flags addon receive =
|
||||||
|
Http2.authPost
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/archive"
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Api.Model.AddonRegister.encode addon)
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonsUpdate : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
addonsUpdate flags addonId receive =
|
||||||
|
Http2.authPut
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/archive/" ++ addonId
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.emptyBody
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonRunConfigGet : Flags -> (Result Http.Error AddonRunConfigList -> msg) -> Cmd msg
|
||||||
|
addonRunConfigGet flags receive =
|
||||||
|
Http2.authGet
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/run-config"
|
||||||
|
, account = getAccount flags
|
||||||
|
, expect = Http.expectJson receive Api.Model.AddonRunConfigList.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonRunConfigSet :
|
||||||
|
Flags
|
||||||
|
-> AddonRunConfig
|
||||||
|
-> (Result Http.Error BasicResult -> msg)
|
||||||
|
-> Cmd msg
|
||||||
|
addonRunConfigSet flags cfg receive =
|
||||||
|
if cfg.id == "" then
|
||||||
|
Http2.authPost
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/run-config"
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Api.Model.AddonRunConfig.encode cfg)
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
Http2.authPut
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/run-config/" ++ cfg.id
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Api.Model.AddonRunConfig.encode cfg)
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonRunConfigDelete : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
addonRunConfigDelete flags id receive =
|
||||||
|
Http2.authDelete
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/run-config/" ++ id
|
||||||
|
, account = getAccount flags
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonRunExistingItem : Flags -> AddonRunExistingItem -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
|
addonRunExistingItem flags input receive =
|
||||||
|
Http2.authPost
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/addon/run/existingitem"
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.jsonBody (Api.Model.AddonRunExistingItem.encode input)
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Helper
|
--- Helper
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import Api
|
|||||||
import App.Data exposing (..)
|
import App.Data exposing (..)
|
||||||
import Browser exposing (UrlRequest(..))
|
import Browser exposing (UrlRequest(..))
|
||||||
import Browser.Navigation as Nav
|
import Browser.Navigation as Nav
|
||||||
|
import Comp.AddonArchiveManage
|
||||||
import Comp.DownloadAll
|
import Comp.DownloadAll
|
||||||
import Data.AppEvent exposing (AppEvent(..))
|
import Data.AppEvent exposing (AppEvent(..))
|
||||||
import Data.Environment as Env
|
import Data.Environment as Env
|
||||||
@ -345,6 +346,9 @@ updateWithSub msg model =
|
|||||||
Ok (JobsWaiting n) ->
|
Ok (JobsWaiting n) ->
|
||||||
( { model | jobsWaiting = max 0 n }, Cmd.none, Sub.none )
|
( { model | jobsWaiting = max 0 n }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
Ok (AddonInstalled info) ->
|
||||||
|
updateManageData (Page.ManageData.Data.AddonArchiveMsg <| Comp.AddonArchiveManage.addonInstallResult info) model
|
||||||
|
|
||||||
Err _ ->
|
Err _ ->
|
||||||
( model, Cmd.none, Sub.none )
|
( model, Cmd.none, Sub.none )
|
||||||
|
|
||||||
@ -640,7 +644,7 @@ updateManageData : Page.ManageData.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Ms
|
|||||||
updateManageData lmsg model =
|
updateManageData lmsg model =
|
||||||
let
|
let
|
||||||
( lm, lc, ls ) =
|
( lm, lc, ls ) =
|
||||||
Page.ManageData.Update.update model.flags lmsg model.manageDataModel
|
Page.ManageData.Update.update model.flags model.uiSettings lmsg model.manageDataModel
|
||||||
in
|
in
|
||||||
( { model | manageDataModel = lm }
|
( { model | manageDataModel = lm }
|
||||||
, Cmd.map ManageDataMsg lc
|
, Cmd.map ManageDataMsg lc
|
||||||
|
106
modules/webapp/src/main/elm/Comp/AddonArchiveForm.elm
Normal file
106
modules/webapp/src/main/elm/Comp/AddonArchiveForm.elm
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.AddonArchiveForm exposing (Model, Msg, get, init, initWith, update, view)
|
||||||
|
|
||||||
|
import Api.Model.Addon exposing (Addon)
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Events exposing (onInput)
|
||||||
|
import Messages.Comp.AddonArchiveForm exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
import Util.Maybe
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ addon : Addon
|
||||||
|
, url : Maybe String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : ( Model, Cmd Msg )
|
||||||
|
init =
|
||||||
|
( { addon = Api.Model.Addon.empty
|
||||||
|
, url = Nothing
|
||||||
|
}
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
initWith : Addon -> ( Model, Cmd Msg )
|
||||||
|
initWith a =
|
||||||
|
( { addon = a
|
||||||
|
, url = a.url
|
||||||
|
}
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
isValid : Model -> Bool
|
||||||
|
isValid model =
|
||||||
|
model.url /= Nothing
|
||||||
|
|
||||||
|
|
||||||
|
get : Model -> Maybe Addon
|
||||||
|
get model =
|
||||||
|
let
|
||||||
|
a =
|
||||||
|
model.addon
|
||||||
|
in
|
||||||
|
if isValid model then
|
||||||
|
Just
|
||||||
|
{ a
|
||||||
|
| url = model.url
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SetUrl String
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||||
|
update _ msg model =
|
||||||
|
case msg of
|
||||||
|
SetUrl url ->
|
||||||
|
( { model | url = Util.Maybe.fromString url }, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> Model -> Html Msg
|
||||||
|
view texts model =
|
||||||
|
div
|
||||||
|
[ class "flex flex-col" ]
|
||||||
|
[ div [ class "mb-4" ]
|
||||||
|
[ label
|
||||||
|
[ class S.inputLabel
|
||||||
|
]
|
||||||
|
[ text texts.addonUrl
|
||||||
|
, B.inputRequired
|
||||||
|
]
|
||||||
|
, input
|
||||||
|
[ type_ "text"
|
||||||
|
, placeholder texts.addonUrlPlaceholder
|
||||||
|
, class S.textInput
|
||||||
|
, classList [ ( "disabled", model.addon.id /= "" ) ]
|
||||||
|
, value (model.url |> Maybe.withDefault "")
|
||||||
|
, onInput SetUrl
|
||||||
|
, disabled (model.addon.id /= "")
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, span [ class "text-sm opacity-75" ]
|
||||||
|
[ text texts.installInfoText
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
429
modules/webapp/src/main/elm/Comp/AddonArchiveManage.elm
Normal file
429
modules/webapp/src/main/elm/Comp/AddonArchiveManage.elm
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.AddonArchiveManage exposing (Model, Msg, addonInstallResult, init, loadAddons, update, view)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.Addon exposing (Addon)
|
||||||
|
import Api.Model.AddonList exposing (AddonList)
|
||||||
|
import Api.Model.AddonRegister exposing (AddonRegister)
|
||||||
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
|
import Comp.AddonArchiveForm
|
||||||
|
import Comp.AddonArchiveTable
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.ItemDetail.Model exposing (Msg(..))
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.ServerEvent exposing (AddonInfo)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Events exposing (onClick)
|
||||||
|
import Http
|
||||||
|
import Markdown
|
||||||
|
import Messages.Comp.AddonArchiveManage exposing (Texts)
|
||||||
|
import Page exposing (Page(..))
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type FormError
|
||||||
|
= FormErrorNone
|
||||||
|
| FormErrorHttp Http.Error
|
||||||
|
| FormErrorInvalid
|
||||||
|
| FormErrorSubmit String
|
||||||
|
|
||||||
|
|
||||||
|
type ViewMode
|
||||||
|
= Table
|
||||||
|
| Form
|
||||||
|
|
||||||
|
|
||||||
|
type DeleteConfirm
|
||||||
|
= DeleteConfirmOff
|
||||||
|
| DeleteConfirmOn
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ viewMode : ViewMode
|
||||||
|
, addons : List Addon
|
||||||
|
, formModel : Comp.AddonArchiveForm.Model
|
||||||
|
, loading : Bool
|
||||||
|
, formError : FormError
|
||||||
|
, deleteConfirm : DeleteConfirm
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
let
|
||||||
|
( fm, fc ) =
|
||||||
|
Comp.AddonArchiveForm.init
|
||||||
|
in
|
||||||
|
( { viewMode = Table
|
||||||
|
, addons = []
|
||||||
|
, formModel = fm
|
||||||
|
, loading = False
|
||||||
|
, formError = FormErrorNone
|
||||||
|
, deleteConfirm = DeleteConfirmOff
|
||||||
|
}
|
||||||
|
, Cmd.batch
|
||||||
|
[ Cmd.map FormMsg fc
|
||||||
|
, Api.addonsGetAll flags LoadAddonsResp
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= LoadAddons
|
||||||
|
| TableMsg Comp.AddonArchiveTable.Msg
|
||||||
|
| FormMsg Comp.AddonArchiveForm.Msg
|
||||||
|
| InitNewAddon
|
||||||
|
| SetViewMode ViewMode
|
||||||
|
| Submit
|
||||||
|
| RequestDelete
|
||||||
|
| CancelDelete
|
||||||
|
| DeleteAddonNow String
|
||||||
|
| LoadAddonsResp (Result Http.Error AddonList)
|
||||||
|
| AddAddonResp (Result Http.Error BasicResult)
|
||||||
|
| UpdateAddonResp (Result Http.Error BasicResult)
|
||||||
|
| DeleteAddonResp (Result Http.Error BasicResult)
|
||||||
|
| AddonInstallResp AddonInfo
|
||||||
|
|
||||||
|
|
||||||
|
loadAddons : Msg
|
||||||
|
loadAddons =
|
||||||
|
LoadAddons
|
||||||
|
|
||||||
|
|
||||||
|
addonInstallResult : AddonInfo -> Msg
|
||||||
|
addonInstallResult info =
|
||||||
|
AddonInstallResp info
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
InitNewAddon ->
|
||||||
|
let
|
||||||
|
( bm, bc ) =
|
||||||
|
Comp.AddonArchiveForm.init
|
||||||
|
|
||||||
|
nm =
|
||||||
|
{ model
|
||||||
|
| viewMode = Form
|
||||||
|
, formError = FormErrorNone
|
||||||
|
, formModel = bm
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( nm, Cmd.map FormMsg bc, Sub.none )
|
||||||
|
|
||||||
|
SetViewMode vm ->
|
||||||
|
( { model | viewMode = vm, formError = FormErrorNone }
|
||||||
|
, if vm == Table then
|
||||||
|
Api.addonsGetAll flags LoadAddonsResp
|
||||||
|
|
||||||
|
else
|
||||||
|
Cmd.none
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
FormMsg lm ->
|
||||||
|
let
|
||||||
|
( fm, fc ) =
|
||||||
|
Comp.AddonArchiveForm.update flags lm model.formModel
|
||||||
|
in
|
||||||
|
( { model | formModel = fm, formError = FormErrorNone }
|
||||||
|
, Cmd.map FormMsg fc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
TableMsg lm ->
|
||||||
|
let
|
||||||
|
action =
|
||||||
|
Comp.AddonArchiveTable.update lm
|
||||||
|
in
|
||||||
|
case action of
|
||||||
|
Comp.AddonArchiveTable.Selected addon ->
|
||||||
|
let
|
||||||
|
( bm, bc ) =
|
||||||
|
Comp.AddonArchiveForm.initWith addon
|
||||||
|
in
|
||||||
|
( { model
|
||||||
|
| viewMode = Form
|
||||||
|
, formError = FormErrorNone
|
||||||
|
, formModel = bm
|
||||||
|
}
|
||||||
|
, Cmd.map FormMsg bc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
RequestDelete ->
|
||||||
|
( { model | deleteConfirm = DeleteConfirmOn }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
CancelDelete ->
|
||||||
|
( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DeleteAddonNow id ->
|
||||||
|
( { model | deleteConfirm = DeleteConfirmOff, loading = True }
|
||||||
|
, Api.addonsDelete flags id DeleteAddonResp
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadAddons ->
|
||||||
|
( { model | loading = True }
|
||||||
|
, Api.addonsGetAll flags LoadAddonsResp
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadAddonsResp (Ok list) ->
|
||||||
|
( { model | loading = False, addons = list.items, formError = FormErrorNone }
|
||||||
|
, Cmd.none
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadAddonsResp (Err err) ->
|
||||||
|
( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
AddonInstallResp info ->
|
||||||
|
if info.success then
|
||||||
|
( { model | loading = False, viewMode = Table }, Api.addonsGetAll flags LoadAddonsResp, Sub.none )
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | loading = False, formError = FormErrorSubmit info.message }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
Submit ->
|
||||||
|
case Comp.AddonArchiveForm.get model.formModel of
|
||||||
|
Just data ->
|
||||||
|
if data.id /= "" then
|
||||||
|
( { model | loading = True }
|
||||||
|
, Api.addonsUpdate flags data.id UpdateAddonResp
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | loading = True }
|
||||||
|
, Api.addonsInstall
|
||||||
|
flags
|
||||||
|
(AddonRegister <| Maybe.withDefault "" data.url)
|
||||||
|
AddAddonResp
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( { model | formError = FormErrorInvalid }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
AddAddonResp (Ok res) ->
|
||||||
|
if res.success then
|
||||||
|
( model, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | loading = False, formError = FormErrorSubmit res.message }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
AddAddonResp (Err err) ->
|
||||||
|
( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
UpdateAddonResp (Ok res) ->
|
||||||
|
if res.success then
|
||||||
|
( model, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | loading = False, formError = FormErrorSubmit res.message }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
UpdateAddonResp (Err err) ->
|
||||||
|
( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DeleteAddonResp (Ok res) ->
|
||||||
|
if res.success then
|
||||||
|
update flags (SetViewMode Table) { model | loading = False }
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | formError = FormErrorSubmit res.message, loading = False }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DeleteAddonResp (Err err) ->
|
||||||
|
( { model | formError = FormErrorHttp err, loading = False }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- view
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Flags -> Model -> Html Msg
|
||||||
|
view texts settings flags model =
|
||||||
|
if model.viewMode == Table then
|
||||||
|
viewTable texts model
|
||||||
|
|
||||||
|
else
|
||||||
|
viewForm texts settings flags model
|
||||||
|
|
||||||
|
|
||||||
|
viewTable : Texts -> Model -> Html Msg
|
||||||
|
viewTable texts model =
|
||||||
|
div [ class "flex flex-col" ]
|
||||||
|
[ MB.view
|
||||||
|
{ start =
|
||||||
|
[]
|
||||||
|
, end =
|
||||||
|
[ MB.PrimaryButton
|
||||||
|
{ tagger = InitNewAddon
|
||||||
|
, title = texts.createNewAddonArchive
|
||||||
|
, icon = Just "fa fa-plus"
|
||||||
|
, label = texts.newAddonArchive
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, rootClasses = "mb-4"
|
||||||
|
, sticky = True
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ class "flex flex-col"
|
||||||
|
]
|
||||||
|
[ Html.map TableMsg
|
||||||
|
(Comp.AddonArchiveTable.view texts.addonArchiveTable model.addons)
|
||||||
|
]
|
||||||
|
, B.loadingDimmer
|
||||||
|
{ label = ""
|
||||||
|
, active = model.loading
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewForm : Texts -> UiSettings -> Flags -> Model -> Html Msg
|
||||||
|
viewForm texts _ _ model =
|
||||||
|
let
|
||||||
|
newAddon =
|
||||||
|
model.formModel.addon.id == ""
|
||||||
|
|
||||||
|
isValid =
|
||||||
|
Comp.AddonArchiveForm.get model.formModel /= Nothing
|
||||||
|
in
|
||||||
|
div [ class "relative" ]
|
||||||
|
[ Html.form []
|
||||||
|
[ if newAddon then
|
||||||
|
h1 [ class S.header2 ]
|
||||||
|
[ text texts.createNewAddonArchive
|
||||||
|
]
|
||||||
|
|
||||||
|
else
|
||||||
|
h1 [ class S.header2 ]
|
||||||
|
[ text (Comp.AddonArchiveForm.get model.formModel |> Maybe.map .name |> Maybe.withDefault "Update")
|
||||||
|
]
|
||||||
|
, MB.view
|
||||||
|
{ start =
|
||||||
|
[ MB.SecondaryButton
|
||||||
|
{ tagger = SetViewMode Table
|
||||||
|
, title = texts.basics.backToList
|
||||||
|
, icon = Just "fa fa-arrow-left"
|
||||||
|
, label = texts.basics.back
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, end =
|
||||||
|
if not newAddon then
|
||||||
|
[ MB.DeleteButton
|
||||||
|
{ tagger = RequestDelete
|
||||||
|
, title = texts.deleteThisAddonArchive
|
||||||
|
, icon = Just "fa fa-trash"
|
||||||
|
, label = texts.basics.delete
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
, rootClasses = "mb-4"
|
||||||
|
, sticky = True
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ classList
|
||||||
|
[ ( "hidden", model.formError == FormErrorNone )
|
||||||
|
]
|
||||||
|
, class "my-2"
|
||||||
|
, class S.errorMessage
|
||||||
|
]
|
||||||
|
[ case model.formError of
|
||||||
|
FormErrorNone ->
|
||||||
|
text ""
|
||||||
|
|
||||||
|
FormErrorHttp err ->
|
||||||
|
text (texts.httpError err)
|
||||||
|
|
||||||
|
FormErrorInvalid ->
|
||||||
|
text texts.correctFormErrors
|
||||||
|
|
||||||
|
FormErrorSubmit m ->
|
||||||
|
text m
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ Html.map FormMsg (Comp.AddonArchiveForm.view texts.addonArchiveForm model.formModel)
|
||||||
|
]
|
||||||
|
, MB.view
|
||||||
|
{ start =
|
||||||
|
[ MB.PrimaryButton
|
||||||
|
{ tagger = Submit
|
||||||
|
, title = texts.installNow
|
||||||
|
, icon =
|
||||||
|
if newAddon then
|
||||||
|
Just "fa fa-save"
|
||||||
|
|
||||||
|
else
|
||||||
|
Just "fa fa-arrows-rotate"
|
||||||
|
, label =
|
||||||
|
if newAddon then
|
||||||
|
texts.installNow
|
||||||
|
|
||||||
|
else
|
||||||
|
texts.updateNow
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, end = []
|
||||||
|
, rootClasses = "mb-4"
|
||||||
|
, sticky = False
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ class "mb-4"
|
||||||
|
, classList [ ( "hidden", newAddon ) ]
|
||||||
|
]
|
||||||
|
[ label [ class S.inputLabel ] [ text texts.description ]
|
||||||
|
, case model.formModel.addon.description of
|
||||||
|
Just desc ->
|
||||||
|
Markdown.toHtml [ class "markdown-preview" ] desc
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
div [ class "italic" ] [ text "-" ]
|
||||||
|
]
|
||||||
|
, B.loadingDimmer
|
||||||
|
{ active = model.loading
|
||||||
|
, label = texts.basics.loading
|
||||||
|
}
|
||||||
|
, B.contentDimmer
|
||||||
|
(model.deleteConfirm == DeleteConfirmOn)
|
||||||
|
(div [ class "flex flex-col" ]
|
||||||
|
[ div [ class "text-lg" ]
|
||||||
|
[ i [ class "fa fa-info-circle mr-2" ] []
|
||||||
|
, text texts.reallyDeleteAddonArchive
|
||||||
|
]
|
||||||
|
, div [ class "mt-4 flex flex-row items-center" ]
|
||||||
|
[ B.deleteButton
|
||||||
|
{ label = texts.basics.yes
|
||||||
|
, icon = "fa fa-check"
|
||||||
|
, disabled = False
|
||||||
|
, handler = onClick (DeleteAddonNow model.formModel.addon.id)
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
}
|
||||||
|
, B.secondaryButton
|
||||||
|
{ label = texts.basics.no
|
||||||
|
, icon = "fa fa-times"
|
||||||
|
, disabled = False
|
||||||
|
, handler = onClick CancelDelete
|
||||||
|
, attrs = [ href "#", class "ml-2" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
72
modules/webapp/src/main/elm/Comp/AddonArchiveTable.elm
Normal file
72
modules/webapp/src/main/elm/Comp/AddonArchiveTable.elm
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.AddonArchiveTable exposing (..)
|
||||||
|
|
||||||
|
import Api.Model.Addon exposing (Addon)
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Html exposing (Html, div, table, tbody, td, text, th, thead, tr)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Messages.Comp.AddonArchiveTable exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SelectAddon Addon
|
||||||
|
|
||||||
|
|
||||||
|
type TableAction
|
||||||
|
= Selected Addon
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> TableAction
|
||||||
|
update msg =
|
||||||
|
case msg of
|
||||||
|
SelectAddon addon ->
|
||||||
|
Selected addon
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> List Addon -> Html Msg
|
||||||
|
view texts addons =
|
||||||
|
table [ class S.tableMain ]
|
||||||
|
[ thead []
|
||||||
|
[ tr []
|
||||||
|
[ th [ class "" ] []
|
||||||
|
, th [ class "text-left" ]
|
||||||
|
[ text texts.basics.name
|
||||||
|
]
|
||||||
|
, th [ class "text-left" ]
|
||||||
|
[ text texts.version
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, tbody []
|
||||||
|
(List.map (renderAddonLine texts) addons)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderAddonLine : Texts -> Addon -> Html Msg
|
||||||
|
renderAddonLine texts addon =
|
||||||
|
tr
|
||||||
|
[ class S.tableRow
|
||||||
|
]
|
||||||
|
[ B.editLinkTableCell texts.basics.edit (SelectAddon addon)
|
||||||
|
, td [ class "text-left py-4 md:py-2" ]
|
||||||
|
[ text addon.name
|
||||||
|
]
|
||||||
|
, td [ class "text-left" ]
|
||||||
|
[ text addon.version
|
||||||
|
]
|
||||||
|
]
|
709
modules/webapp/src/main/elm/Comp/AddonRunConfigForm.elm
Normal file
709
modules/webapp/src/main/elm/Comp/AddonRunConfigForm.elm
Normal file
@ -0,0 +1,709 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.AddonRunConfigForm exposing (Model, Msg, get, init, initWith, update, view)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.Addon exposing (Addon)
|
||||||
|
import Api.Model.AddonList exposing (AddonList)
|
||||||
|
import Api.Model.AddonRef exposing (AddonRef)
|
||||||
|
import Api.Model.AddonRunConfig exposing (AddonRunConfig)
|
||||||
|
import Api.Model.User exposing (User)
|
||||||
|
import Api.Model.UserList exposing (UserList)
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.CalEventInput
|
||||||
|
import Comp.Dropdown
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.AddonTrigger exposing (AddonTrigger)
|
||||||
|
import Data.CalEvent exposing (CalEvent)
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.TimeZone exposing (TimeZone)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Events exposing (onClick, onInput)
|
||||||
|
import Http
|
||||||
|
import Markdown
|
||||||
|
import Messages.Comp.AddonRunConfigForm exposing (Texts)
|
||||||
|
import Process
|
||||||
|
import Styles as S
|
||||||
|
import Task
|
||||||
|
import Util.List
|
||||||
|
import Util.String
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ runConfig : AddonRunConfig
|
||||||
|
, name : String
|
||||||
|
, enabled : Bool
|
||||||
|
, userDropdown : Comp.Dropdown.Model User
|
||||||
|
, userId : Maybe String
|
||||||
|
, userList : List User
|
||||||
|
, scheduleModel : Maybe Comp.CalEventInput.Model
|
||||||
|
, schedule : Maybe CalEvent
|
||||||
|
, triggerDropdown : Comp.Dropdown.Model AddonTrigger
|
||||||
|
, addons : List AddonRef
|
||||||
|
, selectedAddon : Maybe AddonConfigModel
|
||||||
|
, existingAddonDropdown : Comp.Dropdown.Model Addon
|
||||||
|
, existingAddons : List Addon
|
||||||
|
, configApplied : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias AddonConfigModel =
|
||||||
|
{ ref : AddonRef
|
||||||
|
, position : Int
|
||||||
|
, args : String
|
||||||
|
, readMore : Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getRef : AddonConfigModel -> AddonRef
|
||||||
|
getRef cfg =
|
||||||
|
let
|
||||||
|
a =
|
||||||
|
cfg.ref
|
||||||
|
in
|
||||||
|
{ a | args = cfg.args }
|
||||||
|
|
||||||
|
|
||||||
|
emptyModel : Model
|
||||||
|
emptyModel =
|
||||||
|
{ runConfig = Api.Model.AddonRunConfig.empty
|
||||||
|
, name = ""
|
||||||
|
, enabled = True
|
||||||
|
, userDropdown = Comp.Dropdown.makeSingle
|
||||||
|
, userId = Nothing
|
||||||
|
, userList = []
|
||||||
|
, scheduleModel = Nothing
|
||||||
|
, schedule = Nothing
|
||||||
|
, triggerDropdown =
|
||||||
|
Comp.Dropdown.makeMultipleList
|
||||||
|
{ options = Data.AddonTrigger.all, selected = [] }
|
||||||
|
, addons = []
|
||||||
|
, selectedAddon = Nothing
|
||||||
|
, existingAddonDropdown = Comp.Dropdown.makeSingle
|
||||||
|
, existingAddons = []
|
||||||
|
, configApplied = False
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
( emptyModel
|
||||||
|
, Cmd.batch
|
||||||
|
[ Api.getUsers flags UserListResp
|
||||||
|
, Api.addonsGetAll flags AddonListResp
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
initWith : Flags -> AddonRunConfig -> ( Model, Cmd Msg )
|
||||||
|
initWith flags a =
|
||||||
|
let
|
||||||
|
ce =
|
||||||
|
Maybe.andThen Data.CalEvent.fromEvent a.schedule
|
||||||
|
|
||||||
|
ceInit =
|
||||||
|
Maybe.map (Comp.CalEventInput.init flags) ce
|
||||||
|
|
||||||
|
triggerModel =
|
||||||
|
Comp.Dropdown.makeMultipleList
|
||||||
|
{ options = Data.AddonTrigger.all
|
||||||
|
, selected = Data.AddonTrigger.fromList a.trigger
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( { emptyModel
|
||||||
|
| runConfig = a
|
||||||
|
, name = a.name
|
||||||
|
, enabled = a.enabled
|
||||||
|
, scheduleModel = Maybe.map Tuple.first ceInit
|
||||||
|
, schedule = ce
|
||||||
|
, triggerDropdown = triggerModel
|
||||||
|
, userId = a.userId
|
||||||
|
, addons = a.addons
|
||||||
|
}
|
||||||
|
, Cmd.batch
|
||||||
|
[ Api.getUsers flags UserListResp
|
||||||
|
, Api.addonsGetAll flags AddonListResp
|
||||||
|
, Maybe.map Tuple.second ceInit
|
||||||
|
|> Maybe.map (Cmd.map ScheduleMsg)
|
||||||
|
|> Maybe.withDefault Cmd.none
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
isValid : Model -> Bool
|
||||||
|
isValid model =
|
||||||
|
model.name
|
||||||
|
/= ""
|
||||||
|
&& (Comp.Dropdown.getSelected model.triggerDropdown
|
||||||
|
|> List.isEmpty
|
||||||
|
|> not
|
||||||
|
)
|
||||||
|
&& (List.isEmpty model.addons
|
||||||
|
|> not
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
get : Model -> Maybe AddonRunConfig
|
||||||
|
get model =
|
||||||
|
let
|
||||||
|
a =
|
||||||
|
model.runConfig
|
||||||
|
in
|
||||||
|
if isValid model then
|
||||||
|
Just
|
||||||
|
{ a
|
||||||
|
| name = model.name
|
||||||
|
, enabled = model.enabled
|
||||||
|
, schedule = Maybe.map Data.CalEvent.makeEvent model.schedule
|
||||||
|
, trigger =
|
||||||
|
Comp.Dropdown.getSelected model.triggerDropdown
|
||||||
|
|> List.map Data.AddonTrigger.asString
|
||||||
|
, userId = model.userId
|
||||||
|
, addons = model.addons
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SetName String
|
||||||
|
| UserListResp (Result Http.Error UserList)
|
||||||
|
| AddonListResp (Result Http.Error AddonList)
|
||||||
|
| ScheduleMsg Comp.CalEventInput.Msg
|
||||||
|
| UserDropdownMsg (Comp.Dropdown.Msg User)
|
||||||
|
| TriggerDropdownMsg (Comp.Dropdown.Msg AddonTrigger)
|
||||||
|
| AddonDropdownMsg (Comp.Dropdown.Msg Addon)
|
||||||
|
| Configure Int AddonRef
|
||||||
|
| Up Int
|
||||||
|
| Down Int
|
||||||
|
| Remove Int
|
||||||
|
| ToggleEnabled
|
||||||
|
| ConfigSetArgs String
|
||||||
|
| ConfigApply
|
||||||
|
| ConfigCancel
|
||||||
|
| AddSelectedAddon
|
||||||
|
| ConfigToggleReadMore
|
||||||
|
| ConfigArgsUpdated Bool
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> TimeZone -> Msg -> Model -> ( Model, Cmd Msg )
|
||||||
|
update flags tz msg model =
|
||||||
|
case msg of
|
||||||
|
UserListResp (Ok list) ->
|
||||||
|
let
|
||||||
|
um =
|
||||||
|
Comp.Dropdown.makeSingleList
|
||||||
|
{ options = list.items
|
||||||
|
, selected = Nothing
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( { model | userDropdown = um, userList = list.items }, Cmd.none )
|
||||||
|
|
||||||
|
UserListResp (Err err) ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
AddonListResp (Ok list) ->
|
||||||
|
let
|
||||||
|
am =
|
||||||
|
Comp.Dropdown.makeSingleList
|
||||||
|
{ options = list.items
|
||||||
|
, selected = Nothing
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( { model | existingAddonDropdown = am, existingAddons = list.items }, Cmd.none )
|
||||||
|
|
||||||
|
AddonListResp (Err err) ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
UserDropdownMsg lm ->
|
||||||
|
let
|
||||||
|
( um, cmd ) =
|
||||||
|
Comp.Dropdown.update lm model.userDropdown
|
||||||
|
|
||||||
|
sel =
|
||||||
|
Comp.Dropdown.getSelected um |> List.head
|
||||||
|
in
|
||||||
|
( { model | userDropdown = um, userId = Maybe.map .id sel }, Cmd.map UserDropdownMsg cmd )
|
||||||
|
|
||||||
|
TriggerDropdownMsg lm ->
|
||||||
|
let
|
||||||
|
( tm, tc ) =
|
||||||
|
Comp.Dropdown.update lm model.triggerDropdown
|
||||||
|
|
||||||
|
( nm, nc ) =
|
||||||
|
initScheduleIfNeeded flags { model | triggerDropdown = tm } tz
|
||||||
|
in
|
||||||
|
( nm, Cmd.batch [ Cmd.map TriggerDropdownMsg tc, nc ] )
|
||||||
|
|
||||||
|
ScheduleMsg lm ->
|
||||||
|
case model.scheduleModel of
|
||||||
|
Just m ->
|
||||||
|
let
|
||||||
|
( cm, cc, ce ) =
|
||||||
|
Comp.CalEventInput.update flags tz model.schedule lm m
|
||||||
|
in
|
||||||
|
( { model | scheduleModel = Just cm, schedule = ce }, Cmd.map ScheduleMsg cc )
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
ToggleEnabled ->
|
||||||
|
( { model | enabled = not model.enabled }, Cmd.none )
|
||||||
|
|
||||||
|
AddonDropdownMsg lm ->
|
||||||
|
let
|
||||||
|
( am, ac ) =
|
||||||
|
Comp.Dropdown.update lm model.existingAddonDropdown
|
||||||
|
in
|
||||||
|
( { model | existingAddonDropdown = am }, Cmd.map AddonDropdownMsg ac )
|
||||||
|
|
||||||
|
Configure index ref ->
|
||||||
|
let
|
||||||
|
cfg =
|
||||||
|
{ ref = ref
|
||||||
|
, position = index + 1
|
||||||
|
, args = ref.args
|
||||||
|
, readMore = False
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( { model | selectedAddon = Just cfg }, Cmd.none )
|
||||||
|
|
||||||
|
ConfigCancel ->
|
||||||
|
( { model | selectedAddon = Nothing }, Cmd.none )
|
||||||
|
|
||||||
|
ConfigToggleReadMore ->
|
||||||
|
case model.selectedAddon of
|
||||||
|
Just cfg ->
|
||||||
|
( { model | selectedAddon = Just { cfg | readMore = not cfg.readMore } }, Cmd.none )
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
ConfigArgsUpdated flag ->
|
||||||
|
( { model | configApplied = flag }, Cmd.none )
|
||||||
|
|
||||||
|
ConfigSetArgs str ->
|
||||||
|
case model.selectedAddon of
|
||||||
|
Just cfg ->
|
||||||
|
( { model | selectedAddon = Just { cfg | args = str } }
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
ConfigApply ->
|
||||||
|
case model.selectedAddon of
|
||||||
|
Just cfg ->
|
||||||
|
let
|
||||||
|
na =
|
||||||
|
getRef cfg
|
||||||
|
|
||||||
|
addons =
|
||||||
|
Util.List.replaceByIndex (cfg.position - 1) na model.addons
|
||||||
|
in
|
||||||
|
( { model | addons = addons, configApplied = True }
|
||||||
|
, Process.sleep 1200 |> Task.perform (\_ -> ConfigArgsUpdated False)
|
||||||
|
)
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
AddSelectedAddon ->
|
||||||
|
let
|
||||||
|
sel =
|
||||||
|
Comp.Dropdown.getSelected model.existingAddonDropdown |> List.head
|
||||||
|
|
||||||
|
( dm, _ ) =
|
||||||
|
Comp.Dropdown.update (Comp.Dropdown.SetSelection []) model.existingAddonDropdown
|
||||||
|
|
||||||
|
addon =
|
||||||
|
Maybe.map
|
||||||
|
(\a ->
|
||||||
|
{ addonId = a.id
|
||||||
|
, name = a.name
|
||||||
|
, version = a.version
|
||||||
|
, description = a.description
|
||||||
|
, args = ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
sel
|
||||||
|
|
||||||
|
newAddons =
|
||||||
|
Maybe.map (\e -> e :: model.addons) addon
|
||||||
|
|> Maybe.withDefault model.addons
|
||||||
|
in
|
||||||
|
( { model | addons = newAddons, existingAddonDropdown = dm, selectedAddon = Nothing }, Cmd.none )
|
||||||
|
|
||||||
|
Up curIndex ->
|
||||||
|
let
|
||||||
|
newAddons =
|
||||||
|
Util.List.changePosition curIndex (curIndex - 1) model.addons
|
||||||
|
in
|
||||||
|
( { model | addons = newAddons, selectedAddon = Nothing }, Cmd.none )
|
||||||
|
|
||||||
|
Down curIndex ->
|
||||||
|
let
|
||||||
|
newAddons =
|
||||||
|
Util.List.changePosition (curIndex + 1) curIndex model.addons
|
||||||
|
in
|
||||||
|
( { model | addons = newAddons, selectedAddon = Nothing }, Cmd.none )
|
||||||
|
|
||||||
|
SetName str ->
|
||||||
|
( { model | name = str }, Cmd.none )
|
||||||
|
|
||||||
|
Remove index ->
|
||||||
|
( { model | addons = Util.List.removeByIndex index model.addons, selectedAddon = Nothing }, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
|
initScheduleIfNeeded : Flags -> Model -> TimeZone -> ( Model, Cmd Msg )
|
||||||
|
initScheduleIfNeeded flags model tz =
|
||||||
|
let
|
||||||
|
hasTrigger =
|
||||||
|
Comp.Dropdown.getSelected model.triggerDropdown
|
||||||
|
|> List.any ((==) Data.AddonTrigger.Scheduled)
|
||||||
|
|
||||||
|
noModel =
|
||||||
|
model.scheduleModel == Nothing
|
||||||
|
|
||||||
|
hasModel =
|
||||||
|
not noModel
|
||||||
|
|
||||||
|
ce =
|
||||||
|
Data.CalEvent.everyMonthTz tz
|
||||||
|
|
||||||
|
( cm, cc ) =
|
||||||
|
Comp.CalEventInput.init flags ce
|
||||||
|
in
|
||||||
|
if hasTrigger && noModel then
|
||||||
|
( { model | scheduleModel = Just cm, schedule = Just ce }, Cmd.map ScheduleMsg cc )
|
||||||
|
|
||||||
|
else if not hasTrigger && hasModel then
|
||||||
|
( { model | scheduleModel = Nothing, schedule = Nothing }, Cmd.none )
|
||||||
|
|
||||||
|
else
|
||||||
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts settings model =
|
||||||
|
let
|
||||||
|
userDs =
|
||||||
|
{ makeOption = \user -> { text = user.login, additional = "" }
|
||||||
|
, placeholder = texts.basics.selectPlaceholder
|
||||||
|
, labelColor = \_ -> \_ -> ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerDs =
|
||||||
|
{ makeOption = \trigger -> { text = Data.AddonTrigger.asString trigger, additional = "" }
|
||||||
|
, placeholder = texts.basics.selectPlaceholder
|
||||||
|
, labelColor = \_ -> \_ -> ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ class "flex flex-col" ]
|
||||||
|
[ div [ class "mb-4" ]
|
||||||
|
[ div [ class "mb-4" ]
|
||||||
|
[ label
|
||||||
|
[ class S.inputLabel
|
||||||
|
]
|
||||||
|
[ text texts.basics.name
|
||||||
|
, B.inputRequired
|
||||||
|
]
|
||||||
|
, input
|
||||||
|
[ type_ "text"
|
||||||
|
, placeholder texts.chooseName
|
||||||
|
, value model.name
|
||||||
|
, onInput SetName
|
||||||
|
, class S.textInput
|
||||||
|
, classList [ ( S.inputErrorBorder, model.name == "" ) ]
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ MB.viewItem <|
|
||||||
|
MB.Checkbox
|
||||||
|
{ tagger = \_ -> ToggleEnabled
|
||||||
|
, label = texts.enableDisable
|
||||||
|
, value = model.enabled
|
||||||
|
, id = "addon-run-config-enabled"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ label
|
||||||
|
[ class S.inputLabel
|
||||||
|
]
|
||||||
|
[ text texts.impersonateUser
|
||||||
|
]
|
||||||
|
, Html.map UserDropdownMsg
|
||||||
|
(Comp.Dropdown.view2 userDs settings model.userDropdown)
|
||||||
|
]
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ label
|
||||||
|
[ class S.inputLabel
|
||||||
|
]
|
||||||
|
[ text texts.triggerRun
|
||||||
|
, B.inputRequired
|
||||||
|
]
|
||||||
|
, Html.map TriggerDropdownMsg
|
||||||
|
(Comp.Dropdown.view2 triggerDs settings model.triggerDropdown)
|
||||||
|
]
|
||||||
|
, case model.scheduleModel of
|
||||||
|
Nothing ->
|
||||||
|
span [ class "hidden" ] []
|
||||||
|
|
||||||
|
Just m ->
|
||||||
|
div [ class "mb-4" ]
|
||||||
|
[ label
|
||||||
|
[ class S.inputLabel ]
|
||||||
|
[ text texts.schedule
|
||||||
|
]
|
||||||
|
, Html.map ScheduleMsg (Comp.CalEventInput.view2 texts.calEventInput "" model.schedule m)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ h2 [ class S.header2 ]
|
||||||
|
[ text texts.addons ]
|
||||||
|
, addonRef texts model
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.includedAddons
|
||||||
|
, B.inputRequired
|
||||||
|
]
|
||||||
|
, newAddon texts settings model
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ div [ class "flex flex-col mb-4" ]
|
||||||
|
(List.indexedMap (addonLine texts model) model.addons)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
newAddon : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
newAddon texts uiSettings model =
|
||||||
|
let
|
||||||
|
addonDs =
|
||||||
|
{ makeOption = \addon -> { text = addon.name ++ " / " ++ addon.version, additional = "" }
|
||||||
|
, placeholder = texts.basics.selectPlaceholder
|
||||||
|
, labelColor = \_ -> \_ -> ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
in
|
||||||
|
div [ class "mb-4" ]
|
||||||
|
[ div [ class "flex flex-row" ]
|
||||||
|
[ div [ class "flex-grow mr-2" ]
|
||||||
|
[ Html.map AddonDropdownMsg
|
||||||
|
(Comp.Dropdown.view2 addonDs uiSettings model.existingAddonDropdown)
|
||||||
|
]
|
||||||
|
, B.primaryBasicButton
|
||||||
|
{ label = texts.add
|
||||||
|
, icon = "fa fa-plus"
|
||||||
|
, disabled = List.isEmpty (Comp.Dropdown.getSelected model.existingAddonDropdown)
|
||||||
|
, handler = onClick AddSelectedAddon
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
addonRef : Texts -> Model -> Html Msg
|
||||||
|
addonRef texts model =
|
||||||
|
let
|
||||||
|
maybeRef =
|
||||||
|
Maybe.map .ref model.selectedAddon
|
||||||
|
|
||||||
|
refInfo =
|
||||||
|
case model.selectedAddon of
|
||||||
|
Nothing ->
|
||||||
|
div [ class "mb-4" ]
|
||||||
|
[ text "[ -- ]"
|
||||||
|
]
|
||||||
|
|
||||||
|
Just cfg ->
|
||||||
|
let
|
||||||
|
( descr, requireFolding ) =
|
||||||
|
case cfg.ref.description of
|
||||||
|
Just d ->
|
||||||
|
let
|
||||||
|
part =
|
||||||
|
Util.String.firstSentenceOrMax 120 d
|
||||||
|
|
||||||
|
text =
|
||||||
|
if cfg.readMore then
|
||||||
|
d
|
||||||
|
|
||||||
|
else
|
||||||
|
Maybe.withDefault d part
|
||||||
|
in
|
||||||
|
( Markdown.toHtml [ class "markdown-preview" ] text, part /= Nothing )
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( span [ class "italic" ] [ text "No description." ], False )
|
||||||
|
in
|
||||||
|
div [ class "flex flex-col mb-4" ]
|
||||||
|
[ div [ class "mt-2" ]
|
||||||
|
[ label [ class " font-semibold py-0.5 " ]
|
||||||
|
[ text cfg.ref.name
|
||||||
|
, text " "
|
||||||
|
, text cfg.ref.version
|
||||||
|
, text " (pos. "
|
||||||
|
, text <| String.fromInt cfg.position
|
||||||
|
, text ")"
|
||||||
|
, span
|
||||||
|
[ classList [ ( "hidden", not requireFolding ) ]
|
||||||
|
, class "ml-2"
|
||||||
|
]
|
||||||
|
[ a
|
||||||
|
[ class "px-4"
|
||||||
|
, class S.link
|
||||||
|
, href "#"
|
||||||
|
, onClick ConfigToggleReadMore
|
||||||
|
]
|
||||||
|
[ if cfg.readMore then
|
||||||
|
text texts.readLess
|
||||||
|
|
||||||
|
else
|
||||||
|
text texts.readMore
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "px-3 py-1 border-l dark:border-slate-600" ]
|
||||||
|
[ descr
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ class "flex flex-col mb-3"
|
||||||
|
, classList [ ( "disabled", maybeRef == Nothing ) ]
|
||||||
|
]
|
||||||
|
[ refInfo
|
||||||
|
, div [ class "mb-2" ]
|
||||||
|
[ label [ class S.inputLabel ] [ text texts.arguments ]
|
||||||
|
, textarea
|
||||||
|
[ Maybe.map .args model.selectedAddon |> Maybe.withDefault "" |> value
|
||||||
|
, class S.textAreaInput
|
||||||
|
, class "font-mono"
|
||||||
|
, rows 8
|
||||||
|
, onInput ConfigSetArgs
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
, MB.view
|
||||||
|
{ start =
|
||||||
|
[ MB.PrimaryButton
|
||||||
|
{ tagger = ConfigApply
|
||||||
|
, title = ""
|
||||||
|
, icon = Just "fa fa-save"
|
||||||
|
, label = texts.update
|
||||||
|
}
|
||||||
|
, MB.SecondaryButton
|
||||||
|
{ tagger = ConfigCancel
|
||||||
|
, title = texts.basics.cancel
|
||||||
|
, icon = Just "fa fa-times"
|
||||||
|
, label = texts.basics.cancel
|
||||||
|
}
|
||||||
|
, MB.CustomElement <|
|
||||||
|
div
|
||||||
|
[ classList [ ( "hidden", not model.configApplied ) ]
|
||||||
|
, class S.successText
|
||||||
|
, class "inline-block min-w-fit font-semibold text-normal min-w-fit"
|
||||||
|
]
|
||||||
|
[ text texts.argumentsUpdated
|
||||||
|
, i [ class "fa fa-thumbs-up ml-2" ] []
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, end = []
|
||||||
|
, rootClasses = "mb-4 text-sm"
|
||||||
|
, sticky = False
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
addonLine : Texts -> Model -> Int -> AddonRef -> Html Msg
|
||||||
|
addonLine texts model index ref =
|
||||||
|
let
|
||||||
|
isSelected =
|
||||||
|
case model.selectedAddon of
|
||||||
|
Just cfg ->
|
||||||
|
cfg.position - 1 == index
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
False
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ class "flex flex-row items-center px-4 py-4 rounded shadow dark:border dark:border-slate-600 mb-2"
|
||||||
|
, classList [ ( "ring-2", isSelected ) ]
|
||||||
|
]
|
||||||
|
[ div [ class "px-2 hidden sm:block" ]
|
||||||
|
[ span [ class "label rounded-full opacity-75" ]
|
||||||
|
[ text <| String.fromInt (index + 1)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div [ class "px-4 font-semibold" ]
|
||||||
|
[ text ref.name
|
||||||
|
, text " v"
|
||||||
|
, text ref.version
|
||||||
|
]
|
||||||
|
, div [ class "flex-grow" ]
|
||||||
|
[]
|
||||||
|
, div [ class "px-2" ]
|
||||||
|
[ MB.view
|
||||||
|
{ start = []
|
||||||
|
, end =
|
||||||
|
[ MB.PrimaryButton
|
||||||
|
{ tagger = Configure index ref
|
||||||
|
, title = texts.configureTitle
|
||||||
|
, icon = Just "fa fa-cog"
|
||||||
|
, label = texts.configureLabel
|
||||||
|
}
|
||||||
|
, MB.CustomElement <|
|
||||||
|
B.secondaryButton
|
||||||
|
{ handler = onClick (Up index)
|
||||||
|
, attrs = [ title "Move up", href "#" ]
|
||||||
|
, icon = "fa fa-arrow-up"
|
||||||
|
, label = ""
|
||||||
|
, disabled = index == 0
|
||||||
|
}
|
||||||
|
, MB.CustomElement <|
|
||||||
|
B.secondaryButton
|
||||||
|
{ handler = onClick (Down index)
|
||||||
|
, attrs = [ title "Move down", href "#" ]
|
||||||
|
, icon = "fa fa-arrow-down"
|
||||||
|
, label = ""
|
||||||
|
, disabled = index + 1 == List.length model.addons
|
||||||
|
}
|
||||||
|
, MB.CustomElement <|
|
||||||
|
B.deleteButton
|
||||||
|
{ label = ""
|
||||||
|
, icon = "fa fa-trash"
|
||||||
|
, disabled = False
|
||||||
|
, handler = onClick (Remove index)
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, rootClasses = "text-sm"
|
||||||
|
, sticky = False
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
364
modules/webapp/src/main/elm/Comp/AddonRunConfigManage.elm
Normal file
364
modules/webapp/src/main/elm/Comp/AddonRunConfigManage.elm
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.AddonRunConfigManage exposing (Model, Msg, init, loadConfigs, update, view)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Api.Model.AddonRunConfig exposing (AddonRunConfig)
|
||||||
|
import Api.Model.AddonRunConfigList exposing (AddonRunConfigList)
|
||||||
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
|
import Comp.AddonRunConfigForm
|
||||||
|
import Comp.AddonRunConfigTable
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.ItemDetail.Model exposing (Msg(..))
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.TimeZone exposing (TimeZone)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Events exposing (onClick)
|
||||||
|
import Http
|
||||||
|
import Messages.Comp.AddonRunConfigManage exposing (Texts)
|
||||||
|
import Page exposing (Page(..))
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
type FormError
|
||||||
|
= FormErrorNone
|
||||||
|
| FormErrorHttp Http.Error
|
||||||
|
| FormErrorInvalid
|
||||||
|
| FormErrorSubmit String
|
||||||
|
|
||||||
|
|
||||||
|
type ViewMode
|
||||||
|
= Table
|
||||||
|
| Form
|
||||||
|
|
||||||
|
|
||||||
|
type DeleteConfirm
|
||||||
|
= DeleteConfirmOff
|
||||||
|
| DeleteConfirmOn
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ viewMode : ViewMode
|
||||||
|
, runConfigs : List AddonRunConfig
|
||||||
|
, formModel : Comp.AddonRunConfigForm.Model
|
||||||
|
, loading : Bool
|
||||||
|
, formError : FormError
|
||||||
|
, deleteConfirm : DeleteConfirm
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
|
init flags =
|
||||||
|
let
|
||||||
|
( fm, fc ) =
|
||||||
|
Comp.AddonRunConfigForm.init flags
|
||||||
|
in
|
||||||
|
( { viewMode = Table
|
||||||
|
, runConfigs = []
|
||||||
|
, formModel = fm
|
||||||
|
, loading = False
|
||||||
|
, formError = FormErrorNone
|
||||||
|
, deleteConfirm = DeleteConfirmOff
|
||||||
|
}
|
||||||
|
, Cmd.batch
|
||||||
|
[ Cmd.map FormMsg fc
|
||||||
|
, Api.addonRunConfigGet flags LoadConfigsResp
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= LoadRunConfigs
|
||||||
|
| TableMsg Comp.AddonRunConfigTable.Msg
|
||||||
|
| FormMsg Comp.AddonRunConfigForm.Msg
|
||||||
|
| InitNewConfig
|
||||||
|
| SetViewMode ViewMode
|
||||||
|
| Submit
|
||||||
|
| RequestDelete
|
||||||
|
| CancelDelete
|
||||||
|
| DeleteConfigNow String
|
||||||
|
| LoadConfigsResp (Result Http.Error AddonRunConfigList)
|
||||||
|
| AddConfigResp (Result Http.Error BasicResult)
|
||||||
|
| DeleteConfigResp (Result Http.Error BasicResult)
|
||||||
|
|
||||||
|
|
||||||
|
loadConfigs : Msg
|
||||||
|
loadConfigs =
|
||||||
|
LoadRunConfigs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- update
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> TimeZone -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
|
update flags tz msg model =
|
||||||
|
case msg of
|
||||||
|
InitNewConfig ->
|
||||||
|
let
|
||||||
|
( bm, bc ) =
|
||||||
|
Comp.AddonRunConfigForm.init flags
|
||||||
|
|
||||||
|
nm =
|
||||||
|
{ model
|
||||||
|
| viewMode = Form
|
||||||
|
, formError = FormErrorNone
|
||||||
|
, formModel = bm
|
||||||
|
}
|
||||||
|
in
|
||||||
|
( nm, Cmd.map FormMsg bc, Sub.none )
|
||||||
|
|
||||||
|
SetViewMode vm ->
|
||||||
|
( { model | viewMode = vm, formError = FormErrorNone }
|
||||||
|
, if vm == Table then
|
||||||
|
Api.addonRunConfigGet flags LoadConfigsResp
|
||||||
|
|
||||||
|
else
|
||||||
|
Cmd.none
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
FormMsg lm ->
|
||||||
|
let
|
||||||
|
( fm, fc ) =
|
||||||
|
Comp.AddonRunConfigForm.update flags tz lm model.formModel
|
||||||
|
in
|
||||||
|
( { model | formModel = fm, formError = FormErrorNone }
|
||||||
|
, Cmd.map FormMsg fc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
TableMsg lm ->
|
||||||
|
let
|
||||||
|
action =
|
||||||
|
Comp.AddonRunConfigTable.update lm
|
||||||
|
in
|
||||||
|
case action of
|
||||||
|
Comp.AddonRunConfigTable.Selected addon ->
|
||||||
|
let
|
||||||
|
( bm, bc ) =
|
||||||
|
Comp.AddonRunConfigForm.initWith flags addon
|
||||||
|
in
|
||||||
|
( { model
|
||||||
|
| viewMode = Form
|
||||||
|
, formError = FormErrorNone
|
||||||
|
, formModel = bm
|
||||||
|
}
|
||||||
|
, Cmd.map FormMsg bc
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
RequestDelete ->
|
||||||
|
( { model | deleteConfirm = DeleteConfirmOn }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
CancelDelete ->
|
||||||
|
( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DeleteConfigNow id ->
|
||||||
|
( { model | deleteConfirm = DeleteConfirmOff, loading = True }
|
||||||
|
, Api.addonRunConfigDelete flags id DeleteConfigResp
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadRunConfigs ->
|
||||||
|
( { model | loading = True }
|
||||||
|
, Api.addonRunConfigGet flags LoadConfigsResp
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadConfigsResp (Ok list) ->
|
||||||
|
( { model | loading = False, runConfigs = list.items, formError = FormErrorNone }
|
||||||
|
, Cmd.none
|
||||||
|
, Sub.none
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadConfigsResp (Err err) ->
|
||||||
|
( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
Submit ->
|
||||||
|
case Comp.AddonRunConfigForm.get model.formModel of
|
||||||
|
Just data ->
|
||||||
|
( { model | loading = True }, Api.addonRunConfigSet flags data AddConfigResp, Sub.none )
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( { model | formError = FormErrorInvalid }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
AddConfigResp (Ok res) ->
|
||||||
|
if res.success then
|
||||||
|
( { model | loading = False }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | loading = False, formError = FormErrorSubmit res.message }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
AddConfigResp (Err err) ->
|
||||||
|
( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DeleteConfigResp (Ok res) ->
|
||||||
|
if res.success then
|
||||||
|
update flags tz (SetViewMode Table) { model | loading = False }
|
||||||
|
|
||||||
|
else
|
||||||
|
( { model | formError = FormErrorSubmit res.message, loading = False }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
DeleteConfigResp (Err err) ->
|
||||||
|
( { model | formError = FormErrorHttp err, loading = False }, Cmd.none, Sub.none )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- view
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Flags -> Model -> Html Msg
|
||||||
|
view texts settings flags model =
|
||||||
|
if model.viewMode == Table then
|
||||||
|
viewTable texts model
|
||||||
|
|
||||||
|
else
|
||||||
|
viewForm texts settings flags model
|
||||||
|
|
||||||
|
|
||||||
|
viewTable : Texts -> Model -> Html Msg
|
||||||
|
viewTable texts model =
|
||||||
|
div [ class "flex flex-col" ]
|
||||||
|
[ MB.view
|
||||||
|
{ start =
|
||||||
|
[]
|
||||||
|
, end =
|
||||||
|
[ MB.PrimaryButton
|
||||||
|
{ tagger = InitNewConfig
|
||||||
|
, title = texts.createNewAddonRunConfig
|
||||||
|
, icon = Just "fa fa-plus"
|
||||||
|
, label = texts.newAddonRunConfig
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, rootClasses = "mb-4"
|
||||||
|
, sticky = True
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ class "flex flex-col"
|
||||||
|
]
|
||||||
|
[ Html.map TableMsg
|
||||||
|
(Comp.AddonRunConfigTable.view texts.addonArchiveTable model.runConfigs)
|
||||||
|
]
|
||||||
|
, B.loadingDimmer
|
||||||
|
{ label = ""
|
||||||
|
, active = model.loading
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewForm : Texts -> UiSettings -> Flags -> Model -> Html Msg
|
||||||
|
viewForm texts uiSettings _ model =
|
||||||
|
let
|
||||||
|
newConfig =
|
||||||
|
model.formModel.runConfig.id == ""
|
||||||
|
|
||||||
|
isValid =
|
||||||
|
Comp.AddonRunConfigForm.get model.formModel /= Nothing
|
||||||
|
in
|
||||||
|
div []
|
||||||
|
[ Html.form []
|
||||||
|
[ if newConfig then
|
||||||
|
h1 [ class S.header2 ]
|
||||||
|
[ text texts.createNewAddonRunConfig
|
||||||
|
]
|
||||||
|
|
||||||
|
else
|
||||||
|
h1 [ class S.header2 ]
|
||||||
|
[ text (Comp.AddonRunConfigForm.get model.formModel |> Maybe.map .name |> Maybe.withDefault "Update")
|
||||||
|
]
|
||||||
|
, MB.view
|
||||||
|
{ start =
|
||||||
|
[ MB.CustomElement <|
|
||||||
|
B.primaryButton
|
||||||
|
{ handler = onClick Submit
|
||||||
|
, title = texts.basics.submitThisForm
|
||||||
|
, icon = "fa fa-save"
|
||||||
|
, label = texts.basics.submit
|
||||||
|
, disabled = not isValid
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
}
|
||||||
|
, MB.SecondaryButton
|
||||||
|
{ tagger = SetViewMode Table
|
||||||
|
, title = texts.basics.backToList
|
||||||
|
, icon = Just "fa fa-arrow-left"
|
||||||
|
, label = texts.basics.back
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, end =
|
||||||
|
if not newConfig then
|
||||||
|
[ MB.DeleteButton
|
||||||
|
{ tagger = RequestDelete
|
||||||
|
, title = texts.deleteThisAddonRunConfig
|
||||||
|
, icon = Just "fa fa-trash"
|
||||||
|
, label = texts.basics.delete
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
, rootClasses = "mb-4"
|
||||||
|
, sticky = True
|
||||||
|
}
|
||||||
|
, div
|
||||||
|
[ classList
|
||||||
|
[ ( "hidden", model.formError == FormErrorNone )
|
||||||
|
]
|
||||||
|
, class "my-2"
|
||||||
|
, class S.errorMessage
|
||||||
|
]
|
||||||
|
[ case model.formError of
|
||||||
|
FormErrorNone ->
|
||||||
|
text ""
|
||||||
|
|
||||||
|
FormErrorHttp err ->
|
||||||
|
text (texts.httpError err)
|
||||||
|
|
||||||
|
FormErrorInvalid ->
|
||||||
|
text texts.correctFormErrors
|
||||||
|
|
||||||
|
FormErrorSubmit m ->
|
||||||
|
text m
|
||||||
|
]
|
||||||
|
, div []
|
||||||
|
[ Html.map FormMsg (Comp.AddonRunConfigForm.view texts.addonArchiveForm uiSettings model.formModel)
|
||||||
|
]
|
||||||
|
, B.loadingDimmer
|
||||||
|
{ active = model.loading
|
||||||
|
, label = texts.basics.loading
|
||||||
|
}
|
||||||
|
, B.contentDimmer
|
||||||
|
(model.deleteConfirm == DeleteConfirmOn)
|
||||||
|
(div [ class "flex flex-col" ]
|
||||||
|
[ div [ class "text-lg" ]
|
||||||
|
[ i [ class "fa fa-info-circle mr-2" ] []
|
||||||
|
, text texts.reallyDeleteAddonRunConfig
|
||||||
|
]
|
||||||
|
, div [ class "mt-4 flex flex-row items-center" ]
|
||||||
|
[ B.deleteButton
|
||||||
|
{ label = texts.basics.yes
|
||||||
|
, icon = "fa fa-check"
|
||||||
|
, disabled = False
|
||||||
|
, handler = onClick (DeleteConfigNow model.formModel.runConfig.id)
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
}
|
||||||
|
, B.secondaryButton
|
||||||
|
{ label = texts.basics.no
|
||||||
|
, icon = "fa fa-times"
|
||||||
|
, disabled = False
|
||||||
|
, handler = onClick CancelDelete
|
||||||
|
, attrs = [ href "#", class "ml-2" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
79
modules/webapp/src/main/elm/Comp/AddonRunConfigTable.elm
Normal file
79
modules/webapp/src/main/elm/Comp/AddonRunConfigTable.elm
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.AddonRunConfigTable exposing (..)
|
||||||
|
|
||||||
|
import Api.Model.AddonRunConfig exposing (AddonRunConfig)
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Html exposing (Html, div, table, tbody, td, text, th, thead, tr)
|
||||||
|
import Html.Attributes exposing (class)
|
||||||
|
import Messages.Comp.AddonRunConfigTable exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
import Util.Html
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= SelectRunConfig AddonRunConfig
|
||||||
|
|
||||||
|
|
||||||
|
type TableAction
|
||||||
|
= Selected AddonRunConfig
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Update
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> TableAction
|
||||||
|
update msg =
|
||||||
|
case msg of
|
||||||
|
SelectRunConfig cfg ->
|
||||||
|
Selected cfg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> List AddonRunConfig -> Html Msg
|
||||||
|
view texts addons =
|
||||||
|
table [ class S.tableMain ]
|
||||||
|
[ thead []
|
||||||
|
[ tr []
|
||||||
|
[ th [ class "" ] []
|
||||||
|
, th [ class "text-left" ]
|
||||||
|
[ text texts.basics.name
|
||||||
|
]
|
||||||
|
, th [ class "px-2 text-center" ] [ text texts.enabled ]
|
||||||
|
, th [ class "px-2 text-left" ] [ text texts.trigger ]
|
||||||
|
, th [ class "px-2 text-center" ] [ text "# Addons" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, tbody []
|
||||||
|
(List.map (renderRunConfigLine texts) addons)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
renderRunConfigLine : Texts -> AddonRunConfig -> Html Msg
|
||||||
|
renderRunConfigLine texts cfg =
|
||||||
|
tr
|
||||||
|
[ class S.tableRow
|
||||||
|
]
|
||||||
|
[ B.editLinkTableCell texts.basics.edit (SelectRunConfig cfg)
|
||||||
|
, td [ class "text-left py-4 md:py-2" ]
|
||||||
|
[ text cfg.name
|
||||||
|
]
|
||||||
|
, td [ class "w-px whitespace-nowrap px-2 text-center" ]
|
||||||
|
[ Util.Html.checkbox2 cfg.enabled
|
||||||
|
]
|
||||||
|
, td [ class "px-2 text-left" ]
|
||||||
|
[ text (String.join ", " cfg.trigger)
|
||||||
|
]
|
||||||
|
, td [ class "px-2 text-center" ]
|
||||||
|
[ text (String.fromInt <| List.length cfg.addons)
|
||||||
|
]
|
||||||
|
]
|
@ -28,6 +28,8 @@ module Comp.ItemDetail.Model exposing
|
|||||||
, resultModelCmdSub
|
, resultModelCmdSub
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import Api.Model.AddonRunConfig exposing (AddonRunConfig)
|
||||||
|
import Api.Model.AddonRunConfigList exposing (AddonRunConfigList)
|
||||||
import Api.Model.BasicResult exposing (BasicResult)
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
import Api.Model.CustomField exposing (CustomField)
|
import Api.Model.CustomField exposing (CustomField)
|
||||||
import Api.Model.EquipmentList exposing (EquipmentList)
|
import Api.Model.EquipmentList exposing (EquipmentList)
|
||||||
@ -72,6 +74,7 @@ import Set exposing (Set)
|
|||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ item : ItemDetail
|
{ item : ItemDetail
|
||||||
|
, runConfigs : List AddonRunConfig
|
||||||
, visibleAttach : Int
|
, visibleAttach : Int
|
||||||
, attachMenuOpen : Bool
|
, attachMenuOpen : Bool
|
||||||
, menuOpen : Bool
|
, menuOpen : Bool
|
||||||
@ -123,6 +126,9 @@ type alias Model =
|
|||||||
, viewMode : ViewMode
|
, viewMode : ViewMode
|
||||||
, showQrModel : ShowQrModel
|
, showQrModel : ShowQrModel
|
||||||
, itemLinkModel : Comp.ItemLinkForm.Model
|
, itemLinkModel : Comp.ItemLinkForm.Model
|
||||||
|
, showRunAddon : Bool
|
||||||
|
, addonRunConfigDropdown : Comp.Dropdown.Model AddonRunConfig
|
||||||
|
, addonRunSubmitted : Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -204,6 +210,7 @@ isEditNotes field =
|
|||||||
emptyModel : Model
|
emptyModel : Model
|
||||||
emptyModel =
|
emptyModel =
|
||||||
{ item = Api.Model.ItemDetail.empty
|
{ item = Api.Model.ItemDetail.empty
|
||||||
|
, runConfigs = []
|
||||||
, visibleAttach = 0
|
, visibleAttach = 0
|
||||||
, attachMenuOpen = False
|
, attachMenuOpen = False
|
||||||
, menuOpen = False
|
, menuOpen = False
|
||||||
@ -259,6 +266,9 @@ emptyModel =
|
|||||||
, viewMode = SimpleView
|
, viewMode = SimpleView
|
||||||
, showQrModel = initShowQrModel
|
, showQrModel = initShowQrModel
|
||||||
, itemLinkModel = Comp.ItemLinkForm.emptyModel
|
, itemLinkModel = Comp.ItemLinkForm.emptyModel
|
||||||
|
, showRunAddon = False
|
||||||
|
, addonRunConfigDropdown = Comp.Dropdown.makeSingle
|
||||||
|
, addonRunSubmitted = False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -373,6 +383,12 @@ type Msg
|
|||||||
| SetNameMsg Comp.SimpleTextInput.Msg
|
| SetNameMsg Comp.SimpleTextInput.Msg
|
||||||
| ToggleSelectItem
|
| ToggleSelectItem
|
||||||
| ItemLinkFormMsg Comp.ItemLinkForm.Msg
|
| ItemLinkFormMsg Comp.ItemLinkForm.Msg
|
||||||
|
| ToggleShowRunAddon
|
||||||
|
| LoadRunConfigResp (Result Http.Error AddonRunConfigList)
|
||||||
|
| RunAddonMsg (Comp.Dropdown.Msg AddonRunConfig)
|
||||||
|
| RunSelectedAddon
|
||||||
|
| RunAddonResp (Result Http.Error BasicResult)
|
||||||
|
| SetAddonRunSubmitted Bool
|
||||||
|
|
||||||
|
|
||||||
type SaveNameState
|
type SaveNameState
|
||||||
|
78
modules/webapp/src/main/elm/Comp/ItemDetail/RunAddonForm.elm
Normal file
78
modules/webapp/src/main/elm/Comp/ItemDetail/RunAddonForm.elm
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.ItemDetail.RunAddonForm exposing (..)
|
||||||
|
|
||||||
|
import Comp.Basic as B
|
||||||
|
import Comp.Dropdown
|
||||||
|
import Comp.ItemDetail.Model exposing (..)
|
||||||
|
import Comp.MenuBar as MB
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (Html, div, h3, label, text)
|
||||||
|
import Html.Attributes exposing (class, classList, title)
|
||||||
|
import Html.Events exposing (onClick)
|
||||||
|
import Messages.Comp.ItemDetail.RunAddonForm exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts uiSettings model =
|
||||||
|
let
|
||||||
|
viewSettings =
|
||||||
|
{ makeOption = \cfg -> { text = cfg.name, additional = "" }
|
||||||
|
, placeholder = texts.basics.selectPlaceholder
|
||||||
|
, labelColor = \_ -> \_ -> ""
|
||||||
|
, style = DS.mainStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
runDisabled =
|
||||||
|
Comp.Dropdown.getSelected model.addonRunConfigDropdown
|
||||||
|
|> List.isEmpty
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ classList [ ( "hidden", not model.showRunAddon ) ]
|
||||||
|
, class "mb-4"
|
||||||
|
]
|
||||||
|
[ h3 [ class S.header3 ] [ text texts.runAddon ]
|
||||||
|
, div [ class "my-2" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.addonRunConfig
|
||||||
|
]
|
||||||
|
, Html.map RunAddonMsg (Comp.Dropdown.view2 viewSettings uiSettings model.addonRunConfigDropdown)
|
||||||
|
]
|
||||||
|
, div [ class "my-2" ]
|
||||||
|
[ MB.view
|
||||||
|
{ start =
|
||||||
|
[ MB.CustomElement <|
|
||||||
|
B.primaryButton
|
||||||
|
{ label = "Run"
|
||||||
|
, icon =
|
||||||
|
if model.addonRunSubmitted then
|
||||||
|
"fa fa-check"
|
||||||
|
|
||||||
|
else
|
||||||
|
"fa fa-play"
|
||||||
|
, disabled = runDisabled
|
||||||
|
, handler = onClick RunSelectedAddon
|
||||||
|
, attrs =
|
||||||
|
[ title texts.runAddonTitle
|
||||||
|
]
|
||||||
|
}
|
||||||
|
, MB.SecondaryButton
|
||||||
|
{ label = texts.basics.cancel
|
||||||
|
, icon = Just "fa fa-times"
|
||||||
|
, tagger = ToggleShowRunAddon
|
||||||
|
, title = ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, end = []
|
||||||
|
, rootClasses = "text-sm mt-1"
|
||||||
|
, sticky = False
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
@ -56,6 +56,7 @@ import Comp.PersonForm
|
|||||||
import Comp.SentMails
|
import Comp.SentMails
|
||||||
import Comp.SimpleTextInput
|
import Comp.SimpleTextInput
|
||||||
import Comp.TagDropdown
|
import Comp.TagDropdown
|
||||||
|
import Data.AddonTrigger
|
||||||
import Data.CustomFieldChange exposing (CustomFieldChange(..))
|
import Data.CustomFieldChange exposing (CustomFieldChange(..))
|
||||||
import Data.Direction
|
import Data.Direction
|
||||||
import Data.Environment as Env
|
import Data.Environment as Env
|
||||||
@ -75,7 +76,9 @@ import Html5.DragDrop as DD
|
|||||||
import Http
|
import Http
|
||||||
import Page exposing (Page(..))
|
import Page exposing (Page(..))
|
||||||
import Ports
|
import Ports
|
||||||
|
import Process
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
import Task
|
||||||
import Util.File exposing (makeFileId)
|
import Util.File exposing (makeFileId)
|
||||||
import Util.List
|
import Util.List
|
||||||
import Util.Maybe
|
import Util.Maybe
|
||||||
@ -121,9 +124,77 @@ update inav env msg model =
|
|||||||
, Cmd.map ItemMailMsg ic
|
, Cmd.map ItemMailMsg ic
|
||||||
, Cmd.map CustomFieldMsg cc
|
, Cmd.map CustomFieldMsg cc
|
||||||
, Api.getSentMails env.flags model.item.id SentMailsResp
|
, Api.getSentMails env.flags model.item.id SentMailsResp
|
||||||
|
, Api.addonRunConfigGet env.flags LoadRunConfigResp
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LoadRunConfigResp (Ok list) ->
|
||||||
|
let
|
||||||
|
existingItem cfg =
|
||||||
|
cfg.enabled
|
||||||
|
&& (Data.AddonTrigger.fromList cfg.trigger
|
||||||
|
|> List.any ((==) Data.AddonTrigger.ExistingItem)
|
||||||
|
)
|
||||||
|
|
||||||
|
configs =
|
||||||
|
List.filter existingItem list.items
|
||||||
|
|
||||||
|
dropdown =
|
||||||
|
Comp.Dropdown.makeSingleList { options = configs, selected = Nothing }
|
||||||
|
in
|
||||||
|
resultModel { model | runConfigs = configs, addonRunConfigDropdown = dropdown }
|
||||||
|
|
||||||
|
RunAddonMsg lm ->
|
||||||
|
let
|
||||||
|
( dd, dc ) =
|
||||||
|
Comp.Dropdown.update lm model.addonRunConfigDropdown
|
||||||
|
in
|
||||||
|
resultModelCmd ( { model | addonRunConfigDropdown = dd }, Cmd.map RunAddonMsg dc )
|
||||||
|
|
||||||
|
RunSelectedAddon ->
|
||||||
|
let
|
||||||
|
configs =
|
||||||
|
Comp.Dropdown.getSelected model.addonRunConfigDropdown
|
||||||
|
|> List.map .id
|
||||||
|
|
||||||
|
payload =
|
||||||
|
{ itemId = model.item.id
|
||||||
|
, additionalItems = []
|
||||||
|
, addonRunConfigIds = configs
|
||||||
|
}
|
||||||
|
|
||||||
|
( dd, _ ) =
|
||||||
|
Comp.Dropdown.update (Comp.Dropdown.SetSelection []) model.addonRunConfigDropdown
|
||||||
|
in
|
||||||
|
case configs of
|
||||||
|
[] ->
|
||||||
|
resultModel model
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
resultModelCmd
|
||||||
|
( { model | addonRunConfigDropdown = dd }
|
||||||
|
, Api.addonRunExistingItem env.flags payload RunAddonResp
|
||||||
|
)
|
||||||
|
|
||||||
|
LoadRunConfigResp (Err _) ->
|
||||||
|
resultModel model
|
||||||
|
|
||||||
|
RunAddonResp (Ok res) ->
|
||||||
|
if res.success then
|
||||||
|
resultModelCmd
|
||||||
|
( { model | addonRunSubmitted = True }
|
||||||
|
, Process.sleep 1200 |> Task.perform (\_ -> SetAddonRunSubmitted False)
|
||||||
|
)
|
||||||
|
|
||||||
|
else
|
||||||
|
resultModel model
|
||||||
|
|
||||||
|
RunAddonResp (Err _) ->
|
||||||
|
resultModel model
|
||||||
|
|
||||||
|
SetAddonRunSubmitted flag ->
|
||||||
|
resultModel { model | addonRunSubmitted = flag }
|
||||||
|
|
||||||
SetItem item ->
|
SetItem item ->
|
||||||
let
|
let
|
||||||
res1 =
|
res1 =
|
||||||
@ -1638,6 +1709,9 @@ update inav env msg model =
|
|||||||
, Sub.map ItemLinkFormMsg ils
|
, Sub.map ItemLinkFormMsg ils
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ToggleShowRunAddon ->
|
||||||
|
resultModel { model | showRunAddon = not model.showRunAddon, mobileItemMenuOpen = False }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Helper
|
--- Helper
|
||||||
|
@ -22,6 +22,7 @@ import Comp.ItemDetail.Model
|
|||||||
, isShowQrItem
|
, isShowQrItem
|
||||||
)
|
)
|
||||||
import Comp.ItemDetail.Notes
|
import Comp.ItemDetail.Notes
|
||||||
|
import Comp.ItemDetail.RunAddonForm
|
||||||
import Comp.ItemDetail.ShowQrCode
|
import Comp.ItemDetail.ShowQrCode
|
||||||
import Comp.ItemDetail.SingleAttachment
|
import Comp.ItemDetail.SingleAttachment
|
||||||
import Comp.ItemLinkForm
|
import Comp.ItemLinkForm
|
||||||
@ -177,6 +178,24 @@ menuBar texts inav env model =
|
|||||||
]
|
]
|
||||||
[ Icons.addFilesIcon2 ""
|
[ Icons.addFilesIcon2 ""
|
||||||
]
|
]
|
||||||
|
, MB.CustomElement <|
|
||||||
|
a
|
||||||
|
[ classList
|
||||||
|
[ ( "bg-gray-200 dark:bg-slate-600", model.showRunAddon )
|
||||||
|
, ( "hidden", not env.flags.config.addonsEnabled || List.isEmpty model.runConfigs )
|
||||||
|
, ( "hidden md:block", env.flags.config.addonsEnabled && not (List.isEmpty model.runConfigs) )
|
||||||
|
]
|
||||||
|
, if model.showRunAddon then
|
||||||
|
title texts.close
|
||||||
|
|
||||||
|
else
|
||||||
|
title texts.runAddonTitle
|
||||||
|
, onClick ToggleShowRunAddon
|
||||||
|
, class S.secondaryBasicButton
|
||||||
|
, href "#"
|
||||||
|
]
|
||||||
|
[ Icons.addonIcon ""
|
||||||
|
]
|
||||||
, MB.CustomElement <|
|
, MB.CustomElement <|
|
||||||
a
|
a
|
||||||
[ classList
|
[ classList
|
||||||
@ -248,6 +267,15 @@ menuBar texts inav env model =
|
|||||||
, onClick AddFilesToggle
|
, onClick AddFilesToggle
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
, { icon = Icons.addonIcon ""
|
||||||
|
, label = texts.runAddonLabel
|
||||||
|
, disabled = False
|
||||||
|
, attrs =
|
||||||
|
[ href "#"
|
||||||
|
, onClick ToggleShowRunAddon
|
||||||
|
, classList [ ( "hidden", not env.flags.config.addonsEnabled ) ]
|
||||||
|
]
|
||||||
|
}
|
||||||
, { icon = Icons.showQrIcon ""
|
, { icon = Icons.showQrIcon ""
|
||||||
, label = texts.showQrCode
|
, label = texts.showQrCode
|
||||||
, disabled = False
|
, disabled = False
|
||||||
@ -402,6 +430,11 @@ itemActions texts flags settings model classes =
|
|||||||
(S.border ++ " mb-4")
|
(S.border ++ " mb-4")
|
||||||
model
|
model
|
||||||
(Comp.ItemDetail.ShowQrCode.Item model.item.id)
|
(Comp.ItemDetail.ShowQrCode.Item model.item.id)
|
||||||
|
, if flags.config.addonsEnabled then
|
||||||
|
Comp.ItemDetail.RunAddonForm.view texts.runAddonForm settings model
|
||||||
|
|
||||||
|
else
|
||||||
|
span [ class "hidden" ] []
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
59
modules/webapp/src/main/elm/Data/AddonTrigger.elm
Normal file
59
modules/webapp/src/main/elm/Data/AddonTrigger.elm
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Data.AddonTrigger exposing (..)
|
||||||
|
|
||||||
|
-- A copy of docspell.addons.AddonTrigger.scala
|
||||||
|
|
||||||
|
|
||||||
|
type AddonTrigger
|
||||||
|
= FinalProcessItem
|
||||||
|
| FinalReprocessItem
|
||||||
|
| Scheduled
|
||||||
|
| ExistingItem
|
||||||
|
|
||||||
|
|
||||||
|
all : List AddonTrigger
|
||||||
|
all =
|
||||||
|
[ FinalProcessItem
|
||||||
|
, FinalReprocessItem
|
||||||
|
, Scheduled
|
||||||
|
, ExistingItem
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
asString : AddonTrigger -> String
|
||||||
|
asString t =
|
||||||
|
case t of
|
||||||
|
FinalProcessItem ->
|
||||||
|
"final-process-item"
|
||||||
|
|
||||||
|
FinalReprocessItem ->
|
||||||
|
"final-reprocess-item"
|
||||||
|
|
||||||
|
Scheduled ->
|
||||||
|
"scheduled"
|
||||||
|
|
||||||
|
ExistingItem ->
|
||||||
|
"existing-item"
|
||||||
|
|
||||||
|
|
||||||
|
fromString : String -> Maybe AddonTrigger
|
||||||
|
fromString s =
|
||||||
|
let
|
||||||
|
name =
|
||||||
|
String.toLower s
|
||||||
|
|
||||||
|
x =
|
||||||
|
List.filter (\e -> asString e == name) all
|
||||||
|
in
|
||||||
|
List.head x
|
||||||
|
|
||||||
|
|
||||||
|
fromList : List String -> List AddonTrigger
|
||||||
|
fromList list =
|
||||||
|
List.filterMap fromString list
|
@ -8,6 +8,7 @@
|
|||||||
module Data.CalEvent exposing
|
module Data.CalEvent exposing
|
||||||
( CalEvent
|
( CalEvent
|
||||||
, everyMonth
|
, everyMonth
|
||||||
|
, everyMonthTz
|
||||||
, fromEvent
|
, fromEvent
|
||||||
, makeEvent
|
, makeEvent
|
||||||
)
|
)
|
||||||
@ -29,7 +30,12 @@ type alias CalEvent =
|
|||||||
|
|
||||||
everyMonth : CalEvent
|
everyMonth : CalEvent
|
||||||
everyMonth =
|
everyMonth =
|
||||||
CalEvent Nothing "*" "*" "01" "00" "00" Data.TimeZone.utc
|
everyMonthTz Data.TimeZone.utc
|
||||||
|
|
||||||
|
|
||||||
|
everyMonthTz : TimeZone -> CalEvent
|
||||||
|
everyMonthTz tz =
|
||||||
|
CalEvent Nothing "*" "*" "01" "00" "00" tz
|
||||||
|
|
||||||
|
|
||||||
makeEvent : CalEvent -> String
|
makeEvent : CalEvent -> String
|
||||||
|
@ -38,6 +38,7 @@ type alias Config =
|
|||||||
, downloadAllMaxFiles : Int
|
, downloadAllMaxFiles : Int
|
||||||
, downloadAllMaxSize : Int
|
, downloadAllMaxSize : Int
|
||||||
, openIdAuth : List OpenIdAuth
|
, openIdAuth : List OpenIdAuth
|
||||||
|
, addonsEnabled : Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
module Data.Icons exposing
|
module Data.Icons exposing
|
||||||
( addFiles2
|
( addFiles2
|
||||||
, addFilesIcon2
|
, addFilesIcon2
|
||||||
|
, addonIcon
|
||||||
|
, addonRunConfigIcon
|
||||||
, concerned
|
, concerned
|
||||||
, concerned2
|
, concerned2
|
||||||
, concernedIcon
|
, concernedIcon
|
||||||
@ -76,7 +78,7 @@ module Data.Icons exposing
|
|||||||
)
|
)
|
||||||
|
|
||||||
import Data.CustomFieldType exposing (CustomFieldType)
|
import Data.CustomFieldType exposing (CustomFieldType)
|
||||||
import Html exposing (Html, i, img)
|
import Html exposing (Html, div, i, img, span)
|
||||||
import Html.Attributes exposing (class, src)
|
import Html.Attributes exposing (class, src)
|
||||||
import Svg
|
import Svg
|
||||||
import Svg.Attributes as SA
|
import Svg.Attributes as SA
|
||||||
@ -265,6 +267,24 @@ customFieldIcon2 classes =
|
|||||||
i [ class (customField2 ++ " " ++ classes) ] []
|
i [ class (customField2 ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
|
addon : String
|
||||||
|
addon =
|
||||||
|
"fa fa-puzzle-piece"
|
||||||
|
|
||||||
|
|
||||||
|
addonIcon : String -> Html msg
|
||||||
|
addonIcon classes =
|
||||||
|
i [ class (addon ++ " " ++ classes) ] []
|
||||||
|
|
||||||
|
|
||||||
|
addonRunConfigIcon : String -> Html msg
|
||||||
|
addonRunConfigIcon classes =
|
||||||
|
div [ class (classes ++ " inline-block relative margin-auto leading-8") ]
|
||||||
|
[ i [ class "fa fa-puzzle-piece" ] []
|
||||||
|
, i [ class "fa fa-play font-bold absolute text-xs -right-2 top-0" ] []
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
search : String
|
search : String
|
||||||
search =
|
search =
|
||||||
"fa fa-search"
|
"fa fa-search"
|
||||||
|
@ -5,15 +5,34 @@
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
||||||
module Data.ServerEvent exposing (ServerEvent(..), decode)
|
module Data.ServerEvent exposing (AddonInfo, ServerEvent(..), decode)
|
||||||
|
|
||||||
import Json.Decode as D
|
import Json.Decode as D
|
||||||
|
import Json.Decode.Pipeline as P
|
||||||
|
|
||||||
|
|
||||||
type ServerEvent
|
type ServerEvent
|
||||||
= JobSubmitted String
|
= JobSubmitted String
|
||||||
| JobDone String
|
| JobDone String
|
||||||
| JobsWaiting Int
|
| JobsWaiting Int
|
||||||
|
| AddonInstalled AddonInfo
|
||||||
|
|
||||||
|
|
||||||
|
type alias AddonInfo =
|
||||||
|
{ success : Bool
|
||||||
|
, addonId : Maybe String
|
||||||
|
, addonUrl : Maybe String
|
||||||
|
, message : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addonInfoDecoder : D.Decoder AddonInfo
|
||||||
|
addonInfoDecoder =
|
||||||
|
D.succeed AddonInfo
|
||||||
|
|> P.required "success" D.bool
|
||||||
|
|> P.optional "addonId" (D.maybe D.string) Nothing
|
||||||
|
|> P.optional "addonUrl" (D.maybe D.string) Nothing
|
||||||
|
|> P.required "message" D.string
|
||||||
|
|
||||||
|
|
||||||
decoder : D.Decoder ServerEvent
|
decoder : D.Decoder ServerEvent
|
||||||
@ -43,5 +62,9 @@ decodeTag tag =
|
|||||||
D.field "content" D.int
|
D.field "content" D.int
|
||||||
|> D.map JobsWaiting
|
|> D.map JobsWaiting
|
||||||
|
|
||||||
|
"addon-installed" ->
|
||||||
|
D.field "content" addonInfoDecoder
|
||||||
|
|> D.map AddonInstalled
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
D.fail ("Unknown tag: " ++ tag)
|
D.fail ("Unknown tag: " ++ tag)
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.AddonArchiveForm exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, fr
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, addonUrl : String
|
||||||
|
, addonUrlPlaceholder : String
|
||||||
|
, installInfoText : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, addonUrl = "Addon URL"
|
||||||
|
, addonUrlPlaceholder = "e.g. https://github.com/some-user/project/refs/tags/1.0.zip"
|
||||||
|
, installInfoText = "Only urls to remote addon zip files are supported."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, addonUrl = "Addon URL"
|
||||||
|
, addonUrlPlaceholder = "z.B. https://github.com/some-user/project/refs/tags/1.0.zip"
|
||||||
|
, installInfoText = "Nur URLs to externen zip Dateien werden unterstützt."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO: translate-fr
|
||||||
|
|
||||||
|
|
||||||
|
fr : Texts
|
||||||
|
fr =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, addonUrl = "Addon URL"
|
||||||
|
, addonUrlPlaceholder = "p.e. https://github.com/some-user/project/refs/tags/1.0.zip"
|
||||||
|
, installInfoText = "Only urls to remote addon zip files are supported."
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.AddonArchiveManage exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, fr
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Http
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.AddonArchiveForm
|
||||||
|
import Messages.Comp.AddonArchiveTable
|
||||||
|
import Messages.Comp.HttpError
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, addonArchiveTable : Messages.Comp.AddonArchiveTable.Texts
|
||||||
|
, addonArchiveForm : Messages.Comp.AddonArchiveForm.Texts
|
||||||
|
, httpError : Http.Error -> String
|
||||||
|
, newAddonArchive : String
|
||||||
|
, reallyDeleteAddonArchive : String
|
||||||
|
, createNewAddonArchive : String
|
||||||
|
, deleteThisAddonArchive : String
|
||||||
|
, correctFormErrors : String
|
||||||
|
, installNow : String
|
||||||
|
, updateNow : String
|
||||||
|
, description : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, addonArchiveTable = Messages.Comp.AddonArchiveTable.gb
|
||||||
|
, addonArchiveForm = Messages.Comp.AddonArchiveForm.gb
|
||||||
|
, httpError = Messages.Comp.HttpError.gb
|
||||||
|
, newAddonArchive = "New Addon"
|
||||||
|
, reallyDeleteAddonArchive = "Really delete this Addon?"
|
||||||
|
, createNewAddonArchive = "Install new Addon"
|
||||||
|
, deleteThisAddonArchive = "Delete this Addon"
|
||||||
|
, correctFormErrors = "Please correct the errors in the form."
|
||||||
|
, installNow = "Install Addon"
|
||||||
|
, updateNow = "Update Addon"
|
||||||
|
, description = "Description"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, addonArchiveTable = Messages.Comp.AddonArchiveTable.de
|
||||||
|
, addonArchiveForm = Messages.Comp.AddonArchiveForm.de
|
||||||
|
, httpError = Messages.Comp.HttpError.de
|
||||||
|
, newAddonArchive = "Neues Addon"
|
||||||
|
, reallyDeleteAddonArchive = "Dieses Addon wirklich entfernen?"
|
||||||
|
, createNewAddonArchive = "Neues Addon installieren"
|
||||||
|
, deleteThisAddonArchive = "Addon löschen"
|
||||||
|
, correctFormErrors = "Bitte korrigiere die Fehler im Formular."
|
||||||
|
, installNow = "Addon Installieren"
|
||||||
|
, updateNow = "Addon aktualisieren"
|
||||||
|
, description = "Beschreibung"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fr : Texts
|
||||||
|
fr =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, addonArchiveTable = Messages.Comp.AddonArchiveTable.fr
|
||||||
|
, addonArchiveForm = Messages.Comp.AddonArchiveForm.fr
|
||||||
|
, httpError = Messages.Comp.HttpError.fr
|
||||||
|
, newAddonArchive = "Nouveau favori"
|
||||||
|
, reallyDeleteAddonArchive = "Confirmer la suppression de ce favori ?"
|
||||||
|
, createNewAddonArchive = "Créer un nouveau favori"
|
||||||
|
, deleteThisAddonArchive = "Supprimer ce favori"
|
||||||
|
, correctFormErrors = "Veuillez corriger les erreurs du formulaire"
|
||||||
|
, installNow = "Installation de l'addon"
|
||||||
|
, updateNow = "Actualiser l'addon"
|
||||||
|
, description = "Description"
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.AddonArchiveTable exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, fr
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, version : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, version = "Version"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, version = "Version"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fr : Texts
|
||||||
|
fr =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, version = "Version"
|
||||||
|
}
|
108
modules/webapp/src/main/elm/Messages/Comp/AddonRunConfigForm.elm
Normal file
108
modules/webapp/src/main/elm/Messages/Comp/AddonRunConfigForm.elm
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.AddonRunConfigForm exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, fr
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Data.TimeZone exposing (TimeZone)
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.CalEventInput
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, calEventInput : Messages.Comp.CalEventInput.Texts
|
||||||
|
, enableDisable : String
|
||||||
|
, chooseName : String
|
||||||
|
, impersonateUser : String
|
||||||
|
, triggerRun : String
|
||||||
|
, schedule : String
|
||||||
|
, addons : String
|
||||||
|
, includedAddons : String
|
||||||
|
, add : String
|
||||||
|
, readMore : String
|
||||||
|
, readLess : String
|
||||||
|
, arguments : String
|
||||||
|
, update : String
|
||||||
|
, argumentsUpdated : String
|
||||||
|
, configureTitle : String
|
||||||
|
, configureLabel : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : TimeZone -> Texts
|
||||||
|
gb tz =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, calEventInput = Messages.Comp.CalEventInput.gb tz
|
||||||
|
, enableDisable = "Enable or disable this run configuration."
|
||||||
|
, chooseName = "Choose a name…"
|
||||||
|
, impersonateUser = "Run on behalf of user"
|
||||||
|
, triggerRun = "Trigger Run"
|
||||||
|
, schedule = "Schedule"
|
||||||
|
, addons = "Addons"
|
||||||
|
, includedAddons = "Included addons"
|
||||||
|
, add = "Add"
|
||||||
|
, readMore = "Read more"
|
||||||
|
, readLess = "Read less"
|
||||||
|
, arguments = "Arguments"
|
||||||
|
, update = "Update"
|
||||||
|
, argumentsUpdated = "Arguments updated"
|
||||||
|
, configureTitle = "Configure this addon"
|
||||||
|
, configureLabel = "Configure"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : TimeZone -> Texts
|
||||||
|
de tz =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, calEventInput = Messages.Comp.CalEventInput.de tz
|
||||||
|
, enableDisable = "Konfiguration aktivieren oder deaktivieren"
|
||||||
|
, chooseName = "Name der Konfiguration…"
|
||||||
|
, impersonateUser = "Als Benutzer ausführen"
|
||||||
|
, triggerRun = "Auslöser"
|
||||||
|
, schedule = "Zeitplan"
|
||||||
|
, addons = "Addons"
|
||||||
|
, includedAddons = "Gewählte Addons"
|
||||||
|
, add = "Hinzufügen"
|
||||||
|
, readMore = "Mehr"
|
||||||
|
, readLess = "Weniger"
|
||||||
|
, arguments = "Argumente"
|
||||||
|
, update = "Aktualisieren"
|
||||||
|
, argumentsUpdated = "Argumente aktualisiert"
|
||||||
|
, configureTitle = "Konfiguriere dieses Addon"
|
||||||
|
, configureLabel = "Konfigurieren"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO: translate-fr
|
||||||
|
|
||||||
|
|
||||||
|
fr : TimeZone -> Texts
|
||||||
|
fr tz =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, calEventInput = Messages.Comp.CalEventInput.fr tz
|
||||||
|
, enableDisable = "Activer ou désactiver cette tâche."
|
||||||
|
, chooseName = "Choose a name…"
|
||||||
|
, impersonateUser = "Impersonate user"
|
||||||
|
, triggerRun = "Trigger Run"
|
||||||
|
, schedule = "Programmation"
|
||||||
|
, addons = "Addons"
|
||||||
|
, includedAddons = "Included addons"
|
||||||
|
, add = "Ajouter"
|
||||||
|
, readMore = "Read more"
|
||||||
|
, readLess = "Read less"
|
||||||
|
, arguments = "Arguments"
|
||||||
|
, update = "Update"
|
||||||
|
, argumentsUpdated = "Arguments updated"
|
||||||
|
, configureTitle = "Configure this addon"
|
||||||
|
, configureLabel = "Configure"
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.AddonRunConfigManage exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, fr
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Data.TimeZone exposing (TimeZone)
|
||||||
|
import Http
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.AddonRunConfigForm
|
||||||
|
import Messages.Comp.AddonRunConfigTable
|
||||||
|
import Messages.Comp.HttpError
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, addonArchiveTable : Messages.Comp.AddonRunConfigTable.Texts
|
||||||
|
, addonArchiveForm : Messages.Comp.AddonRunConfigForm.Texts
|
||||||
|
, httpError : Http.Error -> String
|
||||||
|
, newAddonRunConfig : String
|
||||||
|
, reallyDeleteAddonRunConfig : String
|
||||||
|
, createNewAddonRunConfig : String
|
||||||
|
, deleteThisAddonRunConfig : String
|
||||||
|
, correctFormErrors : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : TimeZone -> Texts
|
||||||
|
gb tz =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, addonArchiveTable = Messages.Comp.AddonRunConfigTable.gb
|
||||||
|
, addonArchiveForm = Messages.Comp.AddonRunConfigForm.gb tz
|
||||||
|
, httpError = Messages.Comp.HttpError.gb
|
||||||
|
, newAddonRunConfig = "New"
|
||||||
|
, reallyDeleteAddonRunConfig = "Really delete this run config?"
|
||||||
|
, createNewAddonRunConfig = "Create a new run configuration"
|
||||||
|
, deleteThisAddonRunConfig = "Delete this run configuration"
|
||||||
|
, correctFormErrors = "Please correct the errors in the form."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : TimeZone -> Texts
|
||||||
|
de tz =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, addonArchiveTable = Messages.Comp.AddonRunConfigTable.de
|
||||||
|
, addonArchiveForm = Messages.Comp.AddonRunConfigForm.de tz
|
||||||
|
, httpError = Messages.Comp.HttpError.de
|
||||||
|
, newAddonRunConfig = "Neu"
|
||||||
|
, reallyDeleteAddonRunConfig = "Dieses Konfiguration wirklich entfernen?"
|
||||||
|
, createNewAddonRunConfig = "Neue Run-Konfiguration erstellen"
|
||||||
|
, deleteThisAddonRunConfig = "Run-Konfiguration löschen"
|
||||||
|
, correctFormErrors = "Bitte korrigiere die Fehler im Formular."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- TODO translate-fr
|
||||||
|
|
||||||
|
|
||||||
|
fr : TimeZone -> Texts
|
||||||
|
fr tz =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, addonArchiveTable = Messages.Comp.AddonRunConfigTable.fr
|
||||||
|
, addonArchiveForm = Messages.Comp.AddonRunConfigForm.fr tz
|
||||||
|
, httpError = Messages.Comp.HttpError.fr
|
||||||
|
, newAddonRunConfig = "Nouveau favori"
|
||||||
|
, reallyDeleteAddonRunConfig = "Confirmer la suppression de ce favori ?"
|
||||||
|
, createNewAddonRunConfig = "Créer un nouveau favori"
|
||||||
|
, deleteThisAddonRunConfig = "Supprimer ce favori"
|
||||||
|
, correctFormErrors = "Veuillez corriger les erreurs du formulaire"
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.AddonRunConfigTable exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, fr
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, enabled : String
|
||||||
|
, trigger : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, enabled = "Enabled"
|
||||||
|
, trigger = "Triggered"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, enabled = "Aktive"
|
||||||
|
, trigger = "Auslöser"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO translate-fr
|
||||||
|
|
||||||
|
|
||||||
|
fr : Texts
|
||||||
|
fr =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, enabled = "Enabled"
|
||||||
|
, trigger = "Triggered"
|
||||||
|
}
|
@ -20,6 +20,7 @@ import Messages.Comp.ItemDetail.AddFilesForm
|
|||||||
import Messages.Comp.ItemDetail.ConfirmModal
|
import Messages.Comp.ItemDetail.ConfirmModal
|
||||||
import Messages.Comp.ItemDetail.ItemInfoHeader
|
import Messages.Comp.ItemDetail.ItemInfoHeader
|
||||||
import Messages.Comp.ItemDetail.Notes
|
import Messages.Comp.ItemDetail.Notes
|
||||||
|
import Messages.Comp.ItemDetail.RunAddonForm
|
||||||
import Messages.Comp.ItemDetail.SingleAttachment
|
import Messages.Comp.ItemDetail.SingleAttachment
|
||||||
import Messages.Comp.ItemLinkForm
|
import Messages.Comp.ItemLinkForm
|
||||||
import Messages.Comp.ItemMail
|
import Messages.Comp.ItemMail
|
||||||
@ -38,6 +39,7 @@ type alias Texts =
|
|||||||
, detailEdit : Messages.Comp.DetailEdit.Texts
|
, detailEdit : Messages.Comp.DetailEdit.Texts
|
||||||
, confirmModal : Messages.Comp.ItemDetail.ConfirmModal.Texts
|
, confirmModal : Messages.Comp.ItemDetail.ConfirmModal.Texts
|
||||||
, itemLinkForm : Messages.Comp.ItemLinkForm.Texts
|
, itemLinkForm : Messages.Comp.ItemLinkForm.Texts
|
||||||
|
, runAddonForm : Messages.Comp.ItemDetail.RunAddonForm.Texts
|
||||||
, httpError : Http.Error -> String
|
, httpError : Http.Error -> String
|
||||||
, key : String
|
, key : String
|
||||||
, backToSearchResults : String
|
, backToSearchResults : String
|
||||||
@ -64,6 +66,8 @@ type alias Texts =
|
|||||||
, selectItem : String
|
, selectItem : String
|
||||||
, deselectItem : String
|
, deselectItem : String
|
||||||
, relatedItems : String
|
, relatedItems : String
|
||||||
|
, runAddonLabel : String
|
||||||
|
, runAddonTitle : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -78,6 +82,7 @@ gb tz =
|
|||||||
, detailEdit = Messages.Comp.DetailEdit.gb
|
, detailEdit = Messages.Comp.DetailEdit.gb
|
||||||
, confirmModal = Messages.Comp.ItemDetail.ConfirmModal.gb
|
, confirmModal = Messages.Comp.ItemDetail.ConfirmModal.gb
|
||||||
, itemLinkForm = Messages.Comp.ItemLinkForm.gb tz
|
, itemLinkForm = Messages.Comp.ItemLinkForm.gb tz
|
||||||
|
, runAddonForm = Messages.Comp.ItemDetail.RunAddonForm.gb
|
||||||
, httpError = Messages.Comp.HttpError.gb
|
, httpError = Messages.Comp.HttpError.gb
|
||||||
, key = "Key"
|
, key = "Key"
|
||||||
, backToSearchResults = "Back to search results"
|
, backToSearchResults = "Back to search results"
|
||||||
@ -104,6 +109,8 @@ gb tz =
|
|||||||
, selectItem = "Select this item"
|
, selectItem = "Select this item"
|
||||||
, deselectItem = "Deselect this item"
|
, deselectItem = "Deselect this item"
|
||||||
, relatedItems = "Linked items"
|
, relatedItems = "Linked items"
|
||||||
|
, runAddonLabel = "Run addon"
|
||||||
|
, runAddonTitle = "Run an addon on this item"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -118,6 +125,7 @@ de tz =
|
|||||||
, detailEdit = Messages.Comp.DetailEdit.de
|
, detailEdit = Messages.Comp.DetailEdit.de
|
||||||
, confirmModal = Messages.Comp.ItemDetail.ConfirmModal.de
|
, confirmModal = Messages.Comp.ItemDetail.ConfirmModal.de
|
||||||
, itemLinkForm = Messages.Comp.ItemLinkForm.de tz
|
, itemLinkForm = Messages.Comp.ItemLinkForm.de tz
|
||||||
|
, runAddonForm = Messages.Comp.ItemDetail.RunAddonForm.de
|
||||||
, httpError = Messages.Comp.HttpError.de
|
, httpError = Messages.Comp.HttpError.de
|
||||||
, key = "Taste"
|
, key = "Taste"
|
||||||
, backToSearchResults = "Zurück zur Suche"
|
, backToSearchResults = "Zurück zur Suche"
|
||||||
@ -144,6 +152,8 @@ de tz =
|
|||||||
, selectItem = "Zur Auswahl hinzufügen"
|
, selectItem = "Zur Auswahl hinzufügen"
|
||||||
, deselectItem = "Aus Auswahl entfernen"
|
, deselectItem = "Aus Auswahl entfernen"
|
||||||
, relatedItems = "Verknüpfte Dokumente"
|
, relatedItems = "Verknüpfte Dokumente"
|
||||||
|
, runAddonLabel = "Addon ausführen"
|
||||||
|
, runAddonTitle = "Addons für dieses Dokument ausführen"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -158,6 +168,7 @@ fr tz =
|
|||||||
, detailEdit = Messages.Comp.DetailEdit.fr
|
, detailEdit = Messages.Comp.DetailEdit.fr
|
||||||
, confirmModal = Messages.Comp.ItemDetail.ConfirmModal.fr
|
, confirmModal = Messages.Comp.ItemDetail.ConfirmModal.fr
|
||||||
, itemLinkForm = Messages.Comp.ItemLinkForm.fr tz
|
, itemLinkForm = Messages.Comp.ItemLinkForm.fr tz
|
||||||
|
, runAddonForm = Messages.Comp.ItemDetail.RunAddonForm.fr
|
||||||
, httpError = Messages.Comp.HttpError.fr
|
, httpError = Messages.Comp.HttpError.fr
|
||||||
, key = "Clé"
|
, key = "Clé"
|
||||||
, backToSearchResults = "Retour aux résultat de recherche"
|
, backToSearchResults = "Retour aux résultat de recherche"
|
||||||
@ -184,4 +195,10 @@ fr tz =
|
|||||||
, selectItem = "Sélectionner ce document"
|
, selectItem = "Sélectionner ce document"
|
||||||
, deselectItem = "Désélectionner ce document"
|
, deselectItem = "Désélectionner ce document"
|
||||||
, relatedItems = "Documents associés"
|
, relatedItems = "Documents associés"
|
||||||
|
, runAddonLabel = "Run addon"
|
||||||
|
, runAddonTitle = "Run an addon on this item"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO translate-fr
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Eike K. & Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.ItemDetail.RunAddonForm exposing (Texts, de, fr, gb)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, runAddon : String
|
||||||
|
, addonRunConfig : String
|
||||||
|
, runAddonTitle : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, runAddon = "Run an addon"
|
||||||
|
, addonRunConfig = "Addon run configuration"
|
||||||
|
, runAddonTitle = "Run the selected addon on this item."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, runAddon = "Addon ausführen"
|
||||||
|
, addonRunConfig = "Addon Konfiguration"
|
||||||
|
, runAddonTitle = "Run the selected addon on this item."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO: translate-fr
|
||||||
|
|
||||||
|
|
||||||
|
fr : Texts
|
||||||
|
fr =
|
||||||
|
{ basics = Messages.Basics.fr
|
||||||
|
, runAddon = "Run an addon"
|
||||||
|
, addonRunConfig = "Addon run configuration"
|
||||||
|
, runAddonTitle = "Run the selected addon on this item."
|
||||||
|
}
|
@ -14,6 +14,8 @@ module Messages.Page.ManageData exposing
|
|||||||
|
|
||||||
import Data.TimeZone exposing (TimeZone)
|
import Data.TimeZone exposing (TimeZone)
|
||||||
import Messages.Basics
|
import Messages.Basics
|
||||||
|
import Messages.Comp.AddonArchiveManage
|
||||||
|
import Messages.Comp.AddonRunConfigManage
|
||||||
import Messages.Comp.BookmarkManage
|
import Messages.Comp.BookmarkManage
|
||||||
import Messages.Comp.CustomFieldManage
|
import Messages.Comp.CustomFieldManage
|
||||||
import Messages.Comp.EquipmentManage
|
import Messages.Comp.EquipmentManage
|
||||||
@ -32,8 +34,12 @@ type alias Texts =
|
|||||||
, folderManage : Messages.Comp.FolderManage.Texts
|
, folderManage : Messages.Comp.FolderManage.Texts
|
||||||
, customFieldManage : Messages.Comp.CustomFieldManage.Texts
|
, customFieldManage : Messages.Comp.CustomFieldManage.Texts
|
||||||
, bookmarkManage : Messages.Comp.BookmarkManage.Texts
|
, bookmarkManage : Messages.Comp.BookmarkManage.Texts
|
||||||
|
, addonArchiveManage : Messages.Comp.AddonArchiveManage.Texts
|
||||||
|
, addonRunConfigManage : Messages.Comp.AddonRunConfigManage.Texts
|
||||||
, manageData : String
|
, manageData : String
|
||||||
, bookmarks : String
|
, bookmarks : String
|
||||||
|
, addonArchives : String
|
||||||
|
, addonRunConfigs : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -47,8 +53,12 @@ gb tz =
|
|||||||
, folderManage = Messages.Comp.FolderManage.gb tz
|
, folderManage = Messages.Comp.FolderManage.gb tz
|
||||||
, customFieldManage = Messages.Comp.CustomFieldManage.gb tz
|
, customFieldManage = Messages.Comp.CustomFieldManage.gb tz
|
||||||
, bookmarkManage = Messages.Comp.BookmarkManage.gb
|
, bookmarkManage = Messages.Comp.BookmarkManage.gb
|
||||||
|
, addonArchiveManage = Messages.Comp.AddonArchiveManage.gb
|
||||||
|
, addonRunConfigManage = Messages.Comp.AddonRunConfigManage.gb tz
|
||||||
, manageData = "Manage Data"
|
, manageData = "Manage Data"
|
||||||
, bookmarks = "Bookmarks"
|
, bookmarks = "Bookmarks"
|
||||||
|
, addonArchives = "Addons"
|
||||||
|
, addonRunConfigs = "Addon Run Configurations"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -62,8 +72,12 @@ de tz =
|
|||||||
, folderManage = Messages.Comp.FolderManage.de tz
|
, folderManage = Messages.Comp.FolderManage.de tz
|
||||||
, customFieldManage = Messages.Comp.CustomFieldManage.de tz
|
, customFieldManage = Messages.Comp.CustomFieldManage.de tz
|
||||||
, bookmarkManage = Messages.Comp.BookmarkManage.de
|
, bookmarkManage = Messages.Comp.BookmarkManage.de
|
||||||
|
, addonArchiveManage = Messages.Comp.AddonArchiveManage.de
|
||||||
|
, addonRunConfigManage = Messages.Comp.AddonRunConfigManage.de tz
|
||||||
, manageData = "Daten verwalten"
|
, manageData = "Daten verwalten"
|
||||||
, bookmarks = "Bookmarks"
|
, bookmarks = "Bookmarks"
|
||||||
|
, addonArchives = "Addons"
|
||||||
|
, addonRunConfigs = "Addon Run Configurations"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -77,6 +91,10 @@ fr tz =
|
|||||||
, folderManage = Messages.Comp.FolderManage.fr tz
|
, folderManage = Messages.Comp.FolderManage.fr tz
|
||||||
, customFieldManage = Messages.Comp.CustomFieldManage.fr tz
|
, customFieldManage = Messages.Comp.CustomFieldManage.fr tz
|
||||||
, bookmarkManage = Messages.Comp.BookmarkManage.fr
|
, bookmarkManage = Messages.Comp.BookmarkManage.fr
|
||||||
|
, addonArchiveManage = Messages.Comp.AddonArchiveManage.fr
|
||||||
|
, addonRunConfigManage = Messages.Comp.AddonRunConfigManage.fr tz
|
||||||
, manageData = "Gestion des métadonnées"
|
, manageData = "Gestion des métadonnées"
|
||||||
, bookmarks = "Favoris"
|
, bookmarks = "Favoris"
|
||||||
|
, addonArchives = "Addons"
|
||||||
|
, addonRunConfigs = "Addon Run Configurations"
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ module Page.ManageData.Data exposing
|
|||||||
, init
|
, init
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import Comp.AddonArchiveManage
|
||||||
|
import Comp.AddonRunConfigManage
|
||||||
import Comp.BookmarkManage
|
import Comp.BookmarkManage
|
||||||
import Comp.CustomFieldManage
|
import Comp.CustomFieldManage
|
||||||
import Comp.EquipmentManage
|
import Comp.EquipmentManage
|
||||||
@ -31,6 +33,8 @@ type alias Model =
|
|||||||
, folderManageModel : Comp.FolderManage.Model
|
, folderManageModel : Comp.FolderManage.Model
|
||||||
, fieldManageModel : Comp.CustomFieldManage.Model
|
, fieldManageModel : Comp.CustomFieldManage.Model
|
||||||
, bookmarkModel : Comp.BookmarkManage.Model
|
, bookmarkModel : Comp.BookmarkManage.Model
|
||||||
|
, addonArchiveModel : Comp.AddonArchiveManage.Model
|
||||||
|
, addonRunConfigModel : Comp.AddonRunConfigManage.Model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -42,6 +46,12 @@ init flags =
|
|||||||
|
|
||||||
( bm, bc ) =
|
( bm, bc ) =
|
||||||
Comp.BookmarkManage.init flags
|
Comp.BookmarkManage.init flags
|
||||||
|
|
||||||
|
( aam, aac ) =
|
||||||
|
Comp.AddonArchiveManage.init flags
|
||||||
|
|
||||||
|
( arm, arc ) =
|
||||||
|
Comp.AddonRunConfigManage.init flags
|
||||||
in
|
in
|
||||||
( { currentTab = Just TagTab
|
( { currentTab = Just TagTab
|
||||||
, tagManageModel = m2
|
, tagManageModel = m2
|
||||||
@ -51,10 +61,14 @@ init flags =
|
|||||||
, folderManageModel = Comp.FolderManage.empty
|
, folderManageModel = Comp.FolderManage.empty
|
||||||
, fieldManageModel = Comp.CustomFieldManage.empty
|
, fieldManageModel = Comp.CustomFieldManage.empty
|
||||||
, bookmarkModel = bm
|
, bookmarkModel = bm
|
||||||
|
, addonArchiveModel = aam
|
||||||
|
, addonRunConfigModel = arm
|
||||||
}
|
}
|
||||||
, Cmd.batch
|
, Cmd.batch
|
||||||
[ Cmd.map TagManageMsg c2
|
[ Cmd.map TagManageMsg c2
|
||||||
, Cmd.map BookmarkMsg bc
|
, Cmd.map BookmarkMsg bc
|
||||||
|
, Cmd.map AddonArchiveMsg aac
|
||||||
|
, Cmd.map AddonRunConfigMsg arc
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,6 +81,8 @@ type Tab
|
|||||||
| FolderTab
|
| FolderTab
|
||||||
| CustomFieldTab
|
| CustomFieldTab
|
||||||
| BookmarkTab
|
| BookmarkTab
|
||||||
|
| AddonArchiveTab
|
||||||
|
| AddonRunConfigTab
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
@ -78,3 +94,5 @@ type Msg
|
|||||||
| FolderMsg Comp.FolderManage.Msg
|
| FolderMsg Comp.FolderManage.Msg
|
||||||
| CustomFieldMsg Comp.CustomFieldManage.Msg
|
| CustomFieldMsg Comp.CustomFieldManage.Msg
|
||||||
| BookmarkMsg Comp.BookmarkManage.Msg
|
| BookmarkMsg Comp.BookmarkManage.Msg
|
||||||
|
| AddonArchiveMsg Comp.AddonArchiveManage.Msg
|
||||||
|
| AddonRunConfigMsg Comp.AddonRunConfigManage.Msg
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
module Page.ManageData.Update exposing (update)
|
module Page.ManageData.Update exposing (update)
|
||||||
|
|
||||||
|
import Comp.AddonArchiveManage
|
||||||
|
import Comp.AddonRunConfigManage
|
||||||
import Comp.BookmarkManage
|
import Comp.BookmarkManage
|
||||||
import Comp.CustomFieldManage
|
import Comp.CustomFieldManage
|
||||||
import Comp.EquipmentManage
|
import Comp.EquipmentManage
|
||||||
@ -15,11 +17,12 @@ import Comp.OrgManage
|
|||||||
import Comp.PersonManage
|
import Comp.PersonManage
|
||||||
import Comp.TagManage
|
import Comp.TagManage
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import Page.ManageData.Data exposing (..)
|
import Page.ManageData.Data exposing (..)
|
||||||
|
|
||||||
|
|
||||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
update : Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||||
update flags msg model =
|
update flags uiSettings msg model =
|
||||||
case msg of
|
case msg of
|
||||||
SetTab t ->
|
SetTab t ->
|
||||||
let
|
let
|
||||||
@ -28,16 +31,16 @@ update flags msg model =
|
|||||||
in
|
in
|
||||||
case t of
|
case t of
|
||||||
TagTab ->
|
TagTab ->
|
||||||
update flags (TagManageMsg Comp.TagManage.LoadTags) m
|
update flags uiSettings (TagManageMsg Comp.TagManage.LoadTags) m
|
||||||
|
|
||||||
EquipTab ->
|
EquipTab ->
|
||||||
update flags (EquipManageMsg Comp.EquipmentManage.LoadEquipments) m
|
update flags uiSettings (EquipManageMsg Comp.EquipmentManage.LoadEquipments) m
|
||||||
|
|
||||||
OrgTab ->
|
OrgTab ->
|
||||||
update flags (OrgManageMsg Comp.OrgManage.LoadOrgs) m
|
update flags uiSettings (OrgManageMsg Comp.OrgManage.LoadOrgs) m
|
||||||
|
|
||||||
PersonTab ->
|
PersonTab ->
|
||||||
update flags (PersonManageMsg Comp.PersonManage.LoadPersons) m
|
update flags uiSettings (PersonManageMsg Comp.PersonManage.LoadPersons) m
|
||||||
|
|
||||||
FolderTab ->
|
FolderTab ->
|
||||||
let
|
let
|
||||||
@ -60,6 +63,20 @@ update flags msg model =
|
|||||||
in
|
in
|
||||||
( { m | bookmarkModel = bm }, Cmd.map BookmarkMsg bc, Sub.none )
|
( { m | bookmarkModel = bm }, Cmd.map BookmarkMsg bc, Sub.none )
|
||||||
|
|
||||||
|
AddonArchiveTab ->
|
||||||
|
let
|
||||||
|
( aam, aac ) =
|
||||||
|
Comp.AddonArchiveManage.init flags
|
||||||
|
in
|
||||||
|
( { m | addonArchiveModel = aam }, Cmd.map AddonArchiveMsg aac, Sub.none )
|
||||||
|
|
||||||
|
AddonRunConfigTab ->
|
||||||
|
let
|
||||||
|
( arm, arc ) =
|
||||||
|
Comp.AddonRunConfigManage.init flags
|
||||||
|
in
|
||||||
|
( { m | addonRunConfigModel = arm }, Cmd.map AddonRunConfigMsg arc, Sub.none )
|
||||||
|
|
||||||
TagManageMsg m ->
|
TagManageMsg m ->
|
||||||
let
|
let
|
||||||
( m2, c2 ) =
|
( m2, c2 ) =
|
||||||
@ -117,3 +134,23 @@ update flags msg model =
|
|||||||
, Cmd.map BookmarkMsg c2
|
, Cmd.map BookmarkMsg c2
|
||||||
, Sub.map BookmarkMsg s2
|
, Sub.map BookmarkMsg s2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AddonArchiveMsg lm ->
|
||||||
|
let
|
||||||
|
( aam, aac, aas ) =
|
||||||
|
Comp.AddonArchiveManage.update flags lm model.addonArchiveModel
|
||||||
|
in
|
||||||
|
( { model | addonArchiveModel = aam }
|
||||||
|
, Cmd.map AddonArchiveMsg aac
|
||||||
|
, Sub.map AddonArchiveMsg aas
|
||||||
|
)
|
||||||
|
|
||||||
|
AddonRunConfigMsg lm ->
|
||||||
|
let
|
||||||
|
( arm, arc, ars ) =
|
||||||
|
Comp.AddonRunConfigManage.update flags uiSettings.timeZone lm model.addonRunConfigModel
|
||||||
|
in
|
||||||
|
( { model | addonRunConfigModel = arm }
|
||||||
|
, Cmd.map AddonRunConfigMsg arc
|
||||||
|
, Sub.map AddonRunConfigMsg ars
|
||||||
|
)
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
module Page.ManageData.View2 exposing (viewContent, viewSidebar)
|
module Page.ManageData.View2 exposing (viewContent, viewSidebar)
|
||||||
|
|
||||||
|
import Comp.AddonArchiveManage
|
||||||
|
import Comp.AddonRunConfigManage
|
||||||
import Comp.BookmarkManage
|
import Comp.BookmarkManage
|
||||||
import Comp.CustomFieldManage
|
import Comp.CustomFieldManage
|
||||||
import Comp.EquipmentManage
|
import Comp.EquipmentManage
|
||||||
@ -27,7 +29,7 @@ import Styles as S
|
|||||||
|
|
||||||
|
|
||||||
viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg
|
viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg
|
||||||
viewSidebar texts visible _ settings model =
|
viewSidebar texts visible flags settings model =
|
||||||
div
|
div
|
||||||
[ id "sidebar"
|
[ id "sidebar"
|
||||||
, class S.sidebar
|
, class S.sidebar
|
||||||
@ -134,6 +136,32 @@ viewSidebar texts visible _ settings model =
|
|||||||
[ text texts.bookmarks
|
[ text texts.bookmarks
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
, a
|
||||||
|
[ href "#"
|
||||||
|
, onClick (SetTab AddonArchiveTab)
|
||||||
|
, menuEntryActive model AddonArchiveTab
|
||||||
|
, class S.sidebarLink
|
||||||
|
, classList [ ( "hidden", not flags.config.addonsEnabled ) ]
|
||||||
|
]
|
||||||
|
[ Icons.addonIcon ""
|
||||||
|
, span
|
||||||
|
[ class "ml-3" ]
|
||||||
|
[ text texts.addonArchives
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, a
|
||||||
|
[ href "#"
|
||||||
|
, onClick (SetTab AddonRunConfigTab)
|
||||||
|
, menuEntryActive model AddonRunConfigTab
|
||||||
|
, class S.sidebarLink
|
||||||
|
, classList [ ( "hidden", not flags.config.addonsEnabled ) ]
|
||||||
|
]
|
||||||
|
[ Icons.addonRunConfigIcon ""
|
||||||
|
, span
|
||||||
|
[ class "ml-3" ]
|
||||||
|
[ text texts.addonRunConfigs
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -166,6 +194,20 @@ viewContent texts flags settings model =
|
|||||||
Just BookmarkTab ->
|
Just BookmarkTab ->
|
||||||
viewBookmarks texts flags settings model
|
viewBookmarks texts flags settings model
|
||||||
|
|
||||||
|
Just AddonArchiveTab ->
|
||||||
|
if flags.config.addonsEnabled then
|
||||||
|
viewAddonArchives texts flags settings model
|
||||||
|
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
|
||||||
|
Just AddonRunConfigTab ->
|
||||||
|
if flags.config.addonsEnabled then
|
||||||
|
viewAddonRunConfigs texts flags settings model
|
||||||
|
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
|
||||||
Nothing ->
|
Nothing ->
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
@ -306,3 +348,33 @@ viewBookmarks texts flags settings model =
|
|||||||
]
|
]
|
||||||
, Html.map BookmarkMsg (Comp.BookmarkManage.view texts.bookmarkManage settings flags model.bookmarkModel)
|
, Html.map BookmarkMsg (Comp.BookmarkManage.view texts.bookmarkManage settings flags model.bookmarkModel)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewAddonArchives : Texts -> Flags -> UiSettings -> Model -> List (Html Msg)
|
||||||
|
viewAddonArchives texts flags settings model =
|
||||||
|
[ h2
|
||||||
|
[ class S.header1
|
||||||
|
, class "inline-flex items-center"
|
||||||
|
]
|
||||||
|
[ Icons.addonIcon ""
|
||||||
|
, div [ class "ml-2" ]
|
||||||
|
[ text texts.addonArchives
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, Html.map AddonArchiveMsg (Comp.AddonArchiveManage.view texts.addonArchiveManage settings flags model.addonArchiveModel)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewAddonRunConfigs : Texts -> Flags -> UiSettings -> Model -> List (Html Msg)
|
||||||
|
viewAddonRunConfigs texts flags settings model =
|
||||||
|
[ h2
|
||||||
|
[ class S.header1
|
||||||
|
, class "inline-flex items-center"
|
||||||
|
]
|
||||||
|
[ Icons.addonRunConfigIcon "mr-4"
|
||||||
|
, div [ class "ml-2" ]
|
||||||
|
[ text texts.addonRunConfigs
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, Html.map AddonRunConfigMsg (Comp.AddonRunConfigManage.view texts.addonRunConfigManage settings flags model.addonRunConfigModel)
|
||||||
|
]
|
||||||
|
@ -35,6 +35,11 @@ sidebarLink =
|
|||||||
" mb-2 px-4 py-3 flex flex-row hover:bg-blue-100 dark:hover:bg-slate-600 hover:font-bold rounded rounded-lg items-center "
|
" mb-2 px-4 py-3 flex flex-row hover:bg-blue-100 dark:hover:bg-slate-600 hover:font-bold rounded rounded-lg items-center "
|
||||||
|
|
||||||
|
|
||||||
|
successText : String
|
||||||
|
successText =
|
||||||
|
" text-green-600 dark:text-lime-500 "
|
||||||
|
|
||||||
|
|
||||||
successMessage : String
|
successMessage : String
|
||||||
successMessage =
|
successMessage =
|
||||||
" border border-green-600 bg-green-50 text-green-600 dark:border-lime-800 dark:bg-lime-300 dark:text-lime-800 px-4 py-2 rounded "
|
" border border-green-600 bg-green-50 text-green-600 dark:border-lime-800 dark:bg-lime-300 dark:text-lime-800 px-4 py-2 rounded "
|
||||||
@ -281,7 +286,7 @@ link =
|
|||||||
|
|
||||||
inputErrorBorder : String
|
inputErrorBorder : String
|
||||||
inputErrorBorder =
|
inputErrorBorder =
|
||||||
" border-red-600 dark:border-orange-600 "
|
" ring dark:ring-0 ring-red-600 dark:border-orange-600 "
|
||||||
|
|
||||||
|
|
||||||
inputLabel : String
|
inputLabel : String
|
||||||
|
@ -14,12 +14,42 @@ module Util.List exposing
|
|||||||
, findNext
|
, findNext
|
||||||
, findPrev
|
, findPrev
|
||||||
, get
|
, get
|
||||||
|
, removeByIndex
|
||||||
|
, replaceByIndex
|
||||||
, sliding
|
, sliding
|
||||||
)
|
)
|
||||||
|
|
||||||
import Html.Attributes exposing (list)
|
import Html.Attributes exposing (list)
|
||||||
|
|
||||||
|
|
||||||
|
removeByIndex : Int -> List a -> List a
|
||||||
|
removeByIndex index list =
|
||||||
|
List.indexedMap
|
||||||
|
(\idx ->
|
||||||
|
\e ->
|
||||||
|
if idx == index then
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
else
|
||||||
|
Just e
|
||||||
|
)
|
||||||
|
list
|
||||||
|
|> List.filterMap identity
|
||||||
|
|
||||||
|
|
||||||
|
replaceByIndex : Int -> a -> List a -> List a
|
||||||
|
replaceByIndex index element list =
|
||||||
|
let
|
||||||
|
repl idx e =
|
||||||
|
if idx == index then
|
||||||
|
element
|
||||||
|
|
||||||
|
else
|
||||||
|
e
|
||||||
|
in
|
||||||
|
List.indexedMap repl list
|
||||||
|
|
||||||
|
|
||||||
changePosition : Int -> Int -> List a -> List a
|
changePosition : Int -> Int -> List a -> List a
|
||||||
changePosition source target list =
|
changePosition source target list =
|
||||||
let
|
let
|
||||||
|
@ -9,6 +9,7 @@ module Util.String exposing
|
|||||||
( appendIfAbsent
|
( appendIfAbsent
|
||||||
, crazyEncode
|
, crazyEncode
|
||||||
, ellipsis
|
, ellipsis
|
||||||
|
, firstSentenceOrMax
|
||||||
, isBlank
|
, isBlank
|
||||||
, isNothingOrBlank
|
, isNothingOrBlank
|
||||||
, underscoreToSpace
|
, underscoreToSpace
|
||||||
@ -16,7 +17,6 @@ module Util.String exposing
|
|||||||
)
|
)
|
||||||
|
|
||||||
import Base64
|
import Base64
|
||||||
import Html exposing (strong)
|
|
||||||
|
|
||||||
|
|
||||||
crazyEncode : String -> String
|
crazyEncode : String -> String
|
||||||
@ -45,6 +45,26 @@ ellipsis len str =
|
|||||||
String.left (len - 1) str ++ "…"
|
String.left (len - 1) str ++ "…"
|
||||||
|
|
||||||
|
|
||||||
|
firstSentenceOrMax : Int -> String -> Maybe String
|
||||||
|
firstSentenceOrMax maxLen str =
|
||||||
|
let
|
||||||
|
idx =
|
||||||
|
String.indexes "." str
|
||||||
|
|> List.head
|
||||||
|
|> Maybe.map ((+) 2)
|
||||||
|
|> Maybe.map (min maxLen)
|
||||||
|
|> Maybe.withDefault maxLen
|
||||||
|
|
||||||
|
len =
|
||||||
|
String.length str
|
||||||
|
in
|
||||||
|
if len <= maxLen then
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
else
|
||||||
|
Just <| String.left (idx - 1) str ++ "…"
|
||||||
|
|
||||||
|
|
||||||
withDefault : String -> String -> String
|
withDefault : String -> String -> String
|
||||||
withDefault default str =
|
withDefault default str =
|
||||||
if str == "" then
|
if str == "" then
|
||||||
|
@ -96,4 +96,8 @@
|
|||||||
.markdown-preview a {
|
.markdown-preview a {
|
||||||
@apply text-blue-400 hover:text-blue-500 dark:text-sky-200 dark:hover:text-sky-100 cursor-pointer;
|
@apply text-blue-400 hover:text-blue-500 dark:text-sky-200 dark:hover:text-sky-100 cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.markdown-preview pre {
|
||||||
|
@apply font-mono px-2 py-2 text-sm border dark:border-slate-600 rounded my-2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user