mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-21 18:08:25 +00:00
Website redesign
This commit is contained in:
@ -14,25 +14,21 @@ type alias Demo =
|
||||
|
||||
demo : Demo -> Html msg
|
||||
demo data =
|
||||
div [ class "columns is-vcentered box mb-5" ]
|
||||
[ div [ class "column" ]
|
||||
[ h2 [ class "title" ]
|
||||
[ text data.title
|
||||
]
|
||||
, if data.info == "" then
|
||||
span [] []
|
||||
div [ class "px-4 py-4 mx-2 sm:mx-8 rounded border shadow-lg flex flex-col" ]
|
||||
[ h2 [ class "text-3xl font-bold py-2 font-serif" ]
|
||||
[ text data.title
|
||||
]
|
||||
, if data.info == "" then
|
||||
span [] []
|
||||
|
||||
else
|
||||
p []
|
||||
[ Markdown.toHtml [] data.info
|
||||
]
|
||||
, div [ class "mt-5 columns is-centered" ]
|
||||
[ video
|
||||
[ src data.url
|
||||
, controls True
|
||||
]
|
||||
[]
|
||||
else
|
||||
Markdown.toHtml [ class "text-lg" ] data.info
|
||||
, div [ class "mt-6 self-center" ]
|
||||
[ video
|
||||
[ src data.url
|
||||
, controls True
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -14,38 +14,66 @@ type alias Feature =
|
||||
|
||||
featureBox : Int -> Feature -> Html msg
|
||||
featureBox index f =
|
||||
case isOdd index of
|
||||
False ->
|
||||
div [ class "columns is-vcentered box mb-5" ]
|
||||
[ div [ class "column is-three-quarter" ]
|
||||
[ figure [ class "image is-2by1 feature-image" ]
|
||||
[ img [ src f.image ] []
|
||||
]
|
||||
]
|
||||
, div [ class "column" ]
|
||||
[ h2 [ class "title" ]
|
||||
[ text f.header
|
||||
]
|
||||
, Markdown.toHtml []
|
||||
f.description
|
||||
]
|
||||
]
|
||||
let
|
||||
titleCss =
|
||||
"text-3xl font-bold font-serif mb-3"
|
||||
|
||||
True ->
|
||||
div [ class "columns is-vcentered box mb-5" ]
|
||||
[ div [ class "column is-three-quarter" ]
|
||||
[ h2 [ class "title" ]
|
||||
[ text f.header
|
||||
]
|
||||
, Markdown.toHtml []
|
||||
f.description
|
||||
]
|
||||
, div [ class "column" ]
|
||||
[ figure [ class "image is-2by1 feature-image" ]
|
||||
[ img [ src f.image ] []
|
||||
boxCss =
|
||||
[ class "flex-col space-y-2"
|
||||
, class "sm:flex-row sm:space-y-0 sm-space-x-4"
|
||||
, class "flex px-8 py-8 border rounded mb-5 shadow-lg mx-2 sm:mx-8"
|
||||
]
|
||||
|
||||
descrCss =
|
||||
"flex flex-col text-xl "
|
||||
in
|
||||
if isOdd index then
|
||||
div boxCss
|
||||
[ div [ class "sm:w-1/2" ]
|
||||
[ figure [ class "block my-auto" ]
|
||||
[ img
|
||||
[ src f.image
|
||||
, class "w-full"
|
||||
, style "min-width" "4rem"
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
, div
|
||||
[ class descrCss
|
||||
, class "pl-4 sm:w-1/2"
|
||||
]
|
||||
[ h2 [ class titleCss ]
|
||||
[ text f.header
|
||||
]
|
||||
, Markdown.toHtml []
|
||||
f.description
|
||||
]
|
||||
]
|
||||
|
||||
else
|
||||
div
|
||||
boxCss
|
||||
[ div
|
||||
[ class descrCss
|
||||
, class "pr-4 sm:w-1/2"
|
||||
]
|
||||
[ h2 [ class titleCss ]
|
||||
[ text f.header
|
||||
]
|
||||
, Markdown.toHtml []
|
||||
f.description
|
||||
]
|
||||
, div [ class "sm:w-1/2" ]
|
||||
[ figure [ class "block my-auto " ]
|
||||
[ img
|
||||
[ src f.image
|
||||
, class "w-full"
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
features : List Feature
|
||||
@ -105,7 +133,7 @@ Users can define IMAP settings so that docspell can import their e-mails. This c
|
||||
, { image = "img/notify-feature.png"
|
||||
, header = "Notifications"
|
||||
, description = """
|
||||
Users can be notified by e-mail for documents whose due-date comes closer.
|
||||
Users can be notified by e-mail, Matrix or Gotify with documents resulting from a query that is executed periodically. Notifications can also be configured for specific events.
|
||||
"""
|
||||
}
|
||||
]
|
||||
|
@ -2,35 +2,32 @@ module GetStarted exposing (..)
|
||||
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Icons
|
||||
import Markdown
|
||||
|
||||
|
||||
getStarted : String -> List (Html msg)
|
||||
getStarted version =
|
||||
[ div [ class "content container" ]
|
||||
[ Markdown.toHtml []
|
||||
getStarted : String -> Html msg
|
||||
getStarted _ =
|
||||
div [ class "container max-w-screen-lg mx-auto text-xl px-10 lg:px-0 leading-relaxed min-h-screen" ]
|
||||
[ Markdown.toHtml [ class "my-4 markdown-view" ]
|
||||
"""Docspell consists of several components. The easiest way to get started is probably to use docker and
|
||||
[docker-compose](https://docs.docker.com/compose/)."""
|
||||
, Markdown.toHtml []
|
||||
, Markdown.toHtml [ class "my-4 markdown-view " ]
|
||||
"""1. Clone the github repository
|
||||
```bash
|
||||
$ git clone https://github.com/eikek/docspell
|
||||
```
|
||||
Alternatively, [download](https://github.com/eikek/docspell/archive/master.zip) the sources and extract the zip file.
|
||||
2. Change into the `docker` directory:
|
||||
2. Change into the `docker-compose` directory:
|
||||
```bash
|
||||
$ cd docspell/docker/docker-compose
|
||||
```
|
||||
3. Run `docker-compose up`:
|
||||
|
||||
```bash
|
||||
$ docker-compose up -d
|
||||
```
|
||||
4. Goto <http://localhost:7880>, signup and login. When signing up,
|
||||
choose the same name for collective and user. Then login
|
||||
with this name and the password.
|
||||
|
||||
5. (Optional) Create a folder `./docs/<collective-name>` (the name you
|
||||
chose for the collective at registration) and place files in there
|
||||
for importing them.
|
||||
@ -38,58 +35,51 @@ getStarted version =
|
||||
The `docker-compose.yml` file defines some environment variables to
|
||||
configure docspell. You can [modify](docs/configure) them as needed.
|
||||
"""
|
||||
]
|
||||
, div [ class "content container" ]
|
||||
[ div [ class "notification is-info is-light" ]
|
||||
, div [ class "blue-message" ]
|
||||
[ text "If you don't use docker, there are other ways that are "
|
||||
, text "described in the relevant "
|
||||
, a [ href "/docs/install" ]
|
||||
, a [ href "/docs/install", class "link" ]
|
||||
[ text "documentation page"
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "content container" ]
|
||||
[ div [ class "notification is-success is-light" ]
|
||||
[ div [ class "content is-medium" ]
|
||||
[ h3 [ class "title" ]
|
||||
[ text "Where to go from here?"
|
||||
, div [ class "green-message mt-4 " ]
|
||||
[ h3 [ class "text-4xl font-bold font-serif py-2 mb-2" ]
|
||||
[ text "Where to go from here?"
|
||||
]
|
||||
, ul [ class "list-disc list-inside " ]
|
||||
[ li []
|
||||
[ text "Find out "
|
||||
, a [ href "/docs/feed" ]
|
||||
[ text "how files can get into Docspell."
|
||||
]
|
||||
]
|
||||
, ul []
|
||||
[ li []
|
||||
[ text "Find out "
|
||||
, a [ href "/docs/feed" ]
|
||||
[ text "how files can get into Docspell."
|
||||
]
|
||||
, li []
|
||||
[ text "The "
|
||||
, a [ href "/docs/intro" ]
|
||||
[ text "introduction" ]
|
||||
, text " writes about the goals and basic idea."
|
||||
]
|
||||
, li []
|
||||
[ text "There is a comprehensive "
|
||||
, a [ href "/docs" ]
|
||||
[ text "documentation"
|
||||
]
|
||||
, li []
|
||||
[ text "The "
|
||||
, a [ href "/docs/intro" ]
|
||||
[ text "introduction" ]
|
||||
, text " writes about the goals and basic idea."
|
||||
, text " available."
|
||||
]
|
||||
, li []
|
||||
[ text "The source code is hosted on "
|
||||
, a [ href "https://github.com/eikek/docspell" ]
|
||||
[ text "github"
|
||||
]
|
||||
, li []
|
||||
[ text "There is a comprehensive "
|
||||
, a [ href "/docs" ]
|
||||
[ text "documentation"
|
||||
]
|
||||
, text " available."
|
||||
]
|
||||
, li []
|
||||
[ text "The source code is hosted on "
|
||||
, a [ href "https://github.com/eikek/docspell" ]
|
||||
[ text "github"
|
||||
]
|
||||
, text "."
|
||||
]
|
||||
, li []
|
||||
[ text "Chat on "
|
||||
, a [ href "https://gitter.im/eikek/docspell" ]
|
||||
[ text "Gitter"
|
||||
]
|
||||
, text " for questions and feedback."
|
||||
, text "."
|
||||
]
|
||||
, li []
|
||||
[ text "Chat on "
|
||||
, a [ href "https://gitter.im/eikek/docspell" ]
|
||||
[ text "Gitter"
|
||||
]
|
||||
, text " for questions and feedback."
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@ -6,7 +6,7 @@ import Html.Attributes exposing (..)
|
||||
|
||||
copyright : Html msg
|
||||
copyright =
|
||||
img [ src "icons/copyright-40.svg" ] []
|
||||
i [ class "fa fa-copyright font-thin" ] []
|
||||
|
||||
|
||||
infoSquared : Html msg
|
||||
@ -36,19 +36,24 @@ logoWidth w =
|
||||
|
||||
home : Html msg
|
||||
home =
|
||||
img [ src "icons/home-40.svg" ] []
|
||||
i [ class "fa fa-home" ] []
|
||||
|
||||
|
||||
docs : Html msg
|
||||
docs =
|
||||
img [ src "icons/notes-40.svg" ] []
|
||||
i [ class "fa fa-book" ] []
|
||||
|
||||
|
||||
github : Html msg
|
||||
github =
|
||||
img [ src "/icons/github-40.svg" ] []
|
||||
i [ class "fab fa-github-alt" ] []
|
||||
|
||||
|
||||
githubGreen : Html msg
|
||||
githubGreen =
|
||||
img [ src "/icons/github-40-green.svg" ] []
|
||||
|
||||
|
||||
blog : Html msg
|
||||
blog =
|
||||
i [ class "fa fa-blog" ] []
|
||||
|
@ -1,7 +1,6 @@
|
||||
module Main exposing (..)
|
||||
|
||||
import Browser exposing (Document)
|
||||
import Browser.Navigation exposing (Key)
|
||||
import Browser
|
||||
import Demo
|
||||
import ExtraAttr exposing (..)
|
||||
import Feature exposing (Feature)
|
||||
@ -109,34 +108,33 @@ subscriptions _ =
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
node "body"
|
||||
[]
|
||||
[ class "text-gray-700" ]
|
||||
[ mainHero model
|
||||
, demoHero
|
||||
, section [ class "section" ]
|
||||
[ div [ class "container" ]
|
||||
, demoHeader
|
||||
, section [ class "container max-w-screen-xl mx-auto mb-2" ]
|
||||
[ div [ class "mt-3 flex flex-col space-y-4" ]
|
||||
[ Demo.demo Demo.processDemo
|
||||
, Demo.demo Demo.navigateDemo
|
||||
]
|
||||
]
|
||||
, featureHero model
|
||||
, section [ class "section" ]
|
||||
[ div [ class "container" ]
|
||||
(List.indexedMap Feature.featureBox model.features
|
||||
++ [ div [ class "columns box" ]
|
||||
[ div [ class "column is-full" ]
|
||||
[ div [ class "content has-text-centered is-medium" ]
|
||||
[ text "A more complete list can be found in "
|
||||
, a [ href "/docs/features" ] [ text "here" ]
|
||||
, text "."
|
||||
]
|
||||
]
|
||||
, featureHeader model
|
||||
, section [ class "mx-auto max-w-screen-xl mb-2 mt-4" ]
|
||||
(List.indexedMap Feature.featureBox model.features
|
||||
++ [ div
|
||||
[ class "flex px-8 py-8 border rounded mb-5 shadow-lg text-2xl"
|
||||
, class "sm:flex-row sm:space-y-0 sm-space-x-4"
|
||||
, class "mx-2 sm:mx-8"
|
||||
]
|
||||
[ div [ class "text-center w-full" ]
|
||||
[ text "A more complete list can be found in "
|
||||
, a [ href "/docs/features", class "link" ] [ text "here" ]
|
||||
, text "."
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
, getStartedHero model
|
||||
, div [ class "section" ]
|
||||
(GetStarted.getStarted model.flags.version)
|
||||
]
|
||||
]
|
||||
)
|
||||
, getStartedHeader model
|
||||
, GetStarted.getStarted model.flags.version
|
||||
, footHero model
|
||||
]
|
||||
|
||||
@ -147,7 +145,7 @@ footHero model =
|
||||
[ id "footer"
|
||||
, class "footer"
|
||||
]
|
||||
[ div [ class "has-text-centered" ]
|
||||
[ div [ class "text-center" ]
|
||||
[ span []
|
||||
[ text ("Docspell, " ++ model.flags.version)
|
||||
]
|
||||
@ -157,6 +155,7 @@ footHero model =
|
||||
, a
|
||||
[ href "https://spdx.org/licenses/AGPL-3.0-or-later.html"
|
||||
, target "_blank"
|
||||
, class "link"
|
||||
]
|
||||
[ text "AGPLv3+"
|
||||
]
|
||||
@ -166,6 +165,7 @@ footHero model =
|
||||
, a
|
||||
[ href "https://github.com/eikek/docspell"
|
||||
, target "_blank"
|
||||
, class "link"
|
||||
]
|
||||
[ text "Source Code"
|
||||
]
|
||||
@ -176,6 +176,7 @@ footHero model =
|
||||
[ a
|
||||
[ href "https://gitter.im/eikek/docspell"
|
||||
, target "_blank"
|
||||
, class "link"
|
||||
]
|
||||
[ text "Chat on Gitter"
|
||||
]
|
||||
@ -184,166 +185,142 @@ footHero model =
|
||||
]
|
||||
|
||||
|
||||
getStartedHero : Model -> Html Msg
|
||||
getStartedHero _ =
|
||||
getStartedHeader : Model -> Html Msg
|
||||
getStartedHeader _ =
|
||||
section
|
||||
[ id "get-started"
|
||||
, class "hero is-primary is-bold"
|
||||
, class "hero-header"
|
||||
]
|
||||
[ div [ class "hero-body" ]
|
||||
[ div [ class "container" ]
|
||||
[ h2 [ class "title" ]
|
||||
[ text "Get Started"
|
||||
]
|
||||
]
|
||||
]
|
||||
[ text "Get Started"
|
||||
]
|
||||
|
||||
|
||||
demoHero : Html msg
|
||||
demoHero =
|
||||
section
|
||||
[ id "demos"
|
||||
, class "hero is-info is-bold"
|
||||
demoHeader : Html msg
|
||||
demoHeader =
|
||||
h2
|
||||
[ class "hero-header"
|
||||
, id "demos"
|
||||
]
|
||||
[ div
|
||||
[ class "hero-body"
|
||||
]
|
||||
[ div [ class "container" ]
|
||||
[ h2 [ class "title" ]
|
||||
[ text "Screencasts"
|
||||
]
|
||||
]
|
||||
]
|
||||
[ text "Screencasts"
|
||||
]
|
||||
|
||||
|
||||
featureHero : Model -> Html Msg
|
||||
featureHero model =
|
||||
section
|
||||
featureHeader : Model -> Html Msg
|
||||
featureHeader _ =
|
||||
h2
|
||||
[ id "feature-selection"
|
||||
, class "hero is-info is-bold"
|
||||
, class "hero-header"
|
||||
]
|
||||
[ div
|
||||
[ class "hero-body"
|
||||
[ text "Feature Selection"
|
||||
]
|
||||
|
||||
|
||||
navBar : String -> Html Msg
|
||||
navBar classes =
|
||||
nav
|
||||
[ id "top-nav"
|
||||
, class "top-0 z-50 w-full flex flex-row justify-start shadow-sm h-14 antialiased "
|
||||
, class classes
|
||||
]
|
||||
[ a
|
||||
[ onClick ToggleNavbarMenu
|
||||
, href "#"
|
||||
, class "font-bold inline-flex items-center px-4 w-10 sm:hidden "
|
||||
]
|
||||
[ div [ class "container" ]
|
||||
[ h2 [ class "title" ]
|
||||
[ text "Feature Selection"
|
||||
]
|
||||
[ i [ class "fa fa-bars" ] []
|
||||
]
|
||||
, a
|
||||
[ class "inline-flex px-4 items-center hover:bg-gray-50 hover:bg-opacity-20"
|
||||
, href "/"
|
||||
]
|
||||
[ div [ class "" ]
|
||||
[ Icons.logo
|
||||
]
|
||||
, span [ class "ml-1 text-2xl font-semibold font-serif" ]
|
||||
[ text "Docspell" ]
|
||||
]
|
||||
, a
|
||||
[ href "docs/"
|
||||
, class "px-4 flex items-center hover:bg-gray-50 hover:bg-opacity-20"
|
||||
, class " text-xl"
|
||||
]
|
||||
[ Icons.docs
|
||||
, span [ class "ml-2 tracking-wide" ]
|
||||
[ text "Documentation"
|
||||
]
|
||||
]
|
||||
, a
|
||||
[ href "blog/"
|
||||
, class "px-4 flex items-center hover:bg-gray-50 hover:bg-opacity-20"
|
||||
, class " text-xl"
|
||||
]
|
||||
[ Icons.blog
|
||||
, span [ class "ml-2 tracking-wide" ]
|
||||
[ text "Blog"
|
||||
]
|
||||
]
|
||||
, a
|
||||
[ target "_blank"
|
||||
, href "https://github.com/eikek/docspell"
|
||||
, class "px-4 flex items-center hover:bg-gray-50 hover:bg-opacity-20"
|
||||
, class " text-xl"
|
||||
]
|
||||
[ Icons.github
|
||||
, span [ class "ml-2 tracking-wide" ]
|
||||
[ text "Github"
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
mainHero : Model -> Html Msg
|
||||
mainHero model =
|
||||
mainHero _ =
|
||||
section
|
||||
[ id "hero-main"
|
||||
, class "hero is-fullheight is-primary"
|
||||
, class "min-h-screen text-white flex flex-col items-center main-background"
|
||||
]
|
||||
[ div [ class "hero-head" ]
|
||||
[ nav [ class "navbar" ]
|
||||
[ div [ class "navbar-brand" ]
|
||||
[ a
|
||||
[ class "navbar-item"
|
||||
, href "/"
|
||||
]
|
||||
[ span [ class "icon is-large" ]
|
||||
[ Icons.logo
|
||||
]
|
||||
, text "Docspell"
|
||||
]
|
||||
, a
|
||||
[ role "button"
|
||||
, onClick ToggleNavbarMenu
|
||||
, classList
|
||||
[ ( "navbar-burger", True )
|
||||
, ( "is-active", model.navbarOpen )
|
||||
]
|
||||
, ariaLabel "menu"
|
||||
, ariaExpanded False
|
||||
]
|
||||
[ span [ ariaHidden True ] []
|
||||
, span [ ariaHidden True ] []
|
||||
, span [ ariaHidden True ] []
|
||||
]
|
||||
[ navBar " text-white"
|
||||
, div [ class "flex-grow flex flex-col items-center justify-center w-full" ]
|
||||
[ Icons.logoWidth 112
|
||||
, h1 [ class "text-6xl font-semibold shadow font-serif" ]
|
||||
[ text "Docspell"
|
||||
]
|
||||
, h2 [ class "text-3xl font-madium tracking-wide mt-2 mb-4 " ]
|
||||
[ text "Simple document organizer"
|
||||
]
|
||||
, p [ class "px-2 text-center text-xl font-light shadow max-w-prose font-sans" ]
|
||||
[ text "Docspell assists in organizing your piles of "
|
||||
, text "digital documents, resulting from scanners, e-mails "
|
||||
, text "and other sources with miminal effort."
|
||||
]
|
||||
, div
|
||||
[ class "mt-4 flex flex-col space-y-2 text-2xl"
|
||||
, class "sm:items-center sm:flex-row sm:space-y-0 sm:space-x-4"
|
||||
]
|
||||
[ a
|
||||
[ class "button info"
|
||||
, href "#demos"
|
||||
]
|
||||
, div
|
||||
[ classList
|
||||
[ ( "navbar-menu", True )
|
||||
, ( "is-active", model.navbarOpen )
|
||||
]
|
||||
[ text "Screencasts"
|
||||
]
|
||||
[ div [ class "navbar-start" ]
|
||||
[ a
|
||||
[ href "docs/"
|
||||
, class "navbar-item"
|
||||
]
|
||||
[ span [ class "icon" ]
|
||||
[ Icons.docs
|
||||
]
|
||||
, span []
|
||||
[ text "Documentation"
|
||||
]
|
||||
]
|
||||
, a
|
||||
[ target "_blank"
|
||||
, href "https://github.com/eikek/docspell"
|
||||
, class "navbar-item"
|
||||
]
|
||||
[ span [ class "icon" ]
|
||||
[ Icons.github
|
||||
]
|
||||
, span []
|
||||
[ text "Github"
|
||||
]
|
||||
]
|
||||
]
|
||||
, a
|
||||
[ class "button info"
|
||||
, href "#feature-selection"
|
||||
]
|
||||
[ text "Features"
|
||||
]
|
||||
, a
|
||||
[ class "button primary"
|
||||
, href "#get-started"
|
||||
]
|
||||
[ text "Get Started"
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "hero-body" ]
|
||||
[ div
|
||||
[ class "container has-text-centered"
|
||||
]
|
||||
[ Icons.logoWidth 112
|
||||
, h1 [ class "title main-title is-2" ]
|
||||
[ text "Docspell"
|
||||
]
|
||||
, h2 [ class "subtitle is-3" ]
|
||||
[ text "Simple document organizer"
|
||||
]
|
||||
, p [ class "content is-medium narrow-center" ]
|
||||
[ text "Docspell assists in organizing your piles of "
|
||||
, text "digital documents, resulting from scanners, e-mails "
|
||||
, text "and other sources with miminal effort."
|
||||
]
|
||||
, div [ class " buttons is-centered" ]
|
||||
[ a
|
||||
[ class "button is-info is-medium"
|
||||
, href "#demos"
|
||||
]
|
||||
[ text "Screencasts"
|
||||
]
|
||||
, a
|
||||
[ class "button is-info is-medium"
|
||||
, href "#feature-selection"
|
||||
]
|
||||
[ text "Features"
|
||||
]
|
||||
, a
|
||||
[ class "button is-primary is-medium"
|
||||
, href "#get-started"
|
||||
]
|
||||
[ text "Get Started"
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "hero-foot" ]
|
||||
[ span [ class "unsplash-credit" ]
|
||||
[ text "Photo by "
|
||||
, div [ class "text-right w-full" ]
|
||||
[ span [ class "opacity-40 text-xs" ]
|
||||
[ i [ class "fab fa-unsplash mr-1" ] []
|
||||
, text "Photo by "
|
||||
, a
|
||||
[ href "https://unsplash.com/@numericcitizen"
|
||||
, target "_blank"
|
||||
|
@ -1,11 +1,9 @@
|
||||
port module Search exposing (..)
|
||||
|
||||
import Browser exposing (Document)
|
||||
import Browser.Navigation exposing (Key)
|
||||
import Browser
|
||||
import Html as H exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick, onInput, onSubmit)
|
||||
import Json.Decode as D
|
||||
import Markdown
|
||||
|
||||
|
||||
@ -45,14 +43,21 @@ type alias SearchEntry =
|
||||
}
|
||||
|
||||
|
||||
type SearchState
|
||||
= Initial
|
||||
| Found (List SearchEntry)
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ searchInput : String
|
||||
, results : List SearchEntry
|
||||
, results : SearchState
|
||||
, searchVisible : Bool
|
||||
}
|
||||
|
||||
|
||||
type Msg
|
||||
= SetSearch String
|
||||
| ToggleBar
|
||||
| SubmitSearch
|
||||
| GetSearchResults (List SearchEntry)
|
||||
|
||||
@ -64,7 +69,8 @@ type Msg
|
||||
init : Flags -> ( Model, Cmd Msg )
|
||||
init flags =
|
||||
( { searchInput = ""
|
||||
, results = []
|
||||
, results = Initial
|
||||
, searchVisible = False
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
@ -77,6 +83,11 @@ init flags =
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
ToggleBar ->
|
||||
( { model | searchVisible = not model.searchVisible }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
SetSearch str ->
|
||||
( { model | searchInput = str }
|
||||
, Cmd.none
|
||||
@ -86,7 +97,7 @@ update msg model =
|
||||
( model, doSearch model.searchInput )
|
||||
|
||||
GetSearchResults list ->
|
||||
( { model | results = List.take 8 list }, Cmd.none )
|
||||
( { model | results = Found <| List.take 20 list }, Cmd.none )
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
@ -100,56 +111,67 @@ subscriptions _ =
|
||||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
H.form
|
||||
[ class "form"
|
||||
, onSubmit SubmitSearch
|
||||
div
|
||||
[ class " inline-flex px-4 items-center hover:bg-amber-600 hover:bg-opacity-10 dark:hover:bg-stone-800"
|
||||
]
|
||||
[ div [ class "dropdown field is-active is-fullwidth has-addons" ]
|
||||
[ div [ class "control is-fullwidth" ]
|
||||
[ a
|
||||
[ href "#"
|
||||
, class "h-full w-full inline-flex items-center"
|
||||
, onClick ToggleBar
|
||||
]
|
||||
[ i [ class "fa fa-search" ] []
|
||||
]
|
||||
, div
|
||||
[ class "absolute px-2 mx-2 right-0 max-w-screen-md rounded top-12 w-full border-l border-r border-b bg-white h-12 dark:bg-stone-800 dark:border-stone-700"
|
||||
, classList [ ( "hidden", not model.searchVisible ) ]
|
||||
]
|
||||
[ H.form [ onSubmit SubmitSearch ]
|
||||
[ input
|
||||
[ class "input"
|
||||
, type_ "text"
|
||||
, placeholder "Search docs…"
|
||||
, onInput SetSearch
|
||||
[ type_ "text"
|
||||
, value model.searchInput
|
||||
, autofocus True
|
||||
, placeholder "Search …"
|
||||
, class "w-full block h-8 border-0 border-b border-stone-400 mt-2 focus:ring-0 focus:border-indigo-500 dark:bg-stone-800 dark:focus:border-cyan-400"
|
||||
, onInput SetSearch
|
||||
]
|
||||
[]
|
||||
]
|
||||
, div [ class "control" ]
|
||||
[ button
|
||||
[ class "button is-primary"
|
||||
, href "#"
|
||||
, onClick SubmitSearch
|
||||
]
|
||||
[ img [ src "/icons/search-white-20.svg" ] []
|
||||
]
|
||||
]
|
||||
, viewResults model.results
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
viewResults : List SearchEntry -> Html Msg
|
||||
viewResults entries =
|
||||
div
|
||||
[ classList
|
||||
[ ( "dropdown-menu", True )
|
||||
, ( "is-hidden", entries == [] )
|
||||
]
|
||||
]
|
||||
[ div [ class "dropdown-content" ]
|
||||
(List.intersperse
|
||||
(div [ class "dropdown-divider" ] [])
|
||||
(List.map viewResult entries)
|
||||
)
|
||||
]
|
||||
viewResults : SearchState -> Html Msg
|
||||
viewResults state =
|
||||
case state of
|
||||
Initial ->
|
||||
span [ class "hidden" ] []
|
||||
|
||||
Found [] ->
|
||||
div
|
||||
[ class "bg-white dark:bg-stone-800 mt-2 w-full"
|
||||
]
|
||||
[ div [ class "flex flex-row items-center h-14 justify-center text-xl" ]
|
||||
[ i [ class "fa fa-meh font-thin mr-2" ]
|
||||
[]
|
||||
, text "No results."
|
||||
]
|
||||
]
|
||||
|
||||
Found entries ->
|
||||
div
|
||||
[ class "bg-white dark:bg-stone-800 mt-2 w-screen sm:w-full h-screen-12 md:h-fit md:max-h-96 overflow-auto shadow-lg border-l border-r border-b dark:border-stone-700"
|
||||
]
|
||||
[ div [ class "px-2 pt-2 pb-1 flex flex-col divide-y dark:divide-stone-700 " ]
|
||||
(List.map viewResult entries)
|
||||
]
|
||||
|
||||
|
||||
viewResult : SearchEntry -> Html Msg
|
||||
viewResult result =
|
||||
div [ class "dropdown-item" ]
|
||||
div [ class "py-2 content" ]
|
||||
[ a
|
||||
[ class "is-size-5"
|
||||
[ class "text-lg font-semibold"
|
||||
, href result.ref
|
||||
]
|
||||
[ text result.doc.title
|
||||
@ -158,6 +180,16 @@ viewResult result =
|
||||
]
|
||||
|
||||
|
||||
textInput : String
|
||||
textInput =
|
||||
" placeholder-gray-400 w-full dark:text-slate-200 dark:bg-slate-800 dark:border-slate-500 border-gray-400 rounded " ++ formFocusRing
|
||||
|
||||
|
||||
formFocusRing : String
|
||||
formFocusRing =
|
||||
" focus:ring focus:ring-black focus:ring-opacity-50 focus:ring-offset-0 dark:focus:ring-slate-400 "
|
||||
|
||||
|
||||
|
||||
--- Ports
|
||||
|
||||
|
Reference in New Issue
Block a user