Outline share detail page

This commit is contained in:
eikek
2021-10-06 11:04:18 +02:00
parent 1a10216e3d
commit b6187bb88d
21 changed files with 622 additions and 157 deletions

View File

@@ -468,23 +468,22 @@ itemCardList texts _ settings model =
previewUrlFallback item =
Api.itemBasePreviewURL item.id
viewCfg sel =
Comp.ItemCardList.ViewConfig
model.scrollToCard
sel
previewUrl
previewUrlFallback
(.id >> Api.fileURL)
(.id >> ItemDetailPage)
itemViewCfg =
case model.viewMode of
SelectView svm ->
Comp.ItemCardList.ViewConfig
model.scrollToCard
(Data.ItemSelection.Active svm.ids)
previewUrl
previewUrlFallback
(.id >> Api.fileURL)
viewCfg (Data.ItemSelection.Active svm.ids)
_ ->
Comp.ItemCardList.ViewConfig
model.scrollToCard
Data.ItemSelection.Inactive
previewUrl
previewUrlFallback
(.id >> Api.fileURL)
viewCfg Data.ItemSelection.Inactive
in
[ Html.map ItemCardListMsg
(Comp.ItemCardList.view2 texts.itemCardList

View File

@@ -15,6 +15,7 @@ import Api.Model.ShareVerifyResult exposing (ShareVerifyResult)
import Comp.ItemCardList
import Comp.PowerSearchInput
import Comp.SearchMenu
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Http
@@ -31,16 +32,10 @@ type PageError
| PageErrorAuthFail
type alias PasswordModel =
{ password : String
, passwordFailed : Bool
}
type alias Model =
{ mode : Mode
, verifyResult : ShareVerifyResult
, passwordModel : PasswordModel
, passwordModel : Comp.SharePasswordForm.Model
, pageError : PageError
, searchMenuModel : Comp.SearchMenu.Model
, powerSearchInput : Comp.PowerSearchInput.Model
@@ -53,10 +48,7 @@ emptyModel : Flags -> Model
emptyModel flags =
{ mode = ModeInitial
, verifyResult = Api.Model.ShareVerifyResult.empty
, passwordModel =
{ password = ""
, passwordFailed = False
}
, passwordModel = Comp.SharePasswordForm.init
, pageError = PageErrorNone
, searchMenuModel = Comp.SearchMenu.init flags
, powerSearchInput = Comp.PowerSearchInput.init
@@ -79,8 +71,7 @@ type Msg
= VerifyResp (Result Http.Error ShareVerifyResult)
| SearchResp (Result Http.Error ItemLightList)
| StatsResp (Result Http.Error SearchStats)
| SetPassword String
| SubmitPassword
| PasswordMsg Comp.SharePasswordForm.Msg
| SearchMenuMsg Comp.SearchMenu.Msg
| PowerSearchMsg Comp.PowerSearchInput.Msg
| ResetSearch

View File

@@ -14,11 +14,12 @@ import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Messages.Page.Share exposing (Texts)
import Page exposing (Page(..))
import Page.Share.Data exposing (Model, Msg(..))
view : Texts -> UiSettings -> Model -> Html Msg
view texts settings model =
view : Texts -> UiSettings -> String -> Model -> Html Msg
view texts settings shareId model =
let
viewCfg =
{ current = Nothing
@@ -26,6 +27,7 @@ view texts settings model =
, previewUrl = \attach -> Api.shareAttachmentPreviewURL attach.id
, previewUrlFallback = \item -> Api.shareItemBasePreviewURL item.id
, attachUrl = .id >> Api.shareFileURL
, detailPage = \item -> ShareDetailPage shareId item.id
}
in
div []

View File

@@ -13,6 +13,7 @@ import Comp.ItemCardList
import Comp.LinkTarget exposing (LinkTarget)
import Comp.PowerSearchInput
import Comp.SearchMenu
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Data.ItemQuery as Q
import Data.SearchMode
@@ -51,26 +52,13 @@ update flags settings shareId msg model =
)
else if res.passwordRequired then
if model.mode == ModePassword then
noSub
( { model
| pageError = PageErrorNone
, passwordModel =
{ password = ""
, passwordFailed = True
}
}
, Cmd.none
)
else
noSub
( { model
| pageError = PageErrorNone
, mode = ModePassword
}
, Cmd.none
)
noSub
( { model
| pageError = PageErrorNone
, mode = ModePassword
}
, Cmd.none
)
else
noSub
@@ -101,21 +89,21 @@ update flags settings shareId msg model =
StatsResp (Err err) ->
noSub ( { model | pageError = PageErrorHttp err }, Cmd.none )
SetPassword pw ->
PasswordMsg lmsg ->
let
pm =
model.passwordModel
( m, c, res ) =
Comp.SharePasswordForm.update shareId flags lmsg model.passwordModel
in
noSub ( { model | passwordModel = { pm | password = pw } }, Cmd.none )
case res of
Just verifyResult ->
update flags
settings
shareId
(VerifyResp (Ok verifyResult))
model
SubmitPassword ->
let
secret =
{ shareId = shareId
, password = Just model.passwordModel.password
}
in
noSub ( model, Api.verifyShare flags secret VerifyResp )
Nothing ->
noSub ( { model | passwordModel = m }, Cmd.map PasswordMsg c )
SearchMenuMsg lm ->
let

View File

@@ -9,6 +9,7 @@ module Page.Share.View exposing (viewContent, viewSidebar)
import Api.Model.VersionInfo exposing (VersionInfo)
import Comp.Basic as B
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Data.Items
import Data.UiSettings exposing (UiSettings)
@@ -35,8 +36,8 @@ viewSidebar texts visible flags settings model =
]
viewContent : Texts -> Flags -> VersionInfo -> UiSettings -> Model -> Html Msg
viewContent texts flags versionInfo uiSettings model =
viewContent : Texts -> Flags -> VersionInfo -> UiSettings -> String -> Model -> Html Msg
viewContent texts flags versionInfo uiSettings shareId model =
case model.mode of
ModeInitial ->
div
@@ -54,15 +55,15 @@ viewContent texts flags versionInfo uiSettings model =
passwordContent texts flags versionInfo model
ModeShare ->
mainContent texts flags uiSettings model
mainContent texts flags uiSettings shareId model
--- Helpers
mainContent : Texts -> Flags -> UiSettings -> Model -> Html Msg
mainContent texts _ settings model =
mainContent : Texts -> Flags -> UiSettings -> String -> Model -> Html Msg
mainContent texts _ settings shareId model =
div
[ id "content"
, class "h-full flex flex-col"
@@ -75,7 +76,7 @@ mainContent texts _ settings model =
[ text <| Maybe.withDefault "" model.verifyResult.name
]
, Menubar.view texts model
, Results.view texts settings model
, Results.view texts settings shareId model
]
@@ -86,76 +87,6 @@ passwordContent texts flags versionInfo model =
, class "h-full flex flex-col items-center justify-center w-full"
, class S.content
]
[ div [ class ("flex flex-col px-4 sm:px-6 md:px-8 lg:px-10 py-8 rounded-md " ++ S.box) ]
[ div [ class "self-center" ]
[ img
[ class "w-16 py-2"
, src (flags.config.docspellAssetPath ++ "/img/logo-96.png")
]
[]
]
, div [ class "font-medium self-center text-xl sm:text-2xl" ]
[ text texts.passwordRequired
]
, Html.form
[ action "#"
, onSubmit SubmitPassword
, autocomplete False
]
[ div [ class "flex flex-col my-3" ]
[ label
[ for "password"
, class S.inputLabel
]
[ text texts.password
]
, div [ class "relative" ]
[ div [ class S.inputIcon ]
[ i [ class "fa fa-lock" ] []
]
, input
[ type_ "password"
, name "password"
, autocomplete False
, autofocus True
, tabindex 1
, onInput SetPassword
, value model.passwordModel.password
, class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput)
, placeholder texts.password
]
[]
]
]
, div [ class "flex flex-col my-3" ]
[ button
[ type_ "submit"
, class S.primaryButton
]
[ text texts.passwordSubmitButton
]
]
, div
[ class S.errorMessage
, classList [ ( "hidden", not model.passwordModel.passwordFailed ) ]
]
[ text texts.passwordFailed
]
]
]
, a
[ class "inline-flex items-center mt-4 text-xs opacity-50 hover:opacity-90"
, href "https://docspell.org"
, target "_new"
]
[ img
[ src (flags.config.docspellAssetPath ++ "/img/logo-mc-96.png")
, class "w-3 h-3 mr-1"
]
[]
, span []
[ text "Docspell "
, text versionInfo.version
]
]
[ Html.map PasswordMsg
(Comp.SharePasswordForm.view texts.passwordForm flags versionInfo model.passwordModel)
]

View File

@@ -0,0 +1,56 @@
module Page.ShareDetail.Data exposing (Model, Msg(..), PageError(..), ViewMode(..), init)
import Api
import Api.Model.ItemDetail exposing (ItemDetail)
import Api.Model.ShareSecret exposing (ShareSecret)
import Api.Model.ShareVerifyResult exposing (ShareVerifyResult)
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Http
type ViewMode
= ViewNormal
| ViewPassword
| ViewLoading
type PageError
= PageErrorNone
| PageErrorHttp Http.Error
| PageErrorAuthFail
type alias Model =
{ item : ItemDetail
, verifyResult : ShareVerifyResult
, passwordModel : Comp.SharePasswordForm.Model
, viewMode : ViewMode
, pageError : PageError
}
type Msg
= VerifyResp (Result Http.Error ShareVerifyResult)
| GetItemResp (Result Http.Error ItemDetail)
| PasswordMsg Comp.SharePasswordForm.Msg
emptyModel : ViewMode -> Model
emptyModel vm =
{ item = Api.Model.ItemDetail.empty
, verifyResult = Api.Model.ShareVerifyResult.empty
, passwordModel = Comp.SharePasswordForm.init
, viewMode = vm
, pageError = PageErrorNone
}
init : Maybe ( String, String ) -> Flags -> ( Model, Cmd Msg )
init mids flags =
case mids of
Just ( shareId, _ ) ->
( emptyModel ViewLoading, Api.verifyShare flags (ShareSecret shareId Nothing) VerifyResp )
Nothing ->
( emptyModel ViewLoading, Cmd.none )

View File

@@ -0,0 +1,64 @@
module Page.ShareDetail.Update exposing (update)
import Api
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Page.ShareDetail.Data exposing (..)
update : String -> String -> Flags -> Msg -> Model -> ( Model, Cmd Msg )
update shareId itemId flags msg model =
case msg of
VerifyResp (Ok res) ->
if res.success then
( { model
| pageError = PageErrorNone
, viewMode = ViewLoading
, verifyResult = res
}
, Api.itemDetailShare flags res.token itemId GetItemResp
)
else if res.passwordRequired then
( { model
| pageError = PageErrorNone
, viewMode = ViewPassword
}
, Cmd.none
)
else
( { model | pageError = PageErrorAuthFail }
, Cmd.none
)
VerifyResp (Err err) ->
( { model | pageError = PageErrorHttp err }, Cmd.none )
GetItemResp (Ok item) ->
( { model
| item = item
, viewMode = ViewNormal
, pageError = PageErrorNone
}
, Cmd.none
)
GetItemResp (Err err) ->
( { model | viewMode = ViewNormal, pageError = PageErrorHttp err }, Cmd.none )
PasswordMsg lmsg ->
let
( m, c, res ) =
Comp.SharePasswordForm.update shareId flags lmsg model.passwordModel
in
case res of
Just verifyResult ->
update shareId
itemId
flags
(VerifyResp (Ok verifyResult))
model
Nothing ->
( { model | passwordModel = m }, Cmd.map PasswordMsg c )

View File

@@ -0,0 +1,108 @@
module Page.ShareDetail.View exposing (viewContent, viewSidebar)
import Api.Model.VersionInfo exposing (VersionInfo)
import Comp.Basic as B
import Comp.SharePasswordForm
import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Messages.Page.ShareDetail exposing (Texts)
import Page exposing (Page(..))
import Page.ShareDetail.Data exposing (..)
import Styles as S
viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg
viewSidebar texts visible flags settings model =
div
[ id "sidebar"
, class "hidden"
]
[]
viewContent : Texts -> Flags -> UiSettings -> VersionInfo -> String -> String -> Model -> Html Msg
viewContent texts flags uiSettings versionInfo shareId itemId model =
case model.viewMode of
ViewLoading ->
div
[ id "content"
, class "h-full w-full flex flex-col text-5xl"
, class S.content
]
[ B.loadingDimmer
{ active = model.pageError == PageErrorNone
, label = ""
}
]
ViewPassword ->
passwordContent texts flags versionInfo model
ViewNormal ->
mainContent texts flags uiSettings shareId model
--- Helper
mainContent : Texts -> Flags -> UiSettings -> String -> Model -> Html Msg
mainContent texts flags settings shareId model =
div
[ class "flex flex-col"
, class S.content
]
[ itemHead texts shareId model
, div [ class "flex flex-col sm:flex-row" ]
[ itemData texts model
, itemPreview texts flags settings model
]
]
itemData : Texts -> Model -> Html Msg
itemData texts model =
div [ class "flex" ]
[]
{-| Using ItemDetail Model to be able to reuse SingleAttachment component
-}
itemPreview : Texts -> Flags -> UiSettings -> Model -> Html Msg
itemPreview texts flags settings model =
div [ class "flex flex-grow" ]
[]
itemHead : Texts -> String -> Model -> Html Msg
itemHead texts shareId model =
div [ class "flex flex-col sm:flex-row" ]
[ div [ class "flex flex-grow items-center" ]
[ h1 [ class S.header1 ]
[ text model.item.name
]
]
, div [ class "flex flex-row items-center justify-end" ]
[ B.secondaryBasicButton
{ label = "Close"
, icon = "fa fa-times"
, disabled = False
, handler = Page.href (SharePage shareId)
, attrs = []
}
]
]
passwordContent : Texts -> Flags -> VersionInfo -> Model -> Html Msg
passwordContent texts flags versionInfo model =
div
[ id "content"
, class "h-full flex flex-col items-center justify-center w-full"
, class S.content
]
[ Html.map PasswordMsg
(Comp.SharePasswordForm.view texts.passwordForm flags versionInfo model.passwordModel)
]