Website redesign

This commit is contained in:
eikek 2022-01-27 20:23:15 +01:00
parent 3fc7f54f1a
commit 261d2af9bb
248 changed files with 3519 additions and 1484 deletions

6
.gitignore vendored
View File

@ -7,10 +7,14 @@ elm-stuff
result
_site/
*.qcow2
/website/site/content/docs/changelog/
/website/site/content/docs/install/changelog.md
/website/site/public/
/website/site/static/openapi/
/website/site/static/js/bundle.js
/website/site/static/styles.css
/website/site/static/syntax-*.css
/website/site/static/webfonts/
/website/site/static/files/*.woff*
/website/site/templates/shortcodes/server.conf
/website/site/templates/shortcodes/sample-exim.conf
/website/site/templates/shortcodes/joex.conf

View File

@ -840,19 +840,17 @@ val website = project
}.taskValue,
Compile / resourceGenerators += Def.task {
val changelog = (LocalRootProject / baseDirectory).value / "Changelog.md"
val targetDir = baseDirectory.value / "site" / "content" / "docs" / "changelog"
val targetDir = baseDirectory.value / "site" / "content" / "docs" / "install"
IO.createDirectory(targetDir)
val target = targetDir / "_index.md"
val target = targetDir / "changelog.md"
IO.write(
target,
"""|+++
|title = "Changelog"
|description = "See what changed between releases."
|weight = 10
|weight = 10000
|insert_anchor_links = "right"
|[extra]
|maketoc = false
|+++
|""".stripMargin
)

View File

@ -15,6 +15,7 @@ object Cmd {
}
def run(cmd: Seq[String], wd: File, logger: Logger): Unit = {
logger.info(s"Running ${cmd.mkString(" ")}")
val res = Cmd.exec(cmd, Some(wd))
logger.info(res.out)
logger.error(res.err)

View File

@ -2,6 +2,7 @@ package docspell.build
import sbt._
import sbt.Keys._
import sbt.nio.file.FileTreeView
import scala.sys.process._
object ZolaPlugin extends AutoPlugin {
@ -74,10 +75,12 @@ object ZolaPlugin extends AutoPlugin {
case Some(url) =>
Seq("--base-url", url)
case None =>
runYarnInstall("yarn", inDir.getParentFile, logger)
runElmCompile("elm", inDir.getParentFile, inDir, logger)
Seq.empty
}
runYarnInstall("yarn", inDir.getParentFile, logger)
runElmCompile("elm", inDir.getParentFile, inDir, logger)
runTailwind("npx", inDir.getParentFile, inDir, logger)
Cmd.run(
Seq(zolaCmd, "build", "-o", outDir.absolutePath.toString) ++ baseUrl,
inDir,
@ -106,4 +109,39 @@ object ZolaPlugin extends AutoPlugin {
logger
)
def runTailwind(npx: String, inDir: File, zolaRoot: File, logger: Logger): Unit = {
val fontTarget = zolaRoot / "static" / "files"
val iconTarget = zolaRoot / "static" / "webfonts"
IO.createDirectories(Seq(fontTarget, iconTarget))
val fontIn = Glob(inDir / "node_modules" / "@fontsource") / * / "files" / *
val fontInFiles = FileTreeView.default.list(fontIn).map(_._1.toFile())
logger.info(s"Copy ${fontInFiles.size} webfonts from node_modules to ${fontTarget}")
IO.copy(fontInFiles.pair(Path.flat(fontTarget)))
val iconIn =
Glob(inDir / "node_modules" / "@fortawesome" / "fontawesome-free" / "webfonts") / *
val iconInFiles = FileTreeView.default.list(iconIn).map(_._1.toFile())
logger.info(s"Copy ${iconInFiles.size} icons from node_modules to ${iconTarget}")
IO.copy(iconInFiles.pair(Path.flat(iconTarget)))
logger.info("Running tailwind…")
Cmd.run(
Seq(
npx,
"tailwindcss",
"-i",
(inDir / "styles" / "input.css").toString,
"-o",
(zolaRoot / "static" / "styles.css").toString,
"--config",
(inDir / "tailwind.config.js").toString,
"--postcss",
(inDir / "postcss.config.js").toString,
"--minify"
),
inDir,
logger
)
}
}

View File

@ -8,61 +8,61 @@ The website is created using [zola](https://github.com/getzola/zola)
static site generator. The (very minimal) dynamic parts are written in
Elm.
The `build.sh` script builds the site.
Sbt is used to build the site.
## Development
Install things by running `yarn install`.
Open two terminals. In first run:
Open terminal for each script below:
``` shell
nix-shell --run ./run-elm.sh
```
and in the second
``` shell
nix-shell --run "cd site && zola serve"
```
1. Starting the server
``` shell
nix-shell --run "cd site && zola serve"
```
2. Building the stylesheet
``` shell
nix-shell --run ./scripts/run-styles.sh
```
3. Building some javascript files
``` shell
nix-shell --run ./scripts/run-elm.sh
```
Open browser at `localhost:1111`.
## Publishing
The above is great when editing, but doesn't fully reflect what will
be finally deployed. To see this, start sbt and change into the
website project.
``` shell
nix-shell website/shell.nix --run sbt
sbt> project website
```
### Check Links
Build everything and check for dead links:
``` scala
sbt> zolaBuild
sbt> zolaBuildTest
sbt> zolaCheck
```
### Testing
``` scala
sbt> zolaBuildTest
sbt> ghpagesSynchLocal
```
Other terminal:
The final site is now generated and a simple http server can be used
to see how it will look when deployed.
``` shell
cd ~/.sbt/ghpages/<some-hash>/com.github.eikek/docspell-website
python -m SimpleHTTPServer 1234
python -m http.server 1234
```
Open http://localhost:1234 in a browser.
### Publish
``` scala
sbt> zolaBuild
sbt> ghpagesPushSite
```

View File

@ -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
]
[]
]
]

View File

@ -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.
"""
}
]

View File

@ -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."
]
]
]
]
]

View File

@ -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" ] []

View File

@ -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"

View File

@ -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

View File

@ -1,6 +1,17 @@
{
"license": "GPL-3.0-or-later",
"dependencies": {
"bulma": "^0.9.0"
"@fontsource/montserrat": "^4.5.3",
"@fontsource/source-code-pro": "^4.5.2",
"@fontsource/spectral": "^4.5.1",
"@fortawesome/fontawesome-free": "^5.15",
"@tailwindcss/forms": "^0.4.0",
"autoprefixer": "^10.4",
"cssnano": "^5.0",
"postcss": "^8.4.5",
"postcss-cli": "^9.1.0",
"postcss-import": "^14.0.2",
"postcss-purgecss": "^2.0.3",
"tailwindcss": "^3.0"
}
}

10
website/postcss.config.js Normal file
View File

@ -0,0 +1,10 @@
//postcss.config.js
module.exports = (ctx) => ({
plugins: [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
require('cssnano'),
]
})

View File

@ -3,6 +3,7 @@
set -e
yarn install
npx tailwindcss -i ./styles/input.css -o ./site/public/styles.css --config ./tailwind.config.js --postcss ./postcss.config.js
elm make --output site/static/js/bundle.js --optimize elm/Main.elm
cd site && zola build
cd ..

11
website/scripts/run-styles.sh Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
mkdir -p ./site/public/files
mkdir -p ./site/public/webfonts
echo "Copy webfonts…"
cp node_modules/@fontsource/*/files/* ./site/public/files/
cp node_modules/@fortawesome/fontawesome-free/webfonts/* ./site/public/webfonts/
echo "Running tailwind…"
npx tailwindcss -i ./styles/input.css -o ./site/public/styles.css --config ./tailwind.config.js --postcss ./postcss.config.js "$1"

74
website/scripts/screenshot.sh Executable file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env bash
#
# Little tool to help with doing screenshots.
#
# Run: ./screenshot.sh output.png
#
# Then select a window. It will create a screenshot from that window,
# cut (optionally) some pixels (removes the browser bar) and then
# resizes it to some maximum width.
set -e
# input file
file=/tmp/screenshot.png
# final output file
out=/tmp/screenshot-out.png
# image dimension ratio w:h
ratio=${RATIO:-"16:9"}
# cut that much from the top to remove browser bar (my firefox settings)
top_cut=${TOP_CUT:-85}
# maximum width of final image
maxw=${MAXW:-1200}
# time to wait in secs
waitsec=${WAIT_SEC:-3}
#### Main ############
work=/tmp/screenshot-work.png
debug() {
(1>&2 echo "$@")
}
scrot -s -c -d $waitsec "$file" 1>&2
cp "$file" "$work"
read -r w h < <(identify -verbose $file |\
grep "Geometry:" | \
cut -d':' -f2 | \
cut -d'+' -f1 | \
tr 'x' ' ' | xargs)
debug "Original size: ${w}x${h}"
read nw nh < <(echo $ratio | tr ':' ' ')
# remove browser bar from top
((h=$h - $top_cut))
# create height to match ratio
((newH=($w * $nh) / $nw))
if [ $newH -gt $h ]; then
debug "Cropping to $w x $h"
debug "Cannot crop to ratio without reducing width"
convert -crop ${w}x${h}+0+${top_cut} "$work" "$out"
else
debug "Cropping to $w x $h"
convert -crop ${w}x${newH}+0+${top_cut} "$work" "$out"
fi
cp "$out" "$work"
debug "Resize to max width $maxw"
convert -resize $maxw "$work" "$out"
rm -f "$work" "$file"
if [ -z "$1" ]; then
echo "$out"
else
mv "$out" "$1"
echo "$1"
fi

40
website/scripts/screenshot2.sh Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
#
# Uses the `screenshot.sh` script to create one screenshot per theme.
#
# First sets light theme and takes a screenshot, then sets dark theme
# and calls screenshot.sh again
#
# Might need to fiddle with the xdotool command
docspell_url=http://localhost:7880
docspell_user=demo
docspell_pass=test
screenshot="$(dirname $0)/screenshot.sh"
out_base="$1"
work_dir=$(mktemp -dt screenshot2-script.XXXXXX)
export HOME=$work_dir
export RATIO="16:9"
export WAIT_SEC=4
#export TOP_CUT=400
dsc write-default-config
sed -i "s,http://localhost:7880,$docspell_url,g" $HOME/.config/dsc/config.toml
set_theme() {
dsc login -u $docspell_user --password $docspell_pass 2>&1 > /dev/null
local token=$(cat $HOME/.config/dsc/dsc-token.json | jq -r '.token')
data=$(curl -sSL -H "X-Docspell-Auth: $token" $docspell_url/api/v1/sec/clientSettings/webClient | jq ".uiTheme=\"$1\"")
curl -sSL -H "X-Docspell-Auth: $token" -XPUT --data "$data" $docspell_url/api/v1/sec/clientSettings/user/webClient
xdotool search --name "Mozilla Firefox" | xargs xdotool windowactivate && xdotool key F5
}
set_theme "Light"
$screenshot "${out_base}.png"
set_theme "dark"
$screenshot "${out_base}_dark.png"

View File

@ -1,7 +1,8 @@
let
nixpkgs = builtins.fetchTarball {
#url = "channel:nixos-21.05";
url = "https://github.com/NixOS/nixpkgs/archive/e6badb26fc0d238fda2432c45b7dd4e782eb8200.tar.gz";
#url = "channel:nixos-21.11";
#url = "https://github.com/NixOS/nixpkgs/archive/e6badb26fc0d238fda2432c45b7dd4e782eb8200.tar.gz";
url = "https://github.com/NixOs/nixpkgs/archive/0f316e4d72daed659233817ffe52bf08e081b5de.tar.gz"; #21.11
};
pkgs = import nixpkgs { };
in
@ -11,6 +12,9 @@ with pkgs;
buildInputs = [
zola
yarn
sbt
elmPackages.elm
nodejs
inotifyTools
];
}

View File

@ -11,7 +11,13 @@ default_language = "en"
[markdown]
highlight_code = true
highlight_theme = "gruvbox-dark"
#light: ayu-light, OneHalfLight, base16-ocean-light
highlight_theme = "css"
highlight_themes_css = [
{ theme = "gruvbox-dark", filename = "syntax-dark.css" },
{ theme = "base16-ocean-light", filename = "syntax-light.css" }
]
[link_checker]
skip_prefixes = [

View File

@ -0,0 +1,24 @@
+++
title = "Preproces Scans before upload"
[extra]
author = "@eresturo"
authorLink = "https://github.com/eresturo"
+++
# Preproces Scans before upload
This script scans from the ADF (Automatic Document Feeder),
preprocesses it and uploads it to Docspell:
[scanadf2docspell](https://github.com/eresturo/scanadf2docspell)
<!-- more -->
<figure>
<img src="https://github.com/eresturo/scanadf2docspell/raw/main/overview.png">
</figure>
I don't know if this is helpful to other Docspell users, but feel free
to link to it in the Docspell documentation.
Any suggestions or missing features?
Sheers eresturo

View File

@ -0,0 +1,51 @@
+++
title = "Upload directly from the browser or email client"
[extra]
author = "gandy92"
+++
# Uploading from browser or email client
An alternative approach came to mind to directly upload from a browser
or email client that at least works on a Linux system. In case this is
interesting for others, I'd like to share it here.
<!-- more -->
1. Create and activate a source in your collective (in this example
MYCOLL); note that path to the file upload (the one with
`/api/v1/open/upload/item/`)
2. Create a file `docspell-upload-MYCOLL` with the following content (replace `UPLOAD_PATH` with the actual path):
```
#!/bin/bash
logger -t docspell_upload -- Docspell upload to MYCOLL: "$*" $(
curl -s -XPOST -F file=@"$1" UPLOAD_PATH
)
```
3. Make it executable: `chmod 755 docspell-upload-MYCOLL`
4. Create a file named `docspell-MYCOLL.desktop` with the following
content (note that you need the full path to
`docspell-upload-MYCOLL`):
```
[Desktop Entry]
Exec=PATH_TO_docspell-upload-MYCOLL %F
MimeType=application/pdf;application/x-zip;application/x-zip-compressed;application/zip
Name=Docspell Upload (MYCOLL)
NoDisplay=true
Type=Application
```
5. Place the file `docspell-MYCOLL.desktop` in
`$HOME/.local/share/applications/`
6. Configure your browser or mail-reader actions for pdf and zip: They
should always ask what to do rather than opening a link or
attachment with the standard application or save it to disk by
default. Actually, always opening a pdf in the browser is fine, if
this allows to later save the viewed file.
Now, when clicking on a file link or attachment, the browser or email
client should ask what to do. You then should be able to choose
"Docspell Upload (MYCOLL)" from the list, which will upload the file
to your collection.
If anything goes wrong, you can monitor the server response with the
command `journalctl -f -t docspell_upload`

View File

@ -0,0 +1,249 @@
+++
title = "Create a new post"
[extra]
author = "eikek"
+++
# Create a new post
Sharing ideas and tips is very much welcome, if you like you can
create a small (or large) post here. You'll need `git` and potentially
a `github` account to make this convenient.
<!-- more -->
The contents of this website is maintained in the [<i class="fab fa-github ml-1"></i> git
repository](https://github.com/eikek/docspell) in the `website/site`
folder. It is build by the static site generator
[zola](https://getzola.org) from a set of
[markdown](https://www.markdownguide.org/basic-syntax) files.
It is not necessary to know how everything is connected, you only need
to edit or create markdown files at some specific location. Here are
some proposals how to add or edit pages and getting them published to
docspell.org.
## Where to create the files
The contents of the published website is in the branch `current-docs`.
You should base your changes on this branch.
All blog pages go into this directory: `website/site/content/blog/`.
In this directory each post is a markdown file named by this pattern:
```
<year>-<month>-<day>_title_with_underscores.md
```
For example, this page here is named `2022-01-31_create_post.md`.
## Write on Github
A very convenient way is to edit and create posts directly on github
in the browser. All pages contain a small `Edit` link at the bottom
that takes you directly into edit model of the corresponding file on
github.
To create a new file on github, you can use this link:
<https://github.com/eikek/docspell/new/current-docs/website/site/content/blog>
It will present a form that lets you create a new file with content.
Once you commit this change, the project will be forked into your
account and the change is applied to this new fork. Then you can
create a pull request into this repository in order to publish it.
Plase see [below](#content) for how to start writing content.
## Writing locally
The preferred approach is to explicitely fork the repository and clone
it to your machine to do the modification. The big advantage is, that
you can look at the results while writing.
If you want to see a live view of the page while editing, some tools
are required. The easiest way to get these is to install
[nix](https://nixos.org/) and run `nix-shell website/shell.nix` to get
an environment with all these tools installed. Otherwise install the
programs mentioned in `website/shell.nix`, which are:
[yarn](https://yarnpkg.com/), [zola](https://getzola.org),
[elm](https://elm-lang.org) and [sbt](https://scala-sbt.org).
Then clone the sources to your machine and build the complete site
once, so that all assets and required stuff is present:
```
sbt website/zolaBuildTest
```
Now you can use zola to start the page and watch for changes. The
changes are visible immediately without reloading the page in the
browser.
```
cd website/site && zola serve
```
This starts a web server on some port (usually `1111`); point your
browser to it and navigate to your new page. Whenever changes are
saved to the markdown file, the page refreshes automatically.
If styling is changed (in the css files or also sometimes when adding
new classes to HTML elements), a rebuild of the site css is necessary.
This can be done by running `scripts/run-styles.sh`. Via
`scripts/run-styles.sh --watch` it is possible to watch for these
changes as well. But it shouldn't be necessary to do large edits to
the css.
# Content
## Front matter
The very beginning of such a markdown file contains some metadata.
Start each page with these lines:
```markdown
+++
title = "Title of the post"
[extra]
author = "<your name>"
authorLink = "https://some-url"
+++
# First heading…
```
The front matter is the first part enclosed in `+++`. See
[zola](https://www.getzola.org/documentation/content/page/)
documentation for more details.
The `author` and `authorLink` setting is optional. You can leave out
the complete `[extra]` section. If `authorLink`is defined, the author
is rendered as a link to that URL. If `author` is missing, it defaults
to "_Unknown_".
## Elements
The content is styled automatically and the post is added to the list
on the main blog page. Additional to the standard markdown formatting,
there are some more usefull elements.
### Linking
If you want to link to an internal page, use markdown links where the
path is formatted like this:
```markdown
[link title](@/path/to/markdown_file.md)
```
Using the `@/path` style, zola generates the correct final link (and
checks for dead links).
### Info and warning boxes
There are small templates available to format a basic info or warning
box message.
```markdown
{%/* infobubble(title="My Title") */%}
Your content here ….
{%/* end */%}
```
For a box more styled like a warning, replace `info` with `warning`.
```markdown
{%/* warningbubble(title="My Title") */%}
Your content here ….
{%/* end */%}
```
This will render into:
{% infobubble(title="My Title") %}
Your content here ….
{% end %}
{% warningbubble(title="My Title") %}
Your content here ….
{% end %}
### Summary
In order to get a decent summary in the list of posts, you need to set
a marker in your file. Place a line containing only
```
<!-- more -->
```
into your file and everything before it will be rendered as a summary
on the blog listing.
### Buttons
Styled buttons can be created using HTML inside the markdown file:
```markdown
<a class="no-default button1" href="#">Click!</a>
```
Turns into:
<a class="no-default button1" href="#">Click!</a>
### Images
In image to appear on the whole page, use HTML with a `figure` tag:
```
<figure>
<img src="image-url.jpg">
</figure>
```
<figure>
<img src="/img/jesse-gardner-EqdpXeemf58-unsplash.jpg" >
</figure>
The site has a light and dark mode and sometimes it's nice to provide
images for both variants. You can use HTML for this and a specific
class per theme:
```html
<figure class="dark-block">
<img src="dark-image.jpg" >
</figure>
<figure class="light-block">
<img src="light-image.jpg" >
</figure>
```
See the effect when changing the theme:
<figure class="dark-block">
<img src="/img/tersius-van-rhyn-xcQWMPm9fG8-unsplash.jpg" >
</figure>
<figure class="light-block">
<img src="/img/cassie-boca-x-tbVqkfQCU-unsplash.jpg" >
</figure>
This can be done via a template if the file is next to the markdown
file in the same directory:
```markdown
{{/* figure2(light="light-image.jpg", dark="dark-image.jpg") */}}
```
<div class="text-sm text-right opacity-80">
Pictures are from <a href="https://unsplash.com" target="_blank">Unsplash</a>.
</div>
# Publish
Open a pull request against the `current-docs` branch. When the pull
request is merged, the publishing process starts automatically and the
content is available minutes after.

View File

@ -0,0 +1,15 @@
+++
title = "Main"
description = "Random collection of stuff around Docspell"
template = "blog.html"
page_template = "blog_page.html"
sort_by = "date"
insert_anchor_links = "right"
+++
# Blog
This is a place to collect random tips and knowledge around Docspell.
This is organized as a log, where entries can be added by whoever
likes to share something. Check [this
page](@/blog/2022-01-31_create_post.md) for creating content here.

View File

@ -1,3 +0,0 @@
+++
redirect_to = "/docs"
+++

View File

@ -1,9 +1,150 @@
+++
title = "Overview"
template = "overview.html"
title = "Documentation"
template = "docs.html"
page_template = "docs.html"
insert_anchor_links = "right"
+++
# Note
This content is not rendered. Everything is in the template.
# Introduction
Docspell aims to be a simple yet effective document organizer that
makes stowing documents away very quick and finding them later
reliable (and also fast). It is a bit opinionated and more targeted
for home use and small/medium organizations.
In contrast to many DMS, the main focus is not so much to provide all
kinds of features to manually create organizational structures, like
folder hierarchies, where you place the documents yourself. The
approach is to leave it as a big pile of documents, but extract and
attach metadata from each document. These are mainly properties that
emerge from the document itself. The reason is that this is possible
to automate. This makes it very simple to *add* documents, because
there is no time spent to think about where to put it. And it is
possible to apply different structures on top later, like show first
all documents of a specific correspondent, then all with tag
'invoice', etc. If these properties are attached to all documents, it
is really easy to find a document. It even can be combined with
fulltext search for the, hopefully rare, desperate cases.
Of course, it is also possible to add custom properties and arbitrary
tags.
Docspell analyzes the text to find metadata automatically. It can
learn from existing data and can apply
[NLP](https://en.wikipedia.org/wiki/Natural_language_processing)
techniques to support this. This metadata must be maintained manually
in the application. Docspell looks for candidates for:
- Correspondents
- Concerned person or things
- A date and due date
- Tags
For tags, it sets all that it thinks do apply. For the others, it will
propose a few candidates and sets the most likely one to your item.
This might be wrong, so it is recommended to curate the results.
However, very often the correct one is either set or within the
proposals where you fix it by a single click.
Besides these properties, there are more metadata you can use to
organize your files, for example custom fields, folders and notes.
Docspell is also for programmers. Everything is available via a REST
or HTTP api and can be easily used within your own scripts and tools,
for example using `curl`. There are also features for "advanced use"
and many configuration options.
# Components
Docspell consists of multiple components that run in separate
processes:
- REST server
- JOEX, short for *job executor*
- Fulltext Search Index (optional, currently Apache SOLR)
The REST server provides the Api and the web application. The web
application is a
[SPA](https://en.wikipedia.org/wiki/Single-page_application) written
in [Elm](https://elm-lang.org) and is a client to the REST api. All
features are available via a http/rest api.
The *joex* is the component that does the “heavy work”, executing
long-running tasks, like processing files or importing your mails
periodically. While the joex component also exposes a small REST api
for controlling it, the main user interface is all inside the rest
server api.
The rest server and the job executor can be started multiple times in
order to scale out. It must be ensured, that all connect to the same
database. And it is also recommended (though not strictly required),
that all components can reach each other.
The fulltext search index is another separate component, where
currently only [SOLR](https://solr.apache.org) is supported.
Fulltext search is optional, so the SOLR component is not required if
docspell is run without fulltext search support.
# Terms
In order to better understand the following pages, some terms are
explained.
## Item
An *item* is roughly your document, only that an item may span
multiple files, which are called *attachments*. An item has *meta
data* associated:
- a *correspondent*: the other side of the communication. It can be
an organization or a person.
- a *concerning person* or *equipment*: a person or thing that
this item is about. Maybe it is an insurance contract about your
car.
- *tag*: an item can be tagged with one or more tags (or labels). A
tag can have a *category*. This is intended for grouping tags, for
example a category `doctype` could be used to group tags like
`bill`, `contract`, `receipt` etc. Usually an item is not tagged
with more than one tag of a category.
- a *folder*: a folder is similiar to a tag, but an item can only be
in exactly one folder (or none). Furthermore folders allow to
associate users, so that items are only visible to the users who are
members of a folder.
- an *item date*: this is the date of the document if this is not
set, the created date of the item is used.
- a *due date*: an optional date indicating that something has to be
done (e.g. paying a bill, submitting it) about this item until this
date
- a *direction*: one of "incoming" or "outgoing"
- a *name*: some item name, defaults to the file name of the
attachments
- some *notes*: arbitrary descriptive text. You can use markdown
here, which is properly formatted in the web application.
## Collective
The users of the application are part of a *collective*. A
*collective* is a group of users that share access to the same
items. The account name is therefore comprised of a *collective name*
and a *user name*.
All users of a collective are equal; they have same permissions to
access all items. The items don't belong to a user, but to the
collective.
That means, to identify yourself when signing in, you have to give the
collective name and your user name. By default it is separated by a
slash `/`, for example `smith/john`. If your user name is the same as
the collective name, you can omit one; so `smith/smith` can be
abbreviated to just `smith`.
By default, all users can see all items of their collective. A
*folder* can be used to implement other visibilities: Every user can
create a folder and associate members. It is possible to put items in
these folders and docspell shows only items that are either in no
specific folder or in a folder where the current user is owner or
member.

View File

@ -3,9 +3,6 @@ title = "Api"
description = "Contains documentation about the REST API."
weight = 70
insert_anchor_links = "right"
template = "pages.html"
template = "docs.html"
sort_by = "weight"
redirect_to = "docs/api/intro"
+++
No Content

View File

@ -3,10 +3,10 @@ title = "Api Introduction"
description = "Api Basics"
weight = 10
insert_anchor_links = "right"
[extra]
mktoc = true
+++
# Api
Docspell is designed as a REST server that uses JSON to exchange
data. The REST api can be used to integrate docspell into your
workflow.

View File

@ -3,10 +3,10 @@ title = "Upload Request"
description = "Describes the upload request"
weight = 20
insert_anchor_links = "right"
[extra]
mktoc = true
+++
# Upload Request
Uploads of files to docspell are always processed the same way, no
matter if coming from a source, the integration endpoint or from the
webapp.

View File

@ -3,10 +3,11 @@ title = "Configuration"
insert_anchor_links = "right"
description = "Describes the configuration file and shows all default settings."
weight = 40
[extra]
mktoc = true
template = "docs.html"
+++
# Configuration
Docspell's executables (restserver and joex) can take one argument a
configuration file. If that is not given, the defaults are used,
overriden by environment variables. A config file overrides default

View File

@ -4,11 +4,14 @@ description = "Contains some ADRs, which are internal notes on decisions made."
weight = 300
sort_by = "weight"
insert_anchor_links = "right"
template = "pages.html"
template = "docs.html"
page_template = "docs.html"
[extra]
mktoc = true
page_list = true
+++
# ADR
This contains a list of ADRs, most of them are from very early. It
often just contains notes that could go nowhere else, but still should
be captured.

View File

@ -3,6 +3,7 @@ title = "Building Docspell"
weight = 0
+++
# Building
You must install [sbt](https://scala-sbt.org),
[nodejs](https://www.npmjs.com/get-npm) (for the `npm` command) and

View File

@ -3,7 +3,9 @@ title = "Tips & Setup"
weight = 20
+++
# Starting Servers with `reStart`
# Setup / Tips
## Starting Servers with `reStart`
When developing, it's very convenient to use the [revolver sbt
plugin](https://github.com/spray/sbt-revolver). Start the sbt console
@ -29,7 +31,7 @@ sbt:docspell-root> reStart
```
# Custom config file
## Custom config file
The sbt build is setup such that a file `dev.conf` in the directory
`local` (at root of the source tree) is picked up as config file, if

View File

@ -3,6 +3,7 @@ title = "Translating Web-UI"
weight = 10
+++
# UI Translation
Help with translating the web-ui is greatly appreciated. I can only
provide translations for English and German, and these may be wrong -
@ -16,7 +17,7 @@ messages.
This guide assumes no knowledge about Elm at all.
# TL;DR
## TL;DR
If you are already familiar with Elm, here is the TL;DR:
@ -92,7 +93,7 @@ sbt:docspell-root> make
This will take a while, you need to wait until this is finished.
## Start the application
### Start the application
If sbt is not started, start sbt from within the source root. Also
export the `DOCSPELL_ENV` variable *before* starting sbt:

View File

@ -3,8 +3,8 @@ title = "FAQ"
weight = 100
description = "Frequently asked questions."
insert_anchor_links = "right"
template = "docs.html"
[extra]
mktoc = true
+++
# FAQ

View File

@ -1,8 +1,9 @@
+++
title = "Features and Limitations"
weight = 10
weight = 9
insert_anchor_links = "right"
description = "A list of features and limitations."
template = "docs.html"
+++
# Features
@ -20,7 +21,7 @@ description = "A list of features and limitations."
- A powerful [query language](@/docs/query/_index.md) to find
documents
- use [bookmarks](@/docs/webapp/bookmarks.md) to save more complex queries
- customizable [dashboads](@/docs/webapp/dashboards.md) as the main page
- customizable [dashboards](@/docs/webapp/dashboards.md) as the main page
- Non-destructive: all your uploaded files are never modified and can
always be downloaded untouched
- Organize files using tags, folders, [Custom
@ -80,8 +81,6 @@ description = "A list of features and limitations."
files, watch folders and many more!
- [Android App](@/docs/tools/android.md) to quickly upload files
from your android devices
- [Firefox plugin](@/docs/tools/browserext.md): right click on a
link and send the file to docspell
- [SMTP Gateway](@/docs/tools/smtpgateway.md): Setup a SMTP server
that delivers mails directly to docspell.
- License: AGPLv3

View File

@ -1,12 +1,15 @@
+++
title = "Feed Data into Docspell"
weight = 5
weight = 8
description = "Shows several ways for getting data into Docspell."
insert_anchor_links = "right"
template = "docs.html"
[extra]
mktoc = true
+++
# Documents → Docspell
One of the main goals is to stow documents away quickly.
Docspell makes no assumptions about where your documents are. It
@ -20,19 +23,19 @@ So the idea is to have most flexibility that is, it is up to you how
documents arrive. Of course, there is something prepared:
# Upload in Webapp
## Upload in Webapp
This is the simplest way, but also the least flexible. You can just
login and go to the upload page to submit files.
{{ figure(file="web-upload.png") }}
{{ figure2(light="web-upload.png", dark="web-upload_dark.png") }}
This requires to login at the webapp. Since this is complicated from
other applications, you can create custom hard-to-guess endpoints to
use with the following options.
# Scanners / Watch Directories
## Scanners / Watch Directories
If you have a (document) scanner (or think about getting one), it can
usually be configured to place scanned documents as image or PDF files
@ -54,10 +57,10 @@ your scanner is connected to your computer. This can create nice pdf
files from scanners with ADF, applying corrections and sending them to
docspell.
{{ buttonright(classes="is-primary ", href="/docs/tools/cli#watch-a-directory", text="More") }}
{{ buttonright(href="/docs/tools/cli#watch-a-directory", text="More") }}
# Android
## Android
There is an [android
client](https://github.com/docspell/android-client) provided that lets
@ -71,42 +74,40 @@ into the Share-With menu and uploads the file to Docspell.
This is especially useful to quickly upload small things like shopping
receipts.
<div class="columns is-centered">
<div class="column is-one-third">
<img src="/docs/tools/screenshot-share.jpg">
</div>
<div class="column is-one-third">
<img src="/docs/tools/screenshot-uploading.jpg">
</div>
</div>
<div class="columns is-vcentered is-centered">
<div class="column is-one-third">
<div class="grid grid-cols-2 gap-8 divide-x ">
<div class="flex items-center justify-center">
<a href="https://f-droid.org/packages/org.docspell.docspellshare">
<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"/>
alt="Get it on F-Droid"
class="w-56"
/>
</a>
</div>
<div class="column is-one-third">
Download the APK from <a href="https://github.com/docspell/android-client/releases/latest">here</a>
<div class="flex items-center justify-center text-xl">
<i class="fa fa-download mr-2"></i>
<span>
<a href="https://github.com/docspell/android-client/releases/latest">Download the APK</a>
</span>
</div>
</div>
{{ buttonright(classes="is-primary ", href="/docs/tools/android", text="More") }}
{{ buttonright(href="/docs/tools/android", text="More") }}
# Poll E-Mails
## Poll E-Mails
Your mailbox can be polled periodically to import mails. For example,
create a dedicated folder in your e-mail client and move mails in
there that you want to push to Docspell. You can then define a
recurring job, that looks into this folders and imports the mails.
{{ figure(file="scanmailbox.png") }}
{{ figure2(light="scanmailbox.png", dark="scanmailbox_dark.png") }}
{{ buttonright(classes="is-primary ", href="/docs/webapp/scanmailbox", text="More") }}
{{ buttonright(href="/docs/webapp/scanmailbox", text="More") }}
# E-Mail Server
## E-Mail Server
This is a little more involved, but can be quite nice. A SMTP server
can be setup that simply uploads incoming mails to Docspell (using
@ -120,29 +121,18 @@ part in Docspell to upload the files to the correct account.
There is a docker container prepared to get started. Click below to
read more.
{{ buttonright(classes="is-primary ", href="/docs/tools/smtpgateway", text="More") }}
{{ buttonright(href="/docs/tools/smtpgateway", text="More") }}
# Command-Line
## Command-Line
I like to use the command line, and so there is a cli that can be used
for some tasks, for example uploading files. Below is a quick demo, it
supports many more options, see the link below for details.
<div class="columns is-centered is-full-width">
<div class="column">
<script id="asciicast-427679" src="https://asciinema.org/a/427679.js" async></script>
</div>
</div>
<figure>
<script id="asciicast-427679" src="https://asciinema.org/a/427679.js" async></script>
</figure>
{{ buttonright(classes="is-primary ", href="/docs/tools/cli", text="More") }}
# Browser Extension
For Firefox, there is a browser extension that creates a context-menu
entry if you right-click on a link. It then downloads the file to your
disk and uploads it to Docspell.
{{ buttonright(classes="is-primary ", href="/docs/tools/browserext", text="More") }}
{{ buttonright(href="/docs/tools/cli", text="More") }}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@ -1,9 +1,10 @@
+++
title = "Installation and Deployment"
title = "Installation"
description = "There are multiple ways to install Docspell. This section contains detailed instructions."
weight = 30
weight = 5
sort_by = "weight"
insert_anchor_links = "right"
template = "pages.html"
template = "docs.html"
page_template = "docs.html"
redirect_to = "/docs/install/quickstart"
+++

View File

@ -3,7 +3,7 @@ title = "Docker"
weight = 20
+++
## Docker Images
# Docker Images
The docker images are at
[hub.docker.com](https://hub.docker.com/u/docspell). The `latest` tag
@ -29,7 +29,7 @@ release page. The images contain all the necessary
is used to watch a directory for uploading files. This runs the `dsc
watch` command.
### Examples
## Examples
These examples use `docker run` to start the restserver and
jobexecutor. Both must be connected to the same database. For this
@ -127,7 +127,7 @@ fulltext search. For a more sophisticated docker setup, use
appropriate tools, for example `docker-compose` which is explained
below.
## Docker Compose
# Docker Compose
There is a [docker-compose](https://docs.docker.com/compose/) setup
available in the `/docker/docker-compose` folder. This setup is
@ -135,8 +135,8 @@ similiar to the example above, but adding fulltext search and a
PostgreSQL database by using just one command. It's only a few steps
to get started.
### Start Docspell
#### 1. Get the docker-compose files
## Start Docspell
### 1. Get the docker-compose files
There are two options. You can clone the whole repository:
@ -159,7 +159,7 @@ You can choose any directory instead of
make the rest of the guide work for both ways of obtaining the
docker-compose file.
#### 2. Run `docker-compose up`
### 2. Run `docker-compose up`
Change into the new `docker-compose` directory, for example:
@ -210,7 +210,7 @@ command:
to the service definition (or add it to an existing `command:`
section).
### Override this setup
## Override this setup
If you want to change this setup, you can simply use your own compose
file or add a `docker-compose.override.yml` that allows to amend
@ -251,7 +251,7 @@ volumes:
```
### Upgrading
## Upgrading
Since [downgrading](@/docs/install/downgrading.md) is not supported,
it is recommended to backup your database before upgrading. Should
@ -267,7 +267,7 @@ $ docker-compose pull
$ docker-compose up --force-recreate --build -d
```
### Backups
## Backups
When running the docker compose setup, you can use the following to
backup the database.

View File

@ -3,7 +3,9 @@ title = "Downgrading"
weight = 37
+++
{% infobubble(mode="info", title="⚠ Please note") %}
# Downgrading
{% warningbubble(title="Note") %}
Downgrading is currently not supported!
It is not safe to install a previous version, because the database

View File

@ -3,24 +3,23 @@ title = "Download & Run"
weight = 22
+++
# Download and Run
You can install via zip or deb archives. Please see the
[prerequisites](@/docs/install/prereq.md) first.
## Using zip files
You need to download the two files:
- [docspell-restserver-{{version()}}.zip](https://github.com/eikek/docspell/releases/download/v{{version()}}/docspell-restserver-{{version()}}.zip)
- [docspell-joex-{{version()}}.zip](https://github.com/eikek/docspell/releases/download/v{{version()}}/docspell-joex-{{version()}}.zip)
1. Unzip both files:
1. Download the two files:
- <a href="https://github.com/eikek/docspell/releases/download/v{{version()}}/docspell-restserver-{{version()}}.zip">docspell-restserver-{{version()}}.zip</a>
- <a href="https://github.com/eikek/docspell/releases/download/v{{version()}}/docspell-joex-{{version()}}.zip">docspell-joex-{{version()}}.zip</a>
2. Unzip both files:
``` bash
$ unzip docspell-*.zip
```
2. Open two terminal windows and navigate to the the directory
3. Open two terminal windows and navigate to the the directory
containing the zip files.
3. Start both components executing:
4. Start both components executing:
``` bash
$ ./docspell-restserver*/bin/docspell-restserver
```
@ -29,8 +28,8 @@ You need to download the two files:
$ ./docspell-joex*/bin/docspell-joex
```
in the other.
4. Point your browser to: <http://localhost:7880/app>
5. Register a new account, sign in and try it.
5. Point your browser to: <http://localhost:7880/app>
6. Register a new account, sign in and try it.
Note, that this setup doesn't include watching a directory nor
fulltext search. Using zip/deb files requires to take care of the
@ -64,7 +63,7 @@ extracted and installed manually somewhere in your `$PATH`. There are
no deb files provided.
## Running
# Running
Run the start script (in the corresponding `bin/` directory when using
the zip files):

View File

@ -3,6 +3,7 @@ title = "Nix / NixOS"
weight = 24
+++
# Nix
## Install via Nix
@ -73,7 +74,7 @@ back to the previous version.
When using the provided nix setup, the `currentPkg` always points to
the latest release. Thus it is enough to run `nix-build`.
## Docspell on NixOS {#nixos}
# Docspell on NixOS {#nixos}
If you are running [NixOS](https://nixos.org), there is a module
definition for installing Docspell as a service using systemd.
@ -141,7 +142,7 @@ The modules files are only applicable to the newest version of
Docspell. If you really need an older version, checkout the
appropriate commit.
### NixOS Example
## NixOS Example
This is a example system configuration that installs docspell with a
postgres database. This snippet can be used to create a vm (using

View File

@ -3,6 +3,8 @@ title = "Prerequisites"
weight = 10
+++
# Prerequisites
The two components have one prerequisite in common: they both require
Java to run. While this is the only requirement for the *REST server*,
the *Joex* components requires some more external programs.
@ -10,7 +12,7 @@ the *Joex* components requires some more external programs.
The rest server and joex components are not required to "see" each
other, though it is recommended.
# Java
## Java
Very often, Java is already installed. You can check this by opening a
terminal and typing `java -version`. Otherwise install Java using your
@ -28,7 +30,7 @@ works on newer java versions. The provided docker images use JDK11.
The next tools are only required on machines running the *Joex*
component.
# External Programs for Joex
## External Programs for Joex
- [Ghostscript](http://pages.cs.wisc.edu/~ghost/) (the `gs` command)
is used to extract/convert PDF files into images that are then fed
@ -57,7 +59,7 @@ The performance of `unoconv` can be improved by starting `unoconv -l`
in a separate process. This runs a libreoffice/openoffice listener and
therefore avoids starting one each time `unoconv` is called.
## Example Debian
### Example Debian
On Debian this should install all joex requirements:

View File

@ -1,8 +1,10 @@
+++
title = "Quickstart"
title = "Getting started"
weight = 0
+++
# Getting started
To get started, here are some quick links:
- Using [docker and docker-compose](@/docs/install/docker.md). This
@ -28,7 +30,7 @@ To get started, here are some quick links:
thread](https://forums.unraid.net/topic/103425-docspell-hilfe/) in
the German Unraid forum. Thanks for providing these!
Every [component](@/docs/intro/_index.md#components) (restserver,
Every [component](@/docs/_index.md#components) (restserver,
joex, dsc watch) can run on different machines and multiple times.
Most of the time running all on one machine is sufficient and also for
simplicity, the docker-compose setup reflects this variant.
@ -39,7 +41,7 @@ file](@/docs/configure/_index.md). If this is not given, the default
is used, which gets you started on a single machine, but it is very
likely you want to change these to match your use-case/setup.
{% infobubble(mode="info", title="⚠ Please note") %}
{% infobubble(title="Note") %}
Please have a look at the [configuration page](/docs/configure/) page,
before making docspell publicly available. By default, everyone can

View File

@ -3,6 +3,8 @@ title = "Reverse Proxy"
weight = 50
+++
# Reverse Proxy
This contains examples for how to use docspell behind a reverse proxy.
For the examples below, assume the following:

View File

@ -1,8 +1,10 @@
+++
title = "Raspberry-Pi and Similiar"
title = "Raspberry-Pi"
weight = 40
+++
# Raspberry Pi
Both components can run next to each other on a raspberry pi or
similiar device.

View File

@ -3,149 +3,8 @@ title = "Introduction"
weight = 0
description = "Gives a short introduction to the goals of docspell and an overview of the components involved."
insert_anchor_links = "right"
redirect_to = "/docs/"
[extra]
mktoc = true
hidden = true
+++
# Introduction
Docspell aims to be a simple yet effective document organizer that
makes stowing documents away very quick and finding them later
reliable (and also fast). It is a bit opinionated and more targeted
for home use and small/medium organizations.
In contrast to many DMS, the main focus is not so much to provide all
kinds of features to manually create organizational structures, like
folder hierarchies, where you place the documents yourself. The
approach is to leave it as a big pile of documents, but extract and
attach metadata from each document. These are mainly properties that
emerge from the document itself. The reason is that this is possible
to automate. This makes it very simple to *add* documents, because
there is no time spent to think about where to put it. And it is
possible to apply different structures on top later, like show first
all documents of a specific correspondent, then all with tag
'invoice', etc. If these properties are attached to all documents, it
is really easy to find a document. It even can be combined with
fulltext search for the, hopefully rare, desperate cases.
Of course, it is also possible to add custom properties and arbitrary
tags.
Docspell analyzes the text to find metadata automatically. It can
learn from existing data and can apply
[NLP](https://en.wikipedia.org/wiki/Natural_language_processing)
techniques to support this. This metadata must be maintained manually
in the application. Docspell looks for candidates for:
- Correspondents
- Concerned person or things
- A date and due date
- Tags
For tags, it sets all that it thinks do apply. For the others, it will
propose a few candidates and sets the most likely one to your item.
This might be wrong, so it is recommended to curate the results.
However, very often the correct one is either set or within the
proposals where you fix it by a single click.
Besides these properties, there are more metadata you can use to
organize your files, for example custom fields, folders and notes.
Docspell is also for programmers. Everything is available via a REST
or HTTP api and can be easily used within your own scripts and tools,
for example using `curl`. There are also features for "advanced use"
and many configuration options.
# Components
Docspell consists of multiple components that run in separate
processes:
- REST server
- JOEX, short for *job executor*
- Fulltext Search Index (optional, currently Apache SOLR)
The REST server provides the Api and the web application. The web
application is a
[SPA](https://en.wikipedia.org/wiki/Single-page_application) written
in [Elm](https://elm-lang.org) and is a client to the REST api. All
features are available via a http/rest api.
The *joex* is the component that does the “heavy work”, executing
long-running tasks, like processing files or importing your mails
periodically. While the joex component also exposes a small REST api
for controlling it, the main user interface is all inside the rest
server api.
The rest server and the job executor can be started multiple times in
order to scale out. It must be ensured, that all connect to the same
database. And it is also recommended (though not strictly required),
that all components can reach each other.
The fulltext search index is another separate component, where
currently only [SOLR](https://solr.apache.org) is supported.
Fulltext search is optional, so the SOLR component is not required if
docspell is run without fulltext search support.
# Terms
In order to better understand the following pages, some terms are
explained.
## Item
An *item* is roughly your document, only that an item may span
multiple files, which are called *attachments*. An item has *meta
data* associated:
- a *correspondent*: the other side of the communication. It can be
an organization or a person.
- a *concerning person* or *equipment*: a person or thing that
this item is about. Maybe it is an insurance contract about your
car.
- *tag*: an item can be tagged with one or more tags (or labels). A
tag can have a *category*. This is intended for grouping tags, for
example a category `doctype` could be used to group tags like
`bill`, `contract`, `receipt` etc. Usually an item is not tagged
with more than one tag of a category.
- a *folder*: a folder is similiar to a tag, but an item can only be
in exactly one folder (or none). Furthermore folders allow to
associate users, so that items are only visible to the users who are
members of a folder.
- an *item date*: this is the date of the document if this is not
set, the created date of the item is used.
- a *due date*: an optional date indicating that something has to be
done (e.g. paying a bill, submitting it) about this item until this
date
- a *direction*: one of "incoming" or "outgoing"
- a *name*: some item name, defaults to the file name of the
attachments
- some *notes*: arbitrary descriptive text. You can use markdown
here, which is properly formatted in the web application.
## Collective
The users of the application are part of a *collective*. A
*collective* is a group of users that share access to the same
items. The account name is therefore comprised of a *collective name*
and a *user name*.
All users of a collective are equal; they have same permissions to
access all items. The items don't belong to a user, but to the
collective.
That means, to identify yourself when signing in, you have to give the
collective name and your user name. By default it is separated by a
slash `/`, for example `smith/john`. If your user name is the same as
the collective name, you can omit one; so `smith/smith` can be
abbreviated to just `smith`.
By default, all users can see all items of their collective. A
*folder* can be used to implement other visibilities: Every user can
create a folder and associate members. It is possible to put items in
these folders and docspell shows only items that are either in no
specific folder or in a folder where the current user is owner or
member.

View File

@ -7,6 +7,8 @@ insert_anchor_links = "right"
mktoc = true
+++
# File Processing
When uploading a file, it is only saved to the database together with
the given meta information as a "job". The file is not visible in the
ui yet. Then joex takes the next such job and starts processing it.
@ -319,7 +321,7 @@ docspell.joex {
}
```
{% infobubble(mode="warning", title="Please note") %}
{% warningbubble(title="Please note") %}
When this is changed, you must re-generate all preview images. Check
the api for this, there is an endpoint to regenerate all preview

View File

@ -7,7 +7,8 @@ insert_anchor_links = "right"
mktoc = true
+++
# Introduction
# Joex
## Introduction
Joex is short for *Job Executor* and it is the component managing long
running tasks in docspell. One of these long running tasks is the file
@ -30,7 +31,7 @@ compete on getting the next job from the queue. After a job finishes
and no job is waiting in the queue, joex will sleep until notified
again. It will also periodically notify itself as a fallback.
# Task vs Job
## Task vs Job
Just for the sake of this document, a task denotes the code that has
to be executed or the thing that has to be done. It emerges in a job,
@ -39,7 +40,7 @@ up and executed eventually. A job maintains a state and other things,
while a task is just code.
# Scheduler and Queue
## Scheduler and Queue
The scheduler is the part that runs and monitors the long running
jobs. It works together with the job queue, which defines what job to
@ -62,7 +63,7 @@ logged in, jobs are more important that those submitted when not
logged in.
# Scheduler Config
## Scheduler Config
The relevant part of the config file regarding the scheduler is shown
below with some explanations.
@ -130,7 +131,7 @@ reach a joex component. This periodic wakup is just to ensure that
jobs are eventually run.
# Periodic Tasks
## Periodic Tasks
The job executor can execute tasks periodically. These tasks are
stored in the database such that they can be submitted into the job
@ -139,7 +140,7 @@ something with a task. So a periodic task is never submitted twice. It
is also not submitted, if a previous task has not finished yet.
# Starting on demand
## Starting on demand
The job executor and rest server can be started multiple times. This
is especially useful for the job executor. For example, when
@ -154,7 +155,7 @@ Once the files have been processced you can stop the additional
executors.
# Shutting down
## Shutting down
If a job executor is sleeping and not executing any jobs, you can just
quit using SIGTERM or `Ctrl-C` when running in a terminal. But if

View File

@ -1,10 +1,15 @@
+++
title = "JSON (mini) query"
weight = 58
template = "docs.html"
page_template = "docs.html"
[extra]
mktoc = true
hidden = true
+++
# JSON Miniquery
A "JSON mini query" is a simple expression that evaluates to `true` or
`false` for any given JSON value.

View File

@ -3,15 +3,14 @@ title = "Query Language"
weight = 55
description = "The query language is a powerful way to search for documents."
insert_anchor_links = "right"
[extra]
mktoc = true
template = "docs.html"
+++
# Query Language
Docspell uses a query language to provide a powerful way to search for
your documents. It is targeted at "power users" and it needs to be
enabled explicitely in your user settings to be used on the search
page.
your documents. It currently needs to be enabled explicitely in your
user settings to be used on the search page.
<div class="colums">

View File

@ -6,6 +6,4 @@ insert_anchor_links = "right"
template = "pages.html"
redirect_to = "docs/tools/cli/"
sort_by = "weight"
[extra]
mktoc = false
+++

View File

@ -10,17 +10,22 @@ There is a simple Android App available to conveniently upload files
from your android devices. Combined with a scanner app, this allows to
very quickly scan single page documents like receipts.
<div class="columns is-vcentered is-centered">
<div class="column">
<div class="grid grid-cols-2 gap-8 divide-x ">
<div class="flex items-center justify-center">
<a href="https://f-droid.org/packages/org.docspell.docspellshare">
<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
style="height:120px;"/>
class="w-56"
/>
</a>
</div>
<div class="column">
Download the APK from <a href="https://github.com/docspell/android-client/releases/latest">here</a>
<div class="flex items-center justify-center text-xl">
<i class="fa fa-download mr-2"></i>
<span>
<a href="https://github.com/docspell/android-client/releases/latest">Download the APK</a>
</span>
</div>
</div>
@ -43,32 +48,30 @@ The app is very simple:
- You can now either select an URL from the app, or the upload begins
immediatly if you set a default URL.
<div class="columns">
<div class="column">
<div class="grid grid-cols-3 gap-4 mx-6 my-4">
<div class="shadow dark:shadow-stone-600">
{{ imgnormal(file="screenshot-create.jpg", width="") }}
<p class="has-text-centered subtitle"> (A) </p>
<p class="text-center font-mono"> (A) </p>
</div>
<div class="column">
<div class="box-shadow">
{{ imgnormal(file="screenshot-choose.jpg", width="") }}
<p class="has-text-centered subtitle"> (B) </p>
<p class="text-center font-mono"> (B) </p>
</div>
<div class="column">
<div class="box-shadow">
{{ imgnormal(file="screenshot-options.jpg", width="") }}
<p class="has-text-centered subtitle"> (C) </p>
<p class="text-center font-mono"> (C) </p>
</div>
</div>
<div class="columns">
<div class="column">
<div class="box-shadow">
{{ imgnormal(file="screenshot-default.jpg", width="") }}
<p class="has-text-centered subtitle"> (D) </p>
<p class="text-center font-mono"> (D) </p>
</div>
<div class="column">
<div class="box-shadow">
{{ imgnormal(file="screenshot-share.jpg", width="") }}
<p class="has-text-centered subtitle"> (E) </p>
<p class="text-center font-mono"> (E) </p>
</div>
<div class="column">
<div class="box-shadow">
{{ imgnormal(file="screenshot-uploading.jpg", width="") }}
<p class="has-text-centered subtitle"> (F) </p>
<p class="text-center font-mono"> (F) </p>
</div>
</div>

View File

@ -1,84 +0,0 @@
+++
title = "Browser Extension (Firefox)"
description = "An extension for firefox to upload files from your browser via right-click → upload to docspell."
weight = 40
+++
The idea is to click on a file in firefox and send it to docspell. It
is downloaded in the context of your current page. Then handed to an
application that pushes it to docspell. There is a browser add-on
implementing this in `tools/webextension`. This add-on only works with
firefox.
Installation is a bit complicated, since you need to install external
tools and the web extension. Both work together.
# Install `dsc`
First copy the [dsc](@/docs/tools/cli.md) tool somewhere in your
`PATH`, maybe `/usr/local/bin`.
# Install the native part
Then install the "native" part of the web extension:
Copy or symlink the `native.py` script into some known location. For
example:
``` bash
ln -s ~/docspell-checkout/tools/webextension/native/native.py /usr/local/share/docspell/native.py
```
Then copy the `app_manifest.json` to
`$HOME/.mozilla/native-messaging-hosts/docspell.json`. For example:
``` bash
cp ~/docspell-checkout/tools/webextension/native/app_manifest.json ~/.mozilla/native-messaging-hosts/docspell.json
```
See
[here](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#manifest_location)
for details.
And you might want to modify this json file, so the path to the
`native.py` script is correct (it must be absolute).
If the `dsc` tool is in your `$PATH`, then this should work. You need
to provide a default source id in your `~/.config/dsc/config.toml` so
that the upload command can be used without further arguments.
Otherwise, edit the `native.py` script and change the path to the tool
and/or the arguments. Or create a file
`$HOME/.config/docspell/dsc.cmd` whose content is the path to the
`dsc` tool.
# Install the extension
An extension file can be build using the `make-xpi.sh` script. But
installing it in "standard" firefox won't work, because [Mozilla
requires extensions to be signed by
them](https://wiki.mozilla.org/Add-ons/Extension_Signing). This means
creating an account and going through some process…. So here are two
alternatives:
1. Open firefox and type `about:debugging` in the addressbar. Then
click on *'Load Temporary Add-on...'* and select the
`manifest.json` file. The extension is now installed. The downside
is, that the extension will be removed once firefox is closed.
2. Use Firefox ESR, which allows to install Add-ons not signed by
Mozilla. But it has to be configured: Open firefox and type
`about:config` in the address bar. Search for key
`xpinstall.signatures.required` and set it to `false`. This is
described on the last paragraph on [this
page](https://support.mozilla.org/en-US/kb/add-on-signing-in-firefox).
When you right click on a file link, there should be a context menu
entry *'Docspell Upload Helper'*. The add-on will download this file
using the browser and then send the file path to the `native.py`
script. This script will in turn call `dsc` which finally uploads it
to your configured URLs.
Open the Add-ons page (`Ctrl`+`Shift`+`A`), the new add-on should be
there.

View File

@ -4,7 +4,8 @@ description = "A command line interface to."
weight = 5
+++
# Introduction
# Docspell CLI
## Introduction
The **d**oc**s**pell **c**lient, short
[dsc](https://github.com/docspell/dsc), is a tool to use
@ -17,7 +18,7 @@ directory.
It is a work in progress; eventually most of the
[api](@/docs/api/_index.md) will be covered.
# Usage
## Usage
Download the binary for your architecture from the [release
page](https://github.com/docspell/dsc/releases/latest) and rename it
@ -86,11 +87,9 @@ you need to `login` again.
## Demo
<div class="columns is-centered is-full-width">
<div class="column">
<script id="asciicast-427679" src="https://asciinema.org/a/427679.js" async></script>
</div>
</div>
<figure>
<script id="asciicast-427679" src="https://asciinema.org/a/427679.js" async></script>
</figure>
# Use Cases / Examples

View File

@ -4,7 +4,9 @@ description = "Import your data from paperless."
weight = 60
+++
# Introduction
# Import from Paperless
## Introduction
Coming from
[paperless](https://github.com/the-paperless-project/paperless/), the
@ -15,7 +17,7 @@ importing your data from paperless into docspell.
The script imports the files and also tags and correspondents.
{% infobubble(mode="info", title="⚠ Please note") %}
{% infobubble(title="Note") %}
The script was written some while ago. It currently doesn't work out
of the box, but is a good starting point as the issues are most
@ -25,7 +27,7 @@ issue](https://github.com/eikek/docspell/issues/1241).
{% end %}
# Usage
## Usage
Copy the script to the machine where paperless is running. Run it with
the following arguments:

View File

@ -4,6 +4,8 @@ description = "Start a SMTP server that forwards all mails to docspell."
weight = 50
+++
# SMTP Gateway with Exim
One possible use case for the [integration
endpoint](@/docs/api/upload.md#integration-endpoint) is a SMTP server
that forwards all local mail to docspell. This way there is no

View File

@ -5,6 +5,7 @@ weight = 90
mktoc = true
+++
# Auto-Tagging
Auto-Tagging must be enabled in the collective profile. Docspell can
go through your items periodically and learn from your existing tags.
@ -20,7 +21,7 @@ determined by looking at the text of the document. It would mean that
Docspell could learn relationships that are not correct and then tag
the next incoming items with `Done`.
{{ figure(file="collective-settings-autotag.png") }}
{{ figure2(light="collective-settings-autotag.png", dark="collective-settings-autotag_dark.png") }}
That is why you need to specify what tags to learn. This is done by
defining whitelist or a blacklist of tag categories. When defining a

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -5,6 +5,8 @@ weight = 35
mktoc = true
+++
# Bookmarks
Bookmarks allow you to save queries under a name and refer to it from the search menu.
## Creating bookmarks
@ -12,13 +14,13 @@ Bookmarks allow you to save queries under a name and refer to it from the search
Bookmarks can be created from the search view. Apply some criteria to
select items and then click on the top left menu.
{{ figure(file="bookmarks-02.png") }}
{{ figure2(light="bookmarks-02.png", dark="bookmarks-02_dark.png") }}
This opens a small form right below the search bar where you can
adjust the query and enter the name. You can also decide whether this
bookmark is for all users or just for you.
{{ figure(file="bookmarks-03.png") }}
{{ figure2(light="bookmarks-03.png", dark="bookmarks-03_dark.png") }}
The other way is to go to *Manage Data* where you can edit and delete
existing bookmarks and also create new ones.
@ -31,8 +33,8 @@ that shows you all your bookmarks as well as your shares. Clicking one
"enables" it, meaning the query is used in conjunction with other
criteria.
<div class="columns is-centered">
{{ imgnormal(file="bookmarks-01.png", width="") }}
<div class="flex items-center justify-center">
{{ imgnormal2(light="bookmarks-01.png", dark="bookmarks-01_dark.png", width="") }}
</div>
An active bookmark has a check icon next to its name.
@ -47,7 +49,7 @@ registered users), expired shares are shown as well.
The *Manage Data* page has a section for bookmarks. There you can
delete and edit bookmarks.
{{ figure(file="bookmarks-04.png") }}
{{ figure2(light="bookmarks-04.png", dark="bookmarks-04_dark.png") }}
The personal bookmarks are only visible to you. The collective
bookmarks are visible to every user in the collective, which also

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

View File

@ -3,11 +3,13 @@ title = "Curate Items"
weight = 20
+++
# Curate items
Curating the items meta data helps finding them later. This page
describes how you can quickly go through those items and correct or
amend with existing data.
# Select New items
## Select New items
After files have been uploaded and the job executor created the
corresponding items, they will show up on the main page. All items the
@ -15,14 +17,14 @@ job executor has just created are initially marked as *New*. The
option *Inbox* in the left search menu can be used to select only new
items:
{{ figure(file="docspell-curate-1.png") }}
{{ figure2(light="docspell-curate-1.png", dark="docspell-curate-1_dark.png") }}
Then you can go through all new items and check their metadata: Click
on the first item to open the detail view. This shows the documents
and the meta data in the header.
# Modify if necessary
## Modify if necessary
You can compare the data with the documents and change as you like.
Since the item status is *New*, you'll see the suggestions docspell
@ -31,7 +33,7 @@ select another one by clicking its name in the suggestion list. In
state *New* the left menu is fully expanded so you see all suggestions
immediatly.
{{ figure(file="docspell-curate-3.png") }}
{{ figure2(light="docspell-curate-3.png", dark="docspell-curate-3_dark.png") }}
When you change something in the form, it is immediatly applied.
@ -39,13 +41,11 @@ When you change something in the form, it is immediatly applied.
It is also possible to change tags and folders in the list view via
drag&drop.
<div class="columns is-centered">
<div class="column is-narrow">
{{ imgnormal(file="drop-tag.png", width="500px") }}
</div>
<div class="flex items-center justify-center">
{{ imgnormal2(light="drop-tag.png", dark="drop-tag_dark.png", width="500px") }}
</div>
# Confirm
## Confirm
If everything looks good, click the *Confirm* button to confirm the
current data. The *New* status goes away and also the suggestions are
@ -54,10 +54,10 @@ before. You can always go back by clicking the *Unconfirm* button at
the right of the menu bar.
{{ figure(file="docspell-curate-5.png") }}
{{ figure2(light="docspell-curate-5.png", dark="docspell-curate-5_dark.png") }}
# Proceed with next item
## Proceed with next item
To look at the next item in the search results, click the *Next*
button in the menu (next to the *Edit* button). Clicking next, will
@ -65,4 +65,4 @@ keep the current view, so you can continue checking the data. If you
are on the last item, the view switches to the listing view when
clicking *Next*.
{{ figure(file="docspell-curate-6.png") }}
{{ figure2(light="docspell-curate-6.png", dark="docspell-curate-6_dark.png") }}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View File

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -3,6 +3,8 @@ title = "Custom Fields"
weight = 18
+++
# Custom Fields
Custom fields allow to attach user defined metadata to items. For
example, you may want to track the amount of each receipt or the
invoice number etc. You can define fields that can be associated to
@ -15,7 +17,7 @@ Custom fields can be deactivated in the user settings.
Go to the _Manage Data_ page, that can be reached from the top right
menu. One entry at the left shows _Custom Fields_:
{{ figure(file="custom-fields-01.png") }}
{{ figure2(light="custom-fields-01.png", dark="custom-fields-01_dark.png") }}
Fields are defined per collective. They can also be created in the
item edit menu (just like creating organizations). The `#Usage`
@ -23,7 +25,7 @@ columns show how many items have a value for this field.
A field consists of a name, a format and optional a label:
{{ figure(file="custom-fields-02.png") }}
{{ figure2(light="custom-fields-02.png", dark="custom-fields-02_dark.png") }}
The name and format is required. The name must be unique among all
your fields and it is special in that it must be a valid _identifier_:
@ -73,7 +75,7 @@ corresponding input field is shown asking for values. You can select
multiple fields. Only one value is allowed to set per item and field.
The example below shows a text field and a money field:
{{ figure(file="custom-fields-03.png") }}
{{ figure2(light="custom-fields-03.png", dark="custom-fields-03_dark.png") }}
You can create new fields right here without going to the _Manage
Data_ page, by clicking the plus icon (1). The format of each field is
@ -83,14 +85,13 @@ As soon as a correct value is typed in, it is saved to the item and
shown in the header next to the tags. If you click the trash-can icon
next to an input, the value is removed from the item.
{{ figure(file="custom-fields-04.png") }}
{{ figure2(light="custom-fields-04.png", dark="custom-fields-04_dark.png") }}
The item card also shows custom fields, in the same place as tags:
<div class="columns is-centered">
<div class="column is-one-quarter">
{{ imgnormal(file="custom-fields-05.png", width=300) }}
</div>
<div class="flex flex-row items-center justify-center">
{{ imgnormal2(light="custom-fields-05.png", dark="custom-fields-05_dark.png", width=300) }}
</div>
Adding values for custom fields in
@ -102,13 +103,13 @@ Adding values for custom fields in
The search menu shows the same dropdown for selecting a custom field.
Then you can set values that are matched against your items.
{{ figure(file="custom-fields-06.png") }}
{{ figure2(light="custom-fields-06.png", dark="custom-fields-06_dark.png") }}
Values are also validated in the search form. Only valid values are
sent to the server for searching. There is one exception: you can use
a wildcard at beginning and/or end to do a substring match:
{{ figure(file="custom-fields-07.png") }}
{{ figure2(light="custom-fields-07.png", dark="custom-fields-07_dark.png") }}
For all numeric and money values, a little summary is displayed next
to the overall item count at the top of the page.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

View File

@ -5,18 +5,20 @@ weight = 5
mktoc = true
+++
# Dashboards
The main page shows a dashboard that can be configured to show some
aspects of your documents. The following shows the default dashboard
that is bundled in the application:
{{ figure(file="dashboards-01.png") }}
{{ figure2(light="dashboards-01.png", dark="dashboards-01_dark.png") }}
It shows a predefined set of information, which can be customized. You
can create multiple dashboards and switch between them, you can also
define one as the "default" which is shown when the page loads.
# Side menu
## Side menu
The side menu contains a list of useful links. The first loads the
default dashboard. All others (and more) are available through the
@ -29,7 +31,7 @@ The _Settings_ section contains some links to useful settings and the
_Manage_ section has links to metadata that can be managed separately.
These links are fixed and cannot be changed.
# Dasbhoard properties
## Dasbhoard properties
The main component on this page is the "dashboard". A dashboard has
the following properties (all required):
@ -57,7 +59,7 @@ removing boxes and the dashboard properties.
After clicking _Edit Dashboard_ the dashboard changes into a form:
{{ figure(file="dashboards-02.png") }}
{{ figure2(light="dashboards-02.png", dark="dashboards-02_dark.png") }}
Note the message on the top: it indicates that this dashboard is the
bundled one that is used only if there are no custom ones available.
@ -72,19 +74,19 @@ reorder the boxes using the arrow buttons or drag and drop. When
satisfied, click _Submit_. In the example, the last two boxes are
removed and box decorations are enabled for the field overview box.
{{ figure(file="dashboards-03.png") }}
{{ figure2(light="dashboards-03.png", dark="dashboards-03_dark.png") }}
When you now edit this dasbhoard again, the message is gone and you
can change the dashboard and also delete it. You can also create a new
dashboard or copy the current one.
{{ figure(file="dashboards-04.png") }}
{{ figure2(light="dashboards-04.png", dark="dashboards-04_dark.png") }}
In this example, the dashboard was copied, then the message was
changed and it was set to the default dashboard. This is how it looks
now:
{{ figure(file="dashboards-05.png") }}
{{ figure2(light="dashboards-05.png", dark="dashboards-05_dark.png") }}
When there is more than one dashboard, the side menu shows all of
them. The little house icon indicates whether this is the default

View File

Before

Width:  |  Height:  |  Size: 169 KiB

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Some files were not shown because too many files have changed in this diff Show More