diff --git a/build.sbt b/build.sbt index 4188df7a..2e43f5c9 100644 --- a/build.sbt +++ b/build.sbt @@ -92,11 +92,11 @@ def webjarSettings(queryJS: Project) = Seq( }.taskValue, Compile / resourceGenerators += Def.task { val logger = streams.value.log - val out = (queryJS/Compile/fullOptJS).value + val out = (queryJS / Compile / fullOptJS).value logger.info(s"Produced query js file: ${out.data}") copyWebjarResources( Seq(out.data), - (Compile/resourceManaged).value, + (Compile / resourceManaged).value, name.value, version.value, logger @@ -218,7 +218,9 @@ val openapiScalaSettings = Seq( field.copy(typeDef = TypeDef("OrgUse", Imports("docspell.common.OrgUse"))) case "equipmentuse" => field => - field.copy(typeDef = TypeDef("EquipmentUse", Imports("docspell.common.EquipmentUse"))) + field.copy(typeDef = + TypeDef("EquipmentUse", Imports("docspell.common.EquipmentUse")) + ) })) ) diff --git a/modules/analysis/src/test/scala/docspell/analysis/classifier/StanfordTextClassifierSuite.scala b/modules/analysis/src/test/scala/docspell/analysis/classifier/StanfordTextClassifierSuite.scala index 1fcf5e81..2e483b2a 100644 --- a/modules/analysis/src/test/scala/docspell/analysis/classifier/StanfordTextClassifierSuite.scala +++ b/modules/analysis/src/test/scala/docspell/analysis/classifier/StanfordTextClassifierSuite.scala @@ -1,14 +1,18 @@ package docspell.analysis.classifier -import munit._ -import cats.effect._ -import scala.concurrent.ExecutionContext import java.nio.file.Paths -import cats.data.NonEmptyList -import docspell.common._ -import fs2.Stream + +import scala.concurrent.ExecutionContext + import cats.data.Kleisli -import TextClassifier.Data +import cats.data.NonEmptyList +import cats.effect._ +import fs2.Stream + +import docspell.analysis.classifier.TextClassifier.Data +import docspell.common._ + +import munit._ class StanfordTextClassifierSuite extends FunSuite { val logger = Logger.log4s[IO](org.log4s.getLogger) diff --git a/modules/analysis/src/test/scala/docspell/analysis/contact/ContactAnnotateSpec.scala b/modules/analysis/src/test/scala/docspell/analysis/contact/ContactAnnotateSpec.scala index 106dad9e..f9f5d9e4 100644 --- a/modules/analysis/src/test/scala/docspell/analysis/contact/ContactAnnotateSpec.scala +++ b/modules/analysis/src/test/scala/docspell/analysis/contact/ContactAnnotateSpec.scala @@ -1,6 +1,7 @@ package docspell.analysis.contact import docspell.common.{NerLabel, NerTag} + import munit._ class ContactAnnotateSpec extends FunSuite { diff --git a/modules/analysis/src/test/scala/docspell/analysis/date/DateFindSpec.scala b/modules/analysis/src/test/scala/docspell/analysis/date/DateFindSpec.scala index 3711434f..6d014868 100644 --- a/modules/analysis/src/test/scala/docspell/analysis/date/DateFindSpec.scala +++ b/modules/analysis/src/test/scala/docspell/analysis/date/DateFindSpec.scala @@ -1,10 +1,12 @@ package docspell.analysis.date -import docspell.files.TestFiles -import munit._ -import docspell.common._ import java.time._ +import docspell.common._ +import docspell.files.TestFiles + +import munit._ + class DateFindSpec extends FunSuite { test("find simple dates") { diff --git a/modules/analysis/src/test/scala/docspell/analysis/nlp/BaseCRFAnnotatorSuite.scala b/modules/analysis/src/test/scala/docspell/analysis/nlp/BaseCRFAnnotatorSuite.scala index 340359e1..e760532f 100644 --- a/modules/analysis/src/test/scala/docspell/analysis/nlp/BaseCRFAnnotatorSuite.scala +++ b/modules/analysis/src/test/scala/docspell/analysis/nlp/BaseCRFAnnotatorSuite.scala @@ -2,9 +2,10 @@ package docspell.analysis.nlp import docspell.analysis.Env import docspell.common.Language.NLPLanguage -import munit._ -import docspell.files.TestFiles import docspell.common._ +import docspell.files.TestFiles + +import munit._ class BaseCRFAnnotatorSuite extends FunSuite { diff --git a/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala b/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala index 46bcb841..4938c45b 100644 --- a/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala +++ b/modules/analysis/src/test/scala/docspell/analysis/nlp/StanfordNerAnnotatorSuite.scala @@ -3,12 +3,14 @@ package docspell.analysis.nlp import java.nio.file.Paths import cats.effect.IO + import docspell.analysis.Env -import munit._ -import docspell.files.TestFiles import docspell.common._ import docspell.common.syntax.FileSyntax._ +import docspell.files.TestFiles + import edu.stanford.nlp.pipeline.StanfordCoreNLP +import munit._ class StanfordNerAnnotatorSuite extends FunSuite { lazy val germanClassifier = diff --git a/modules/common/src/test/scala/docspell/common/GlobTest.scala b/modules/common/src/test/scala/docspell/common/GlobTest.scala index be20b9ba..90408ceb 100644 --- a/modules/common/src/test/scala/docspell/common/GlobTest.scala +++ b/modules/common/src/test/scala/docspell/common/GlobTest.scala @@ -1,7 +1,8 @@ package docspell.common +import docspell.common.Glob._ + import munit._ -import Glob._ class GlobTest extends FunSuite { diff --git a/modules/common/src/test/scala/docspell/common/LenientUriTest.scala b/modules/common/src/test/scala/docspell/common/LenientUriTest.scala index 1d814791..5e3e0c97 100644 --- a/modules/common/src/test/scala/docspell/common/LenientUriTest.scala +++ b/modules/common/src/test/scala/docspell/common/LenientUriTest.scala @@ -1,6 +1,7 @@ package docspell.common import cats.implicits._ + import munit._ class LenientUriTest extends FunSuite { diff --git a/modules/common/src/test/scala/docspell/common/MetaProposalListTest.scala b/modules/common/src/test/scala/docspell/common/MetaProposalListTest.scala index fd705510..fdee5937 100644 --- a/modules/common/src/test/scala/docspell/common/MetaProposalListTest.scala +++ b/modules/common/src/test/scala/docspell/common/MetaProposalListTest.scala @@ -1,9 +1,11 @@ package docspell.common -import munit._ import cats.data.NonEmptyList + import docspell.common.MetaProposal.Candidate +import munit._ + class MetaProposalListTest extends FunSuite { test("flatten retains order of candidates") { diff --git a/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala b/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala index f0ce80a4..8528d25f 100644 --- a/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala +++ b/modules/convert/src/test/scala/docspell/convert/ConversionTest.scala @@ -3,16 +3,18 @@ package docspell.convert import java.nio.file.Paths import cats.data.Kleisli -import cats.implicits._ import cats.effect.IO +import cats.implicits._ import fs2.Stream + import docspell.common._ import docspell.convert.ConversionResult.Handler +import docspell.convert.extern.OcrMyPdfConfig import docspell.convert.extern.{TesseractConfig, UnoconvConfig, WkHtmlPdfConfig} import docspell.convert.flexmark.MarkdownConfig import docspell.files.{ExampleFiles, TestFiles} + import munit._ -import docspell.convert.extern.OcrMyPdfConfig class ConversionTest extends FunSuite with FileChecks { val blocker = TestFiles.blocker diff --git a/modules/convert/src/test/scala/docspell/convert/FileChecks.scala b/modules/convert/src/test/scala/docspell/convert/FileChecks.scala index 0f6f17d8..fe340b6c 100644 --- a/modules/convert/src/test/scala/docspell/convert/FileChecks.scala +++ b/modules/convert/src/test/scala/docspell/convert/FileChecks.scala @@ -6,6 +6,7 @@ import java.nio.file.{Files, Path} import cats.data.Kleisli import cats.effect.IO import fs2.{Pipe, Stream} + import docspell.common.MimeType import docspell.convert.ConversionResult.Handler import docspell.files.TikaMimetype diff --git a/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala b/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala index 87cb3d33..305fc2c1 100644 --- a/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala +++ b/modules/convert/src/test/scala/docspell/convert/extern/ExternConvTest.scala @@ -1,13 +1,15 @@ package docspell.convert.extern +import java.nio.charset.StandardCharsets import java.nio.file.{Path, Paths} import cats.effect._ + import docspell.common._ import docspell.convert._ import docspell.files.{ExampleFiles, TestFiles} + import munit._ -import java.nio.charset.StandardCharsets class ExternConvTest extends FunSuite with FileChecks { val blocker = TestFiles.blocker diff --git a/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala b/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala index c880ad6c..c074a02d 100644 --- a/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala +++ b/modules/extract/src/test/scala/docspell/extract/ocr/TextExtractionSuite.scala @@ -1,8 +1,10 @@ package docspell.extract.ocr import cats.effect.IO + import docspell.common.Logger import docspell.files.TestFiles + import munit._ class TextExtractionSuite extends FunSuite { diff --git a/modules/extract/src/test/scala/docspell/extract/odf/OdfExtractTest.scala b/modules/extract/src/test/scala/docspell/extract/odf/OdfExtractTest.scala index ea1d8a49..7d3a172f 100644 --- a/modules/extract/src/test/scala/docspell/extract/odf/OdfExtractTest.scala +++ b/modules/extract/src/test/scala/docspell/extract/odf/OdfExtractTest.scala @@ -1,7 +1,9 @@ package docspell.extract.odf import cats.effect._ + import docspell.files.{ExampleFiles, TestFiles} + import munit._ class OdfExtractTest extends FunSuite { diff --git a/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxExtractTest.scala b/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxExtractTest.scala index d39ef1c2..fa37ec4a 100644 --- a/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxExtractTest.scala +++ b/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxExtractTest.scala @@ -1,7 +1,9 @@ package docspell.extract.pdfbox import cats.effect._ + import docspell.files.{ExampleFiles, TestFiles} + import munit._ class PdfboxExtractTest extends FunSuite { diff --git a/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxPreviewTest.scala b/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxPreviewTest.scala index f4a1fd9b..d1594de6 100644 --- a/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxPreviewTest.scala +++ b/modules/extract/src/test/scala/docspell/extract/pdfbox/PdfboxPreviewTest.scala @@ -1,11 +1,14 @@ package docspell.extract.pdfbox -import cats.effect._ -import docspell.files.{ExampleFiles, TestFiles} -import munit._ import java.nio.file.Path + +import cats.effect._ import fs2.Stream +import docspell.files.{ExampleFiles, TestFiles} + +import munit._ + class PdfboxPreviewTest extends FunSuite { val blocker = TestFiles.blocker implicit val CS = TestFiles.CS diff --git a/modules/extract/src/test/scala/docspell/extract/poi/PoiExtractTest.scala b/modules/extract/src/test/scala/docspell/extract/poi/PoiExtractTest.scala index d89d2c84..336f54d4 100644 --- a/modules/extract/src/test/scala/docspell/extract/poi/PoiExtractTest.scala +++ b/modules/extract/src/test/scala/docspell/extract/poi/PoiExtractTest.scala @@ -1,8 +1,10 @@ package docspell.extract.poi import cats.effect._ + import docspell.common.MimeTypeHint import docspell.files.{ExampleFiles, TestFiles} + import munit._ class PoiExtractTest extends FunSuite { diff --git a/modules/extract/src/test/scala/docspell/extract/rtf/RtfExtractTest.scala b/modules/extract/src/test/scala/docspell/extract/rtf/RtfExtractTest.scala index 6736c0cd..9f513ba4 100644 --- a/modules/extract/src/test/scala/docspell/extract/rtf/RtfExtractTest.scala +++ b/modules/extract/src/test/scala/docspell/extract/rtf/RtfExtractTest.scala @@ -1,6 +1,7 @@ package docspell.extract.rtf import docspell.files.ExampleFiles + import munit._ class RtfExtractTest extends FunSuite { diff --git a/modules/files/src/test/scala/docspell/files/ImageSizeTest.scala b/modules/files/src/test/scala/docspell/files/ImageSizeTest.scala index 8cbc02c9..e82b0ce2 100644 --- a/modules/files/src/test/scala/docspell/files/ImageSizeTest.scala +++ b/modules/files/src/test/scala/docspell/files/ImageSizeTest.scala @@ -1,12 +1,13 @@ package docspell.files -import cats.implicits._ -import cats.effect.{Blocker, IO} -import munit._ - import scala.concurrent.ExecutionContext import scala.util.Using +import cats.effect.{Blocker, IO} +import cats.implicits._ + +import munit._ + class ImageSizeTest extends FunSuite { val blocker = Blocker.liftExecutionContext(ExecutionContext.global) implicit val CS = IO.contextShift(ExecutionContext.global) diff --git a/modules/files/src/test/scala/docspell/files/Playing.scala b/modules/files/src/test/scala/docspell/files/Playing.scala index 0f4f2423..ecddf526 100644 --- a/modules/files/src/test/scala/docspell/files/Playing.scala +++ b/modules/files/src/test/scala/docspell/files/Playing.scala @@ -1,10 +1,11 @@ package docspell.files -import cats.effect.{Blocker, ExitCode, IO, IOApp} -import docspell.common.MimeTypeHint - import scala.concurrent.ExecutionContext +import cats.effect._ + +import docspell.common.MimeTypeHint + object Playing extends IOApp { val blocker = Blocker.liftExecutionContext(ExecutionContext.global) diff --git a/modules/files/src/test/scala/docspell/files/TestFiles.scala b/modules/files/src/test/scala/docspell/files/TestFiles.scala index b415de1c..283734cf 100644 --- a/modules/files/src/test/scala/docspell/files/TestFiles.scala +++ b/modules/files/src/test/scala/docspell/files/TestFiles.scala @@ -1,10 +1,10 @@ package docspell.files +import scala.concurrent.ExecutionContext + import cats.effect.{Blocker, IO} import fs2.Stream -import scala.concurrent.ExecutionContext - object TestFiles { val blocker = Blocker.liftExecutionContext(ExecutionContext.global) implicit val CS = IO.contextShift(ExecutionContext.global) diff --git a/modules/files/src/test/scala/docspell/files/ZipTest.scala b/modules/files/src/test/scala/docspell/files/ZipTest.scala index 51dbb50a..8ca1e991 100644 --- a/modules/files/src/test/scala/docspell/files/ZipTest.scala +++ b/modules/files/src/test/scala/docspell/files/ZipTest.scala @@ -1,11 +1,14 @@ package docspell.files -import munit._ +import scala.concurrent.ExecutionContext + import cats.effect._ import cats.implicits._ -import scala.concurrent.ExecutionContext + import docspell.common.Glob +import munit._ + class ZipTest extends FunSuite { val blocker = Blocker.liftExecutionContext(ExecutionContext.global) diff --git a/modules/joex/src/test/scala/docspell/joex/analysis/NerFileTest.scala b/modules/joex/src/test/scala/docspell/joex/analysis/NerFileTest.scala index fa8412a4..b5c83f5f 100644 --- a/modules/joex/src/test/scala/docspell/joex/analysis/NerFileTest.scala +++ b/modules/joex/src/test/scala/docspell/joex/analysis/NerFileTest.scala @@ -1,9 +1,11 @@ package docspell.joex.analysis -import munit._ -import NerFile.Pattern import java.{util => ju} +import docspell.joex.analysis.NerFile.Pattern + +import munit._ + class NerFileTest extends FunSuite { test("create valid case insensitive patterns") { diff --git a/modules/joex/src/test/scala/docspell/joex/scheduler/CountingSchemeSpec.scala b/modules/joex/src/test/scala/docspell/joex/scheduler/CountingSchemeSpec.scala index 56a5352d..fca5bff5 100644 --- a/modules/joex/src/test/scala/docspell/joex/scheduler/CountingSchemeSpec.scala +++ b/modules/joex/src/test/scala/docspell/joex/scheduler/CountingSchemeSpec.scala @@ -1,6 +1,7 @@ package docspell.joex.scheduler import docspell.common.Priority + import munit._ class CountingSchemeSpec extends FunSuite { diff --git a/modules/query/shared/src/test/scala/docspell/query/FulltextExtractTest.scala b/modules/query/shared/src/test/scala/docspell/query/FulltextExtractTest.scala index 755ea121..b34ab89c 100644 --- a/modules/query/shared/src/test/scala/docspell/query/FulltextExtractTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/FulltextExtractTest.scala @@ -1,9 +1,11 @@ package docspell.query import cats.implicits._ -import munit._ + import docspell.query.FulltextExtract.Result +import munit._ + class FulltextExtractTest extends FunSuite { def findFts(q: String): Result = { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/AttrParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/AttrParserTest.scala index 34c2270f..9330fc3d 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/AttrParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/AttrParserTest.scala @@ -2,6 +2,7 @@ package docspell.query.internal import docspell.query.ItemQuery.Attr import docspell.query.internal.AttrParser + import munit._ class AttrParserTest extends FunSuite { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/BasicParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/BasicParserTest.scala index e397ce9b..fe185454 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/BasicParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/BasicParserTest.scala @@ -1,9 +1,11 @@ package docspell.query.internal -import munit._ import cats.data.{NonEmptyList => Nel} + import docspell.query.internal.BasicParser +import munit._ + class BasicParserTest extends FunSuite { test("single string values") { val p = BasicParser.singleString diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/DateParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/DateParserTest.scala index ec836ced..3bd1cbca 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/DateParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/DateParserTest.scala @@ -1,9 +1,11 @@ package docspell.query.internal -import munit._ -import docspell.query.Date import java.time.Period +import docspell.query.Date + +import munit._ + class DateParserTest extends FunSuite with ValueHelper { test("local date string") { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/ExprParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/ExprParserTest.scala index 07e14e9b..276ea00d 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/ExprParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/ExprParserTest.scala @@ -1,9 +1,11 @@ package docspell.query.internal -import docspell.query.ItemQuery._ -import munit._ import cats.data.{NonEmptyList => Nel} +import docspell.query.ItemQuery._ + +import munit._ + class ExprParserTest extends FunSuite with ValueHelper { test("simple expr") { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/ItemQueryParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/ItemQueryParserTest.scala index 52e35fc4..1e4b0c3a 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/ItemQueryParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/ItemQueryParserTest.scala @@ -2,9 +2,10 @@ package docspell.query.internal import cats.implicits._ -import munit._ -import docspell.query.ItemQueryParser import docspell.query.ItemQuery +import docspell.query.ItemQueryParser + +import munit._ class ItemQueryParserTest extends FunSuite { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/MacroParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/MacroParserTest.scala index 15855916..8f587fe6 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/MacroParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/MacroParserTest.scala @@ -1,9 +1,9 @@ package docspell.query.internal -import munit._ -//import cats.parse.{Parser => P} import docspell.query.ItemQuery.Expr +import munit._ + class MacroParserTest extends FunSuite { test("recognize names shortcut") { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/OperatorParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/OperatorParserTest.scala index 1a5a8af0..a60aa228 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/OperatorParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/OperatorParserTest.scala @@ -1,9 +1,10 @@ package docspell.query.internal -import munit._ import docspell.query.ItemQuery.{Operator, TagOperator} import docspell.query.internal.OperatorParser +import munit._ + class OperatorParserTest extends FunSuite { test("operator values") { val p = OperatorParser.op diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala b/modules/query/shared/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala index 35660dfa..58d4fe5b 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala @@ -1,11 +1,14 @@ package docspell.query.internal -import cats.data.{NonEmptyList => Nel} -import docspell.query.ItemQuery._ -import munit._ -import docspell.query.Date import java.time.Period +import cats.data.{NonEmptyList => Nel} + +import docspell.query.Date +import docspell.query.ItemQuery._ + +import munit._ + class SimpleExprParserTest extends FunSuite with ValueHelper { test("string expr") { diff --git a/modules/query/shared/src/test/scala/docspell/query/internal/ValueHelper.scala b/modules/query/shared/src/test/scala/docspell/query/internal/ValueHelper.scala index f2729f18..34f22f6d 100644 --- a/modules/query/shared/src/test/scala/docspell/query/internal/ValueHelper.scala +++ b/modules/query/shared/src/test/scala/docspell/query/internal/ValueHelper.scala @@ -1,8 +1,9 @@ package docspell.query.internal +import java.time.Period + import docspell.query.Date import docspell.query.ItemQuery._ -import java.time.Period trait ValueHelper { diff --git a/modules/store/src/test/scala/docspell/store/StoreFixture.scala b/modules/store/src/test/scala/docspell/store/StoreFixture.scala index 35b5ae68..acd59963 100644 --- a/modules/store/src/test/scala/docspell/store/StoreFixture.scala +++ b/modules/store/src/test/scala/docspell/store/StoreFixture.scala @@ -1,13 +1,15 @@ package docspell.store +import scala.concurrent.ExecutionContext + import cats.effect._ + import docspell.common.LenientUri import docspell.store.impl.StoreImpl + import doobie._ import org.h2.jdbcx.JdbcConnectionPool -import scala.concurrent.ExecutionContext - trait StoreFixture { def withStore(db: String)(code: Store[IO] => IO[Unit]): Unit = { //StoreFixture.store(StoreFixture.memoryDB(db)).use(code).unsafeRunSync() diff --git a/modules/store/src/test/scala/docspell/store/generator/ItemQueryGeneratorTest.scala b/modules/store/src/test/scala/docspell/store/generator/ItemQueryGeneratorTest.scala index 74612153..2182cf56 100644 --- a/modules/store/src/test/scala/docspell/store/generator/ItemQueryGeneratorTest.scala +++ b/modules/store/src/test/scala/docspell/store/generator/ItemQueryGeneratorTest.scala @@ -2,13 +2,14 @@ package docspell.store.generator import java.time.LocalDate -import docspell.store.records._ -import munit._ import docspell.common._ import docspell.query.ItemQueryParser -import docspell.store.queries.AttachCountTable import docspell.store.qb.DSL._ import docspell.store.qb.generator.{ItemQueryGenerator, Tables} +import docspell.store.queries.AttachCountTable +import docspell.store.records._ + +import munit._ class ItemQueryGeneratorTest extends FunSuite { import docspell.store.impl.DoobieMeta._ diff --git a/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala b/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala index f7d8b990..c355a7cb 100644 --- a/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala +++ b/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala @@ -1,8 +1,9 @@ package docspell.store.qb -import munit._ -import docspell.store.qb.model._ import docspell.store.qb.DSL._ +import docspell.store.qb.model._ + +import munit._ class QueryBuilderTest extends FunSuite { diff --git a/modules/store/src/test/scala/docspell/store/qb/impl/ConditionBuilderTest.scala b/modules/store/src/test/scala/docspell/store/qb/impl/ConditionBuilderTest.scala index 0d8bc32f..ebab052c 100644 --- a/modules/store/src/test/scala/docspell/store/qb/impl/ConditionBuilderTest.scala +++ b/modules/store/src/test/scala/docspell/store/qb/impl/ConditionBuilderTest.scala @@ -1,10 +1,11 @@ package docspell.store.qb.impl -import munit._ -import docspell.store.qb._ import docspell.store.qb.DSL._ +import docspell.store.qb._ import docspell.store.qb.model.{CourseRecord, PersonRecord} +import munit._ + class ConditionBuilderTest extends FunSuite { val c = CourseRecord.as("c") diff --git a/modules/store/src/test/scala/docspell/store/qb/impl/DSLTest.scala b/modules/store/src/test/scala/docspell/store/qb/impl/DSLTest.scala index 8a8872d1..e5b0b5be 100644 --- a/modules/store/src/test/scala/docspell/store/qb/impl/DSLTest.scala +++ b/modules/store/src/test/scala/docspell/store/qb/impl/DSLTest.scala @@ -1,10 +1,11 @@ package docspell.store.qb.impl -import munit._ -import docspell.store.qb._ import docspell.store.qb.DSL._ +import docspell.store.qb._ import docspell.store.qb.model.{CourseRecord, PersonRecord} +import munit._ + class DSLTest extends FunSuite { val course = CourseRecord.as("c") diff --git a/modules/store/src/test/scala/docspell/store/qb/impl/SelectBuilderTest.scala b/modules/store/src/test/scala/docspell/store/qb/impl/SelectBuilderTest.scala index 976cf4de..f8b07595 100644 --- a/modules/store/src/test/scala/docspell/store/qb/impl/SelectBuilderTest.scala +++ b/modules/store/src/test/scala/docspell/store/qb/impl/SelectBuilderTest.scala @@ -1,9 +1,10 @@ package docspell.store.qb.impl -import munit._ +import docspell.store.qb.DSL._ import docspell.store.qb._ import docspell.store.qb.model._ -import docspell.store.qb.DSL._ + +import munit._ class SelectBuilderTest extends FunSuite { diff --git a/modules/store/src/test/scala/docspell/store/qb/model/CourseRecord.scala b/modules/store/src/test/scala/docspell/store/qb/model/CourseRecord.scala index 6b53fdfb..31ee4859 100644 --- a/modules/store/src/test/scala/docspell/store/qb/model/CourseRecord.scala +++ b/modules/store/src/test/scala/docspell/store/qb/model/CourseRecord.scala @@ -1,6 +1,7 @@ package docspell.store.qb.model import cats.data.NonEmptyList + import docspell.store.qb._ case class CourseRecord( diff --git a/modules/store/src/test/scala/docspell/store/qb/model/PersonRecord.scala b/modules/store/src/test/scala/docspell/store/qb/model/PersonRecord.scala index 5ea5b653..2080541b 100644 --- a/modules/store/src/test/scala/docspell/store/qb/model/PersonRecord.scala +++ b/modules/store/src/test/scala/docspell/store/qb/model/PersonRecord.scala @@ -1,8 +1,9 @@ package docspell.store.qb.model import cats.data.NonEmptyList -import docspell.store.qb._ + import docspell.common._ +import docspell.store.qb._ case class PersonRecord(id: Long, name: String, created: Timestamp) diff --git a/modules/webapp/src/main/elm/App/Data.elm b/modules/webapp/src/main/elm/App/Data.elm index b047f250..845a9555 100644 --- a/modules/webapp/src/main/elm/App/Data.elm +++ b/modules/webapp/src/main/elm/App/Data.elm @@ -2,6 +2,7 @@ module App.Data exposing ( Model , Msg(..) , defaultPage + , getUiLanguage , init ) @@ -13,6 +14,7 @@ import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) import Data.UiTheme exposing (UiTheme) import Http +import Messages.UiLanguage exposing (UiLanguage) import Page exposing (Page(..)) import Page.CollectiveSettings.Data import Page.Home.Data @@ -48,6 +50,8 @@ type alias Model = , uiSettings : UiSettings , sidebarVisible : Bool , anonymousTheme : UiTheme + , anonymousUiLang : UiLanguage + , langMenuOpen : Bool } @@ -97,6 +101,8 @@ init key url flags_ settings = , uiSettings = settings , sidebarVisible = settings.sideMenuVisible , anonymousTheme = Data.UiTheme.Light + , anonymousUiLang = Messages.UiLanguage.English + , langMenuOpen = False } , Cmd.batch [ Cmd.map UserSettingsMsg uc @@ -152,8 +158,20 @@ type Msg | GetUiSettings UiSettings | ToggleSidebar | ToggleDarkMode + | ToggleLangMenu + | SetLanguage UiLanguage defaultPage : Flags -> Page -defaultPage flags = +defaultPage _ = HomePage + + +getUiLanguage : Model -> UiLanguage +getUiLanguage model = + case model.flags.account of + Just _ -> + model.uiSettings.uiLang + + Nothing -> + model.anonymousUiLang diff --git a/modules/webapp/src/main/elm/App/Update.elm b/modules/webapp/src/main/elm/App/Update.elm index 63e3aceb..4752f4b0 100644 --- a/modules/webapp/src/main/elm/App/Update.elm +++ b/modules/webapp/src/main/elm/App/Update.elm @@ -84,6 +84,15 @@ updateWithSub msg model = , Sub.none ) + ToggleLangMenu -> + ( { model | langMenuOpen = not model.langMenuOpen } + , Cmd.none + , Sub.none + ) + + SetLanguage lang -> + ( { model | anonymousUiLang = lang, langMenuOpen = False }, Cmd.none, Sub.none ) + HomeMsg lm -> updateHome lm model diff --git a/modules/webapp/src/main/elm/App/View2.elm b/modules/webapp/src/main/elm/App/View2.elm index 7c907437..c8afa599 100644 --- a/modules/webapp/src/main/elm/App/View2.elm +++ b/modules/webapp/src/main/elm/App/View2.elm @@ -7,6 +7,9 @@ import Data.Flags import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages exposing (Messages) +import Messages.App exposing (Texts) +import Messages.UiLanguage import Page exposing (Page(..)) import Page.CollectiveSettings.View2 as CollectiveSettings import Page.Home.Data @@ -41,6 +44,10 @@ topNavbar model = topNavUser : AuthResult -> Model -> Html Msg topNavUser auth model = + let + texts = + Messages.get <| App.Data.getUiLanguage model + in nav [ id "top-nav" , class styleTopNav @@ -56,8 +63,8 @@ topNavUser auth model = } , headerNavItem model , div [ class "flex flex-grow justify-end" ] - [ userMenu auth model - , dataMenu auth model + [ userMenu texts.app auth model + , dataMenu texts.app auth model ] ] @@ -70,7 +77,8 @@ topNavAnon model = ] [ headerNavItem model , div [ class "flex flex-grow justify-end" ] - [ a + [ langMenu model + , a [ href "#" , onClick ToggleDarkMode , class dropdownLink @@ -100,40 +108,44 @@ headerNavItem model = mainContent : Model -> Html Msg mainContent model = + let + texts = + Messages.get <| App.Data.getUiLanguage model + in div [ id "main" , class styleMain ] (case model.page of HomePage -> - viewHome model + viewHome texts model CollectiveSettingPage -> - viewCollectiveSettings model + viewCollectiveSettings texts model LoginPage _ -> - viewLogin model + viewLogin texts model ManageDataPage -> - viewManageData model + viewManageData texts model UserSettingPage -> - viewUserSettings model + viewUserSettings texts model QueuePage -> - viewQueue model + viewQueue texts model RegisterPage -> - viewRegister model + viewRegister texts model UploadPage mid -> - viewUpload mid model + viewUpload texts mid model NewInvitePage -> - viewNewInvite model + viewNewInvite texts model ItemDetailPage id -> - viewItemDetail id model + viewItemDetail texts id model ) @@ -151,8 +163,47 @@ styleMain = "mt-12 flex md:flex-row flex-col w-full h-screen-12 overflow-y-hidden bg-white dark:bg-bluegray-800 text-gray-800 dark:text-bluegray-300 antialiased" -dataMenu : AuthResult -> Model -> Html Msg -dataMenu _ model = +langMenu : Model -> Html Msg +langMenu model = + let + texts = + Messages.get <| App.Data.getUiLanguage model + + langItem lang = + let + langMsg = + Messages.get lang + in + a + [ classList + [ ( dropdownItem, True ) + , ( "bg-gray-200 dark:bg-bluegray-700", lang == texts.lang ) + ] + , onClick (SetLanguage lang) + , href "#" + ] + [ i [ langMsg |> .flagIcon |> class ] [] + , span [ class "ml-2" ] [ text langMsg.label ] + ] + in + div [ class "relative" ] + [ a + [ class dropdownLink + , onClick ToggleLangMenu + , href "#" + ] + [ i [ class texts.flagIcon ] [] + ] + , div + [ class dropdownMenu + , classList [ ( "hidden", not model.langMenuOpen ) ] + ] + (List.map langItem Messages.UiLanguage.all) + ] + + +dataMenu : Texts -> AuthResult -> Model -> Html Msg +dataMenu texts _ model = div [ class "relative" ] [ a [ class dropdownLink @@ -174,7 +225,7 @@ dataMenu _ model = ] [] , div [ class "inline-block ml-2" ] - [ text "Items" + [ text texts.items ] ] , div [ class "py-1" ] [ hr [ class S.border ] [] ] @@ -183,7 +234,7 @@ dataMenu _ model = [] [ i [ class "fa fa-cubes w-6" ] [] , span [ class "ml-1" ] - [ text "Manage Data" + [ text texts.manageData ] ] , div [ class "divider" ] [] @@ -192,7 +243,7 @@ dataMenu _ model = [] [ i [ class "fa fa-upload w-6" ] [] , span [ class "ml-1" ] - [ text "Upload files" + [ text texts.uploadFiles ] ] , dataPageLink model @@ -200,7 +251,7 @@ dataMenu _ model = [] [ i [ class "fa fa-tachometer-alt w-6" ] [] , span [ class "ml-1" ] - [ text "Processing Queue" + [ text texts.processingQueue ] ] , div @@ -215,7 +266,7 @@ dataMenu _ model = [ ( "hidden", model.flags.config.signupMode /= "invite" ) ] [ i [ class "fa fa-key w-6" ] [] , span [ class "ml-1" ] - [ text "New Invites" + [ text texts.newInvites ] ] , div [ class "py-1" ] @@ -229,7 +280,7 @@ dataMenu _ model = , title "Opens https://docspell.org/docs" ] [ i [ class "fa fa-question-circle w-6" ] [] - , span [ class "ml-1" ] [ text "Help" ] + , span [ class "ml-1" ] [ text texts.help ] , span [ class "float-right" ] [ i [ class "fa fa-external-link-alt w-6" ] [] ] @@ -238,8 +289,8 @@ dataMenu _ model = ] -userMenu : AuthResult -> Model -> Html Msg -userMenu acc model = +userMenu : Texts -> AuthResult -> Model -> Html Msg +userMenu texts acc model = div [ class "relative" ] [ a [ class dropdownLink @@ -263,14 +314,14 @@ userMenu acc model = CollectiveSettingPage [ i [ class "fa fa-users w-6" ] [] , span [ class "ml-1" ] - [ text "Collective Profile" + [ text texts.collectiveProfile ] ] , userPageLink model UserSettingPage [ i [ class "fa fa-user-circle w-6" ] [] , span [ class "ml-1" ] - [ text "User Profile" + [ text texts.userProfile ] ] , a @@ -280,7 +331,7 @@ userMenu acc model = ] [ i [ class "fa fa-adjust w-6" ] [] , span [ class "ml-1" ] - [ text "Light/Dark" + [ text texts.lightDark ] ] , div [ class "py-1" ] [ hr [ class S.border ] [] ] @@ -291,7 +342,7 @@ userMenu acc model = ] [ i [ class "fa fa-sign-out-alt w-6" ] [] , span [ class "ml-1" ] - [ text "Logout" + [ text texts.logout ] ] ] @@ -346,85 +397,121 @@ dropdownMenu = " absolute right-0 bg-white dark:bg-bluegray-800 border dark:border-bluegray-700 dark:text-bluegray-300 shadow-lg opacity-1 transition duration-200 min-w-max " -viewHome : Model -> List (Html Msg) -viewHome model = - [ Html.map HomeMsg (Home.viewSidebar model.sidebarVisible model.flags model.uiSettings model.homeModel) - , Html.map HomeMsg (Home.viewContent model.flags model.uiSettings model.homeModel) +viewHome : Messages -> Model -> List (Html Msg) +viewHome texts model = + [ Html.map HomeMsg + (Home.viewSidebar texts.home + model.sidebarVisible + model.flags + model.uiSettings + model.homeModel + ) + , Html.map HomeMsg + (Home.viewContent texts.home + model.flags + model.uiSettings + model.homeModel + ) ] -viewCollectiveSettings : Model -> List (Html Msg) -viewCollectiveSettings model = +viewCollectiveSettings : Messages -> Model -> List (Html Msg) +viewCollectiveSettings texts model = [ Html.map CollSettingsMsg - (CollectiveSettings.viewSidebar model.sidebarVisible + (CollectiveSettings.viewSidebar texts.collectiveSettings + model.sidebarVisible model.flags model.uiSettings model.collSettingsModel ) , Html.map CollSettingsMsg - (CollectiveSettings.viewContent model.flags + (CollectiveSettings.viewContent texts.collectiveSettings + model.flags model.uiSettings model.collSettingsModel ) ] -viewLogin : Model -> List (Html Msg) -viewLogin model = +viewLogin : Messages -> Model -> List (Html Msg) +viewLogin texts model = [ Html.map LoginMsg (Login.viewSidebar model.sidebarVisible model.flags model.uiSettings model.loginModel) , Html.map LoginMsg - (Login.viewContent model.flags model.version model.uiSettings model.loginModel) + (Login.viewContent texts.login model.flags model.version model.uiSettings model.loginModel) ] -viewManageData : Model -> List (Html Msg) -viewManageData model = +viewManageData : Messages -> Model -> List (Html Msg) +viewManageData texts model = [ Html.map ManageDataMsg - (ManageData.viewSidebar model.sidebarVisible model.flags model.uiSettings model.manageDataModel) + (ManageData.viewSidebar texts.manageData + model.sidebarVisible + model.flags + model.uiSettings + model.manageDataModel + ) , Html.map ManageDataMsg - (ManageData.viewContent model.flags model.uiSettings model.manageDataModel) + (ManageData.viewContent texts.manageData + model.flags + model.uiSettings + model.manageDataModel + ) ] -viewUserSettings : Model -> List (Html Msg) -viewUserSettings model = +viewUserSettings : Messages -> Model -> List (Html Msg) +viewUserSettings texts model = [ Html.map UserSettingsMsg - (UserSettings.viewSidebar model.sidebarVisible model.flags model.uiSettings model.userSettingsModel) + (UserSettings.viewSidebar texts.userSettings + model.sidebarVisible + model.flags + model.uiSettings + model.userSettingsModel + ) , Html.map UserSettingsMsg - (UserSettings.viewContent model.flags model.uiSettings model.userSettingsModel) + (UserSettings.viewContent texts.userSettings + model.flags + model.uiSettings + model.userSettingsModel + ) ] -viewQueue : Model -> List (Html Msg) -viewQueue model = +viewQueue : Messages -> Model -> List (Html Msg) +viewQueue texts model = [ Html.map QueueMsg - (Queue.viewSidebar model.sidebarVisible model.flags model.uiSettings model.queueModel) + (Queue.viewSidebar texts.queue + model.sidebarVisible + model.flags + model.uiSettings + model.queueModel + ) , Html.map QueueMsg - (Queue.viewContent model.flags model.uiSettings model.queueModel) + (Queue.viewContent texts.queue model.flags model.uiSettings model.queueModel) ] -viewRegister : Model -> List (Html Msg) -viewRegister model = +viewRegister : Messages -> Model -> List (Html Msg) +viewRegister texts model = [ Html.map RegisterMsg (Register.viewSidebar model.sidebarVisible model.flags model.uiSettings model.registerModel) , Html.map RegisterMsg - (Register.viewContent model.flags model.uiSettings model.registerModel) + (Register.viewContent texts.register model.flags model.uiSettings model.registerModel) ] -viewNewInvite : Model -> List (Html Msg) -viewNewInvite model = +viewNewInvite : Messages -> Model -> List (Html Msg) +viewNewInvite texts model = [ Html.map NewInviteMsg (NewInvite.viewSidebar model.sidebarVisible model.flags model.uiSettings model.newInviteModel) , Html.map NewInviteMsg - (NewInvite.viewContent model.flags model.uiSettings model.newInviteModel) + (NewInvite.viewContent texts.newInvite model.flags model.uiSettings model.newInviteModel) ] -viewUpload : Maybe String -> Model -> List (Html Msg) -viewUpload mid model = +viewUpload : Messages -> Maybe String -> Model -> List (Html Msg) +viewUpload texts mid model = [ Html.map UploadMsg (Upload.viewSidebar mid @@ -434,7 +521,8 @@ viewUpload mid model = model.uploadModel ) , Html.map UploadMsg - (Upload.viewContent mid + (Upload.viewContent texts.upload + mid model.flags model.uiSettings model.uploadModel @@ -442,21 +530,21 @@ viewUpload mid model = ] -viewItemDetail : String -> Model -> List (Html Msg) -viewItemDetail id model = +viewItemDetail : Messages -> String -> Model -> List (Html Msg) +viewItemDetail texts id model = let inav = Page.Home.Data.itemNav id model.homeModel in [ Html.map ItemDetailMsg - (ItemDetail.viewSidebar + (ItemDetail.viewSidebar texts.itemDetail model.sidebarVisible model.flags model.uiSettings model.itemDetailModel ) , Html.map ItemDetailMsg - (ItemDetail.viewContent + (ItemDetail.viewContent texts.itemDetail inav model.flags model.uiSettings diff --git a/modules/webapp/src/main/elm/Comp/AddressForm.elm b/modules/webapp/src/main/elm/Comp/AddressForm.elm index 8b7a439d..e8b2fd61 100644 --- a/modules/webapp/src/main/elm/Comp/AddressForm.elm +++ b/modules/webapp/src/main/elm/Comp/AddressForm.elm @@ -14,6 +14,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.AddressForm exposing (Texts) import Styles as S import Util.List @@ -51,9 +52,7 @@ emptyModel = , city = "" , country = Comp.Dropdown.makeSingleList - { makeOption = \c -> { value = c.code, text = c.label, additional = "" } - , placeholder = "Select Country" - , options = countries + { options = countries , selected = Nothing } } @@ -112,8 +111,16 @@ update msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = + let + countryCfg = + { makeOption = \c -> { text = c.label, additional = "" } + , placeholder = texts.selectCountry + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in div [ class "flex flex-col" ] [ div [ class "mb-2" @@ -122,12 +129,12 @@ view2 settings model = [ for "street" , class S.inputLabel ] - [ text "Street" + [ text texts.street ] , input [ type_ "text" , onInput SetStreet - , placeholder "Street" + , placeholder texts.street , value model.street , name "street" , class S.textInput @@ -141,12 +148,12 @@ view2 settings model = [ for "zip" , class S.inputLabel ] - [ text "Zip Code" + [ text texts.zipCode ] , input [ type_ "text" , onInput SetZip - , placeholder "Zip" + , placeholder texts.zipCode , value model.zip , name "zip" , class S.textInput @@ -160,12 +167,12 @@ view2 settings model = [ for "city" , class S.inputLabel ] - [ text "City" + [ text texts.city ] , input [ type_ "text" , onInput SetCity - , placeholder "City" + , placeholder texts.city , value model.city , name "city" , class S.textInput @@ -174,11 +181,11 @@ view2 settings model = ] , div [ class "" ] [ label [ class S.inputLabel ] - [ text "Country" + [ text texts.country ] , Html.map CountryMsg (Comp.Dropdown.view2 - DS.mainStyle + countryCfg settings model.country ) diff --git a/modules/webapp/src/main/elm/Comp/AttachmentMeta.elm b/modules/webapp/src/main/elm/Comp/AttachmentMeta.elm index 780e4561..10b9920e 100644 --- a/modules/webapp/src/main/elm/Comp/AttachmentMeta.elm +++ b/modules/webapp/src/main/elm/Comp/AttachmentMeta.elm @@ -15,6 +15,7 @@ import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) import Http +import Messages.Comp.AttachmentMeta exposing (Texts) import Styles as S import Util.Http import Util.Time @@ -64,15 +65,18 @@ update msg model = --- View2 -view2 : List (Attribute Msg) -> Model -> Html Msg -view2 attrs model = +view2 : Texts -> List (Attribute Msg) -> Model -> Html Msg +view2 texts attrs model = div attrs [ h3 [ class S.header3 ] - [ text "Extracted Meta Data" + [ text texts.extractedMetadata ] , case model.meta of NotAvailable -> - B.loadingDimmer True + B.loadingDimmer + { active = True + , label = texts.basics.loading + } Failure msg -> div [ class S.errorMessage ] @@ -80,33 +84,33 @@ view2 attrs model = ] Success data -> - viewData2 data + viewData2 texts data ] -viewData2 : AttachmentMeta -> Html Msg -viewData2 meta = +viewData2 : Texts -> AttachmentMeta -> Html Msg +viewData2 texts meta = div [ class "flex flex-col" ] [ div [ class "text-lg font-bold" ] - [ text "Content" + [ text texts.content ] , div [ class "px-2 py-2 text-sm bg-yellow-50 dark:bg-warmgray-800 break-words whitespace-pre max-h-80 overflow-auto" ] [ text meta.content ] , div [ class "text-lg font-bold mt-2" ] - [ text "Labels" + [ text texts.labels ] , div [ class "flex fex-row flex-wrap" ] (List.map renderLabelItem2 meta.labels) , div [ class "text-lg font-bold mt-2" ] - [ text "Proposals" + [ text texts.proposals ] - , viewProposals2 meta.proposals + , viewProposals2 texts meta.proposals ] -viewProposals2 : ItemProposals -> Html Msg -viewProposals2 props = +viewProposals2 : Texts -> ItemProposals -> Html Msg +viewProposals2 texts props = let mkItem n lbl = div @@ -130,32 +134,32 @@ viewProposals2 props = in div [ class "flex flex-col" ] [ div [ class "font-bold mb-2" ] - [ text "Correspondent Organization" + [ text texts.correspondentOrg ] , div [ class "flex flex-row flex-wrap space-x-2" ] (List.indexedMap mkItem props.corrOrg) , div [ class "font-bold mt-3 mb-2" ] - [ text "Correspondent Person" + [ text texts.correspondentPerson ] , div [ class "flex flex-row flex-wrap space-x-2" ] (List.indexedMap mkItem props.corrPerson) , div [ class "font-bold mt-3 mb-2" ] - [ text "Concerning Person" + [ text texts.concerningPerson ] , div [ class "flex flex-row flex-wrap space-x-2" ] (List.indexedMap mkItem props.concPerson) , div [ class "font-bold mt-3 mb-2" ] - [ text "Concerning Equipment" + [ text texts.concerningEquipment ] , div [ class "flex flex-row flex-wrap space-x-2" ] (List.indexedMap mkItem props.concEquipment) , div [ class "font-bold mb-2 mt-3" ] - [ text "Item Date" + [ text texts.itemDate ] , div [ class "flex flex-row flex-wrap space-x-2" ] (List.map mkTimeItem props.itemDate) , div [ class "font-bold mt-3 mb-2" ] - [ text "Item Due Date" + [ text texts.itemDueDate ] , div [ class "flex flex-row flex-wrap space-x-2 mb-2" ] (List.map mkTimeItem props.dueDate) diff --git a/modules/webapp/src/main/elm/Comp/Basic.elm b/modules/webapp/src/main/elm/Comp/Basic.elm index 0686b6ea..f34f010d 100644 --- a/modules/webapp/src/main/elm/Comp/Basic.elm +++ b/modules/webapp/src/main/elm/Comp/Basic.elm @@ -1,6 +1,7 @@ module Comp.Basic exposing ( editLinkLabel , editLinkTableCell + , editLinkTableCell2 , genericButton , horizontalDivider , inputRequired @@ -11,12 +12,12 @@ module Comp.Basic exposing , secondaryBasicButton , secondaryButton , stats - , tooltipRight ) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Basics import Styles as S @@ -174,27 +175,32 @@ linkLabel model = genericLink model.icon model.label attrs -loadingDimmer : Bool -> Html msg -loadingDimmer active = +loadingDimmer : { label : String, active : Bool } -> Html msg +loadingDimmer cfg = div [ classList - [ ( "hidden", not active ) + [ ( "hidden", not cfg.active ) ] , class S.dimmer ] [ div [ class "text-gray-200" ] [ i [ class "fa fa-circle-notch animate-spin" ] [] , span [ class "ml-2" ] - [ text "Loading…" + [ text cfg.label ] ] ] editLinkLabel : msg -> Html msg -editLinkLabel click = +editLinkLabel = + editLinkLabel2 Messages.Basics.gb + + +editLinkLabel2 : Messages.Basics.Texts -> msg -> Html msg +editLinkLabel2 texts click = linkLabel - { label = "Edit" + { label = texts.edit , icon = "fa fa-edit" , handler = click , disabled = False @@ -204,7 +210,14 @@ editLinkLabel click = editLinkTableCell : msg -> Html msg editLinkTableCell m = td [ class S.editLinkTableCellStyle ] - [ editLinkLabel m + [ editLinkLabel2 Messages.Basics.gb m + ] + + +editLinkTableCell2 : Messages.Basics.Texts -> msg -> Html msg +editLinkTableCell2 texts m = + td [ class S.editLinkTableCellStyle ] + [ editLinkLabel2 texts m ] @@ -265,17 +278,6 @@ inputRequired = ] -tooltipRight : Bool -> String -> Html msg -tooltipRight show msg = - div - [ class "absolute bottom-0 right-5 px-2 py-2 rounded-lg z-50 w-40" - , class "bg-white border" - , class "text-sm font-thin" - ] - [ text msg - ] - - --- Helpers diff --git a/modules/webapp/src/main/elm/Comp/CalEventInput.elm b/modules/webapp/src/main/elm/Comp/CalEventInput.elm index f69fb809..a38db6be 100644 --- a/modules/webapp/src/main/elm/Comp/CalEventInput.elm +++ b/modules/webapp/src/main/elm/Comp/CalEventInput.elm @@ -17,6 +17,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) import Http +import Messages.Comp.CalEventInput exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -129,8 +130,8 @@ update flags ev msg model = --- View2 -view2 : String -> CalEvent -> Model -> Html Msg -view2 extraClasses ev model = +view2 : Texts -> String -> CalEvent -> Model -> Html Msg +view2 texts extraClasses ev model = let yearLen = Basics.max 4 (String.length ev.year) @@ -155,7 +156,7 @@ view2 extraClasses ev model = [ label [ class S.inputLabel ] - [ text "Weekday" ] + [ text texts.weekday ] , input [ type_ "text" , class S.textInput @@ -172,7 +173,7 @@ view2 extraClasses ev model = ] , div [ class "flex flex-col space-y-2 mr-2" ] [ label [ class S.inputLabel ] - [ text "Year" ] + [ text texts.year ] , input [ type_ "text" , class S.textInput @@ -188,7 +189,7 @@ view2 extraClasses ev model = ] , div [ class "flex flex-col space-y-2 mr-2" ] [ label [ class S.inputLabel ] - [ text "Month" ] + [ text texts.month ] , input [ type_ "text" , class styleInput @@ -204,7 +205,7 @@ view2 extraClasses ev model = ] , div [ class "flex flex-col space-y-2 mr-4 mr-2" ] [ label [ class S.inputLabel ] - [ text "Day" + [ text texts.day ] , input [ type_ "text" @@ -218,7 +219,8 @@ view2 extraClasses ev model = ] , div [ class "flex flex-col space-y-2 mr-2" ] [ label [ class S.inputLabel ] - [ text "Hour" ] + [ text texts.hour + ] , input [ type_ "text" , class styleInput @@ -234,7 +236,7 @@ view2 extraClasses ev model = ] , div [ class "flex flex-col space-y-2" ] [ label [ class S.inputLabel ] - [ text "Minute" + [ text texts.minute ] , input [ type_ "text" @@ -253,7 +255,7 @@ view2 extraClasses ev model = ] , class S.errorMessage ] - [ text "Error: " + [ text (texts.error ++ ": ") , Maybe.map .message model.checkResult |> Maybe.withDefault "" |> text @@ -269,7 +271,7 @@ view2 extraClasses ev model = ] [ div [] [ div [ class S.inputLabel ] - [ text "Schedule: " + [ text (texts.schedule ++ ": ") ] , div [ class "px-12 font-mono " ] [ Maybe.andThen .event model.checkResult @@ -277,7 +279,7 @@ view2 extraClasses ev model = |> text ] , div [ class S.inputLabel ] - [ text "Next: " + [ text (texts.next ++ ": ") ] , ul [ class "list-decimal list-inside text-sm" ] (Maybe.map .next model.checkResult diff --git a/modules/webapp/src/main/elm/Comp/ChangePasswordForm.elm b/modules/webapp/src/main/elm/Comp/ChangePasswordForm.elm index 6c2e9410..53c9ac7a 100644 --- a/modules/webapp/src/main/elm/Comp/ChangePasswordForm.elm +++ b/modules/webapp/src/main/elm/Comp/ChangePasswordForm.elm @@ -16,6 +16,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Http +import Messages.Comp.ChangePasswordForm exposing (Texts) import Styles as S import Util.Http @@ -179,8 +180,8 @@ update flags msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = let currentEmpty = model.current == Nothing @@ -195,11 +196,12 @@ view2 model = [ class "flex flex-col space-y-4 relative" ] [ div [] [ label [ class S.inputLabel ] - [ text "Current Password" + [ text texts.currentPassword , B.inputRequired ] , Html.map SetCurrent (Comp.PasswordInput.view2 + { placeholder = texts.currentPasswordPlaceholder } model.current currentEmpty model.currentModel @@ -209,11 +211,12 @@ view2 model = [ label [ class S.inputLabel ] - [ text "New Password" + [ text texts.newPassword , B.inputRequired ] , Html.map SetNew1 (Comp.PasswordInput.view2 + { placeholder = texts.newPasswordPlaceholder } model.newPass1 pass1Empty model.pass1Model @@ -221,11 +224,12 @@ view2 model = ] , div [] [ label [ class S.inputLabel ] - [ text "New Password (repeat)" + [ text texts.repeatPassword , B.inputRequired ] , Html.map SetNew2 (Comp.PasswordInput.view2 + { placeholder = texts.repeatPasswordPlaceholder } model.newPass2 pass2Empty model.pass2Model @@ -263,5 +267,8 @@ view2 model = [ text "Submit" ] ] - , B.loadingDimmer model.loading + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/ClassifierSettingsForm.elm b/modules/webapp/src/main/elm/Comp/ClassifierSettingsForm.elm index 3850dab2..9c7d17bc 100644 --- a/modules/webapp/src/main/elm/Comp/ClassifierSettingsForm.elm +++ b/modules/webapp/src/main/elm/Comp/ClassifierSettingsForm.elm @@ -24,6 +24,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Http import Markdown +import Messages.Comp.ClassifierSettingsForm exposing (Texts) import Styles as S import Util.Tag @@ -59,20 +60,14 @@ init flags sett = in ( { scheduleModel = cem , schedule = Data.Validated.Unknown newSchedule - , itemCountModel = Comp.IntField.init (Just 0) Nothing True "Item Count" + , itemCountModel = Comp.IntField.init (Just 0) Nothing True , itemCount = Just sett.itemCount , categoryListModel = let - mkOption s = - { value = s, text = s, additional = "" } - minit = Comp.Dropdown.makeModel { multiple = True , searchable = \n -> n > 0 - , makeOption = mkOption - , labelColor = \_ -> \_ -> "grey " - , placeholder = "Choose categories …" } lm = @@ -86,7 +81,7 @@ init flags sett = Data.ListType.fromString sett.listType |> Maybe.withDefault Data.ListType.Whitelist , categoryListTypeModel = - Comp.FixedDropdown.initMap Data.ListType.label Data.ListType.all + Comp.FixedDropdown.init Data.ListType.all } , Cmd.batch [ Api.getTags flags "" GetTagsResp @@ -183,60 +178,69 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = let - catListTypeItem = - Comp.FixedDropdown.Item - model.categoryListType - (Data.ListType.label model.categoryListType) + categoryCfg = + { makeOption = \s -> { text = s, additional = "" } + , labelColor = \_ -> \_ -> "grey " + , placeholder = "Choose categories …" + , style = DS.mainStyle + } + + catListCfg = + { display = Data.ListType.label + , icon = \_ -> Nothing + , style = DS.mainStyle + } in div [] [ Markdown.toHtml [ class "px-2 py-2 opacity-75" ] - """ - -Auto-tagging works by learning from existing documents. The more -documents you have correctly tagged, the better. Learning is done -periodically based on a schedule. You can specify tag-groups that -should either be used (whitelist) or not used (blacklist) for -learning. - -Use an empty whitelist to disable auto tagging. - - """ + texts.autoTaggingText , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Is the following a blacklist or whitelist?" ] + [ text texts.blacklistOrWhitelist ] , Html.map CategoryListTypeMsg - (Comp.FixedDropdown.view2 (Just catListTypeItem) model.categoryListTypeModel) + (Comp.FixedDropdown.viewStyled2 catListCfg + False + (Just model.categoryListType) + model.categoryListTypeModel + ) ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] [ case model.categoryListType of Data.ListType.Whitelist -> - text "Include tag categories for learning" + text texts.whitelistLabel Data.ListType.Blacklist -> - text "Exclude tag categories from learning" + text texts.blacklistLabel ] , Html.map CategoryListMsg (Comp.Dropdown.view2 - DS.mainStyle + categoryCfg settings model.categoryListModel ) ] , Html.map ItemCountMsg - (Comp.IntField.viewWithInfo2 - "The maximum number of items to learn from, order by date newest first. Use 0 to mean all." - model.itemCount - "mb-4" + (Comp.IntField.view + { label = texts.itemCount + , info = texts.itemCountHelp + , classes = "mb-4" + , number = model.itemCount + } model.itemCountModel ) , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Schedule" ] + [ text texts.schedule ] , Html.map ScheduleMsg - (Comp.CalEventInput.view2 "" (Data.Validated.value model.schedule) model.scheduleModel) + (Comp.CalEventInput.view2 + texts.calEventInput + "" + (Data.Validated.value model.schedule) + model.scheduleModel + ) ] ] diff --git a/modules/webapp/src/main/elm/Comp/CollectiveSettingsForm.elm b/modules/webapp/src/main/elm/Comp/CollectiveSettingsForm.elm index 5b28bb4e..9620f594 100644 --- a/modules/webapp/src/main/elm/Comp/CollectiveSettingsForm.elm +++ b/modules/webapp/src/main/elm/Comp/CollectiveSettingsForm.elm @@ -23,6 +23,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onClick, onInput) import Http +import Messages.Comp.CollectiveSettingsForm exposing (Texts) import Styles as S import Util.Http @@ -50,14 +51,7 @@ init flags settings = in ( { langModel = Comp.Dropdown.makeSingleList - { makeOption = - \l -> - { value = Data.Language.toIso3 l - , text = Data.Language.toName l - , additional = "" - } - , placeholder = "" - , options = Data.Language.all + { options = Data.Language.all , selected = Just lang } , intEnabled = settings.integrationEnabled @@ -200,8 +194,20 @@ update flags msg model = --- View2 -view2 : Flags -> UiSettings -> Model -> Html Msg -view2 flags settings model = +view2 : Flags -> Texts -> UiSettings -> Model -> Html Msg +view2 flags texts settings model = + let + languageCfg = + { makeOption = + \l -> + { text = texts.languageLabel l + , additional = "" + } + , placeholder = "" + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in div [ classList [ ( "ui form error success", True ) @@ -215,10 +221,10 @@ view2 flags settings model = [ MB.CustomElement <| B.primaryButton { handler = onClick SaveSettings - , label = "Save" + , label = texts.save , icon = "fa fa-save" , attrs = - [ title "Save settings" + [ title texts.saveSettings , href "#" ] , disabled = getSettings model |> Data.Validated.isInvalid @@ -228,20 +234,20 @@ view2 flags settings model = , rootClasses = "mb-4" } , h3 [ class S.header3 ] - [ text "Document Language" + [ text texts.documentLanguage ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Document Language" + [ text texts.documentLanguage ] , Html.map LangDropdownMsg (Comp.Dropdown.view2 - DS.mainStyle + languageCfg settings model.langModel ) , span [ class "opacity-50 text-sm" ] - [ text "The language of your documents. This helps text recognition (OCR) and text analysis." + [ text texts.documentLanguageHelp ] ] , div @@ -252,7 +258,7 @@ view2 flags settings model = [ h3 [ class S.header3 ] - [ text "Integration Endpoint" + [ text texts.integrationEndpoint ] , div [ class "mb-4" ] [ label @@ -268,12 +274,11 @@ view2 flags settings model = ] [] , span [ class "ml-2" ] - [ text "Enable integration endpoint" + [ text texts.integrationEndpointHelp ] ] , div [ class "opacity-50 text-sm" ] - [ text "The integration endpoint allows (local) applications to submit files. " - , text "You can choose to disable it for your collective." + [ text texts.integrationEndpointHelp ] ] ] @@ -284,7 +289,7 @@ view2 flags settings model = ] [ h3 [ class S.header3 ] - [ text "Full-Text Search" ] + [ text texts.fulltextSearch ] , div [ class "mb-4" ] [ div [ class "flex flex-row" ] @@ -304,13 +309,12 @@ view2 flags settings model = ] [ i [ class "fa fa-sync-alt" ] [] , span [ class "ml-2 hidden sm:inline" ] - [ text "Re-Index All Data" + [ text texts.reindexAllData ] ] ] , div [ class "opacity-50 text-sm" ] - [ text "This starts a task that clears the full-text index and re-indexes all your data again." - , text "You must type OK before clicking the button to avoid accidental re-indexing." + [ text texts.reindexAllDataHelp ] , renderResultMessage2 model.fullTextReIndexResult ] @@ -322,17 +326,20 @@ view2 flags settings model = ] [ h3 [ class S.header3 ] - [ text "Auto-Tagging" + [ text texts.autoTagging ] , div [ class "mb-4" ] [ Html.map ClassifierSettingMsg - (Comp.ClassifierSettingsForm.view2 settings model.classifierModel) + (Comp.ClassifierSettingsForm.view2 texts.classifierSettingsForm + settings + model.classifierModel + ) , div [ class "flex flex-row justify-end" ] [ B.secondaryBasicButton { handler = onClick StartClassifierTask , icon = "fa fa-play" - , label = "Start now" + , label = texts.startNow , disabled = Data.Validated.isInvalid model.classifierModel.schedule , attrs = [ href "#" ] } diff --git a/modules/webapp/src/main/elm/Comp/ColorTagger.elm b/modules/webapp/src/main/elm/Comp/ColorTagger.elm index a606b337..3fa42a20 100644 --- a/modules/webapp/src/main/elm/Comp/ColorTagger.elm +++ b/modules/webapp/src/main/elm/Comp/ColorTagger.elm @@ -9,6 +9,7 @@ module Comp.ColorTagger exposing import Comp.FixedDropdown import Data.Color exposing (Color) +import Data.DropdownStyle as DS import Dict exposing (Dict) import Html exposing (..) import Html.Attributes exposing (..) @@ -37,7 +38,7 @@ type Msg init : List String -> List Color -> Model init leftSel colors = - { leftDropdown = Comp.FixedDropdown.initString leftSel + { leftDropdown = Comp.FixedDropdown.init leftSel , colors = colors , leftSelect = Nothing } @@ -89,6 +90,7 @@ update msg model = type alias ViewOpts = { renderItem : ( String, Color ) -> Html Msg + , colorLabel : Color -> String , label : String , description : Maybe String } @@ -96,16 +98,26 @@ type alias ViewOpts = view2 : FormData -> ViewOpts -> Model -> Html Msg view2 data opts model = + let + colorLabelCfg = + { display = identity + , icon = \_ -> Nothing + , style = DS.mainStyle + } + in div [ class "flex flex-col" ] [ label [ class S.inputLabel ] [ text opts.label ] , Html.map LeftMsg - (Comp.FixedDropdown.view2 - (Maybe.map (\s -> Comp.FixedDropdown.Item s s) model.leftSelect) + (Comp.FixedDropdown.viewStyled2 + colorLabelCfg + False + model.leftSelect model.leftDropdown ) , div [ class "field" ] [ chooseColor2 + opts.colorLabel (AddPair data) Data.Color.all Nothing @@ -159,8 +171,8 @@ renderFormData2 opts data = (List.map valueItem values) -chooseColor2 : (Color -> msg) -> List Color -> Maybe String -> Html msg -chooseColor2 tagger colors mtext = +chooseColor2 : (Color -> String) -> (Color -> msg) -> List Color -> Maybe String -> Html msg +chooseColor2 colorLabel tagger colors mtext = let renderLabel color = a @@ -170,7 +182,7 @@ chooseColor2 tagger colors mtext = , onClick (tagger color) ] [ Maybe.withDefault - (Data.Color.toString color) + (colorLabel color) mtext |> text ] diff --git a/modules/webapp/src/main/elm/Comp/ConfirmModal.elm b/modules/webapp/src/main/elm/Comp/ConfirmModal.elm index 10b5a3ad..5f01a733 100644 --- a/modules/webapp/src/main/elm/Comp/ConfirmModal.elm +++ b/modules/webapp/src/main/elm/Comp/ConfirmModal.elm @@ -23,14 +23,14 @@ type alias Settings msg = } -defaultSettings : msg -> msg -> String -> Settings msg -defaultSettings confirm cancel confirmMsg = +defaultSettings : msg -> msg -> String -> String -> String -> Settings msg +defaultSettings confirm cancel okLabel cancelLabel confirmMsg = { enabled = True , extraClass = "" , headerIcon = "fa fa-exclamation-circle mr-3" , headerClass = "text-2xl font-bold text-center w-full" - , confirmText = "Ok" - , cancelText = "Cancel" + , confirmText = okLabel + , cancelText = cancelLabel , message = confirmMsg , confirm = confirm , cancel = cancel diff --git a/modules/webapp/src/main/elm/Comp/ContactField.elm b/modules/webapp/src/main/elm/Comp/ContactField.elm index 986d94de..11078acb 100644 --- a/modules/webapp/src/main/elm/Comp/ContactField.elm +++ b/modules/webapp/src/main/elm/Comp/ContactField.elm @@ -1,6 +1,7 @@ module Comp.ContactField exposing ( Model , Msg(..) + , ViewSettings , emptyModel , getContacts , update @@ -11,6 +12,7 @@ import Api.Model.Contact exposing (Contact) import Comp.Basic as B import Comp.FixedDropdown import Data.ContactType exposing (ContactType) +import Data.DropdownStyle as DS import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) @@ -30,7 +32,7 @@ emptyModel : Model emptyModel = { items = [] , kind = - Comp.FixedDropdown.initMap Data.ContactType.toString Data.ContactType.all + Comp.FixedDropdown.init Data.ContactType.all , selectedKind = List.head Data.ContactType.all , value = "" } @@ -41,13 +43,6 @@ getContacts model = List.filter (\c -> c.value /= "") model.items -makeDropdownItem : ContactType -> Comp.FixedDropdown.Item ContactType -makeDropdownItem ct = - { id = ct - , display = Data.ContactType.toString ct - } - - type Msg = SetValue String | TypeMsg (Comp.FixedDropdown.Msg ContactType) @@ -121,19 +116,34 @@ update msg model = --- View2 -view2 : Bool -> UiSettings -> Model -> Html Msg -view2 mobile _ model = +type alias ViewSettings = + { contactTypeLabel : ContactType -> String + , mobile : Bool + } + + +view2 : ViewSettings -> UiSettings -> Model -> Html Msg +view2 cfg _ model = + let + kindCfg = + { display = cfg.contactTypeLabel + , icon = \_ -> Nothing + , style = DS.mainStyle + } + in div [ class "flex flex-col" ] [ div [ class "flex flex-col space-y-2" - , classList [ ( " md:flex-row md:space-y-0 md:space-x-2", not mobile ) ] + , classList [ ( " md:flex-row md:space-y-0 md:space-x-2", not cfg.mobile ) ] ] [ div - [ classList [ ( "flex-none md:w-1/6", not mobile ) ] + [ classList [ ( "flex-none md:w-1/6", not cfg.mobile ) ] ] [ Html.map TypeMsg - (Comp.FixedDropdown.view2 - (Maybe.map makeDropdownItem model.selectedKind) + (Comp.FixedDropdown.viewStyled2 + kindCfg + False + model.selectedKind model.kind ) ] @@ -160,7 +170,7 @@ view2 mobile _ model = ] , class "flex flex-col space-y-2 mt-2 px-2 border-0 border-l dark:border-bluegray-600 " ] - (List.map (renderItem2 mobile) model.items) + (List.map (renderItem2 cfg.mobile) model.items) ] diff --git a/modules/webapp/src/main/elm/Comp/CustomFieldForm.elm b/modules/webapp/src/main/elm/Comp/CustomFieldForm.elm index 2881a4dc..ff6f783f 100644 --- a/modules/webapp/src/main/elm/Comp/CustomFieldForm.elm +++ b/modules/webapp/src/main/elm/Comp/CustomFieldForm.elm @@ -23,8 +23,9 @@ import Data.Flags exposing (Flags) import Data.Validated exposing (Validated) import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onClick, onInput) +import Html.Events exposing (onInput) import Http +import Messages.Comp.CustomFieldForm exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -61,8 +62,7 @@ init field = , label = field.label , ftype = Data.CustomFieldType.fromString field.ftype , ftypeModel = - Comp.FixedDropdown.initMap Data.CustomFieldType.label - Data.CustomFieldType.all + Comp.FixedDropdown.init Data.CustomFieldType.all , loading = False , deleteDimmer = Comp.YesNoDimmer.emptyModel } @@ -197,17 +197,22 @@ type alias ViewSettings = --- View2 -view2 : ViewSettings -> Model -> List (Html Msg) -view2 viewSettings model = +view2 : Texts -> ViewSettings -> Model -> List (Html Msg) +view2 texts viewSettings model = let - mkItem cft = - Comp.FixedDropdown.Item cft (Data.CustomFieldType.label cft) - dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this custom field?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteField + texts.basics.yes + texts.basics.no + + ftypeCfg = + { display = texts.fieldTypeLabel + , icon = \_ -> Nothing + , style = DS.mainStyle + } in (if viewSettings.showControls then - [ viewButtons2 model ] + [ viewButtons2 texts model ] else [] @@ -236,20 +241,19 @@ view2 viewSettings model = ] , if model.field.id == "" then div [ class "py-2 text-lg opacity-75" ] - [ text "Create a new custom field." + [ text texts.createCustomField ] else div [ class "py-2 text-lg opacity-75" ] - [ text "Note that changing the format may " - , text "result in invisible values in the ui, if they don't comply to the new format!" + [ text texts.modifyTypeWarning ] , div [ class "mb-4" ] [ label [ class S.inputLabel , for "fieldname" ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input @@ -266,27 +270,25 @@ view2 viewSettings model = ] [] , div [ class "opacity-75 text-sm" ] - [ text "The name uniquely identifies this field. It must be a valid " - , text "identifier, not contain spaces or weird characters." + [ text texts.nameInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Field Format" + [ text texts.fieldFormat , B.inputRequired ] , Html.map FTypeMsg (Comp.FixedDropdown.viewStyled2 - DS.mainStyle + ftypeCfg (model.ftype == Nothing) - (Maybe.map mkItem model.ftype) + model.ftype model.ftypeModel ) , div [ class "opacity-75 text-sm" ] - [ text "A field must have a format. Values are validated " - , text "according to this format." + [ text texts.fieldFormatInfo ] ] , div [ class "mb-4" ] @@ -294,7 +296,7 @@ view2 viewSettings model = [ class S.inputLabel , for "fieldlabel" ] - [ text "Label" ] + [ text texts.label ] , input [ type_ "text" , onInput SetLabel @@ -306,38 +308,37 @@ view2 viewSettings model = ] [] , div [ class "opacity-75 text-sm" ] - [ text "The user defined label for this field. This is used to represent " - , text "this field in the ui. If not present, the name is used." + [ text texts.labelInfo ] ] ] ] -viewButtons2 : Model -> Html Msg -viewButtons2 model = +viewButtons2 : Texts -> Model -> Html Msg +viewButtons2 texts model = MB.view { start = [ MB.PrimaryButton { tagger = SubmitForm - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = GoBack - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if model.field.id /= "" then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this field" + , title = texts.deleteThisField , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] diff --git a/modules/webapp/src/main/elm/Comp/CustomFieldInput.elm b/modules/webapp/src/main/elm/Comp/CustomFieldInput.elm index f725c66d..5183ac00 100644 --- a/modules/webapp/src/main/elm/Comp/CustomFieldInput.elm +++ b/modules/webapp/src/main/elm/Comp/CustomFieldInput.elm @@ -16,12 +16,13 @@ import Comp.DatePicker import Comp.MenuBar as MB import Data.CustomFieldType exposing (CustomFieldType) import Data.Icons as Icons -import Data.Money +import Data.Money exposing (MoneyParseError(..)) import Date exposing (Date) import DatePicker exposing (DatePicker) import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onCheck, onClick, onInput) +import Html.Events exposing (onClick, onInput) +import Messages.Comp.CustomFieldInput exposing (Texts) import Styles as S import Util.Maybe @@ -32,9 +33,15 @@ type alias Model = } +type FieldError + = NoValue + | NotANumber String + | NotMoney MoneyParseError + + type alias FloatModel = { input : String - , result : Result String Float + , result : Result FieldError Float } @@ -61,27 +68,47 @@ fieldType field = |> Maybe.withDefault Data.CustomFieldType.Text -errorMsg : Model -> Maybe String -errorMsg model = +errorMsg : Texts -> Model -> Maybe String +errorMsg texts model = let - getMsg res = - case res of - Ok _ -> - Nothing + parseMsg isMoneyField perr = + case perr of + NoValue -> + if isMoneyField then + Just <| texts.errorNoAmount - Err m -> - Just m + else + Just <| texts.errorNoNumber + + NotANumber str -> + Just <| texts.errorNotANumber str + + NotMoney (RequireTwoDigitsAfterDot _) -> + Just "Two digits required after the dot." + + NotMoney (NoOrTooManyPoints _) -> + Just "One single dot + digits required for money." in case model.fieldModel of NumberField fm -> - getMsg fm.result + case fm.result of + Ok _ -> + Nothing + + Err parseError -> + parseMsg False parseError MoneyField fm -> - getMsg fm.result + case fm.result of + Ok _ -> + Nothing + + Err parseError -> + parseMsg True parseError TextField mt -> if mt == Nothing then - Just "Please fill in some value" + Just texts.errorNoValue else Nothing @@ -103,10 +130,10 @@ init field = TextField Nothing Data.CustomFieldType.Numeric -> - NumberField (FloatModel "" (Err "No number given")) + NumberField (FloatModel "" (Err NoValue)) Data.CustomFieldType.Money -> - MoneyField (FloatModel "" (Err "No amount given")) + MoneyField (FloatModel "" (Err NoValue)) Data.CustomFieldType.Boolean -> BoolField False @@ -150,7 +177,7 @@ initWith value = updateFloatModel False value.value - Data.Money.fromString + (Data.Money.fromString >> Result.mapError NotMoney) Data.Money.normalizeInput in MoneyField fm @@ -230,7 +257,7 @@ update1 forSearch msg model = updateFloatModel forSearch str - Data.Money.fromString + (Data.Money.fromString >> Result.mapError NotMoney) Data.Money.normalizeInput model_ = @@ -294,7 +321,7 @@ update1 forSearch msg model = updateFloatModel : Bool -> String - -> (String -> Result String Float) + -> (String -> Result FieldError Float) -> (String -> String) -> ( FloatModel, FieldResult ) updateFloatModel forSearch msg parse normalize = @@ -331,11 +358,11 @@ hasWildCards msg = --- View2 -view2 : String -> Maybe String -> Model -> Html Msg -view2 classes icon model = +view2 : Texts -> String -> Maybe String -> Model -> Html Msg +view2 texts classes icon model = let error = - errorMsg model + errorMsg texts model in div [ class classes @@ -473,11 +500,11 @@ mkLabel model = Maybe.withDefault model.field.name model.field.label -string2Float : String -> Result String Float +string2Float : String -> Result FieldError Float string2Float str = case String.toFloat str of Just n -> Ok n Nothing -> - Err ("Not a number: " ++ str) + Err (NotANumber str) diff --git a/modules/webapp/src/main/elm/Comp/CustomFieldManage.elm b/modules/webapp/src/main/elm/Comp/CustomFieldManage.elm index b6c596da..37965d9f 100644 --- a/modules/webapp/src/main/elm/Comp/CustomFieldManage.elm +++ b/modules/webapp/src/main/elm/Comp/CustomFieldManage.elm @@ -17,8 +17,8 @@ import Comp.MenuBar as MB import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onClick, onInput) import Http +import Messages.Comp.CustomFieldManage exposing (Texts) import Styles as S import Util.CustomField @@ -135,18 +135,18 @@ update flags msg model = --- View2 -view2 : Flags -> Model -> Html Msg -view2 flags model = +view2 : Texts -> Flags -> Model -> Html Msg +view2 texts flags model = case model.detailModel of Just dm -> - viewDetail2 flags dm + viewDetail2 texts flags dm Nothing -> - viewTable2 model + viewTable2 texts model -viewDetail2 : Flags -> Comp.CustomFieldForm.Model -> Html Msg -viewDetail2 _ detailModel = +viewDetail2 : Texts -> Flags -> Comp.CustomFieldForm.Model -> Html Msg +viewDetail2 texts _ detailModel = let viewSettings = { showControls = True @@ -156,44 +156,55 @@ viewDetail2 _ detailModel = div [] ((if detailModel.field.id == "" then h3 [ class S.header2 ] - [ text "Create new custom field" + [ text texts.newCustomField ] else h3 [ class S.header2 ] [ Util.CustomField.nameOrLabel detailModel.field |> text , div [ class "opacity-50 text-sm" ] - [ text "Id: " + [ text (texts.basics.id ++ ": ") , text detailModel.field.id ] ] ) - :: List.map (Html.map DetailMsg) (Comp.CustomFieldForm.view2 viewSettings detailModel) + :: List.map (Html.map DetailMsg) + (Comp.CustomFieldForm.view2 texts.fieldForm + viewSettings + detailModel + ) ) -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col md:relative" ] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNewCustomField - , title = "Add a new custom field" + , title = texts.addCustomField , icon = Just "fa fa-plus" - , label = "New custom field" + , label = texts.newCustomField } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.CustomFieldTable.view2 model.tableModel model.fields) - , B.loadingDimmer model.loading + , Html.map TableMsg + (Comp.CustomFieldTable.view2 texts.fieldTable + model.tableModel + model.fields + ) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/CustomFieldMultiInput.elm b/modules/webapp/src/main/elm/Comp/CustomFieldMultiInput.elm index 73c8981a..51dbf2d4 100644 --- a/modules/webapp/src/main/elm/Comp/CustomFieldMultiInput.elm +++ b/modules/webapp/src/main/elm/Comp/CustomFieldMultiInput.elm @@ -29,6 +29,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Http +import Messages.Comp.CustomFieldMultiInput exposing (Texts) import Styles as S import Util.CustomField import Util.Maybe @@ -130,7 +131,7 @@ reset model = mkFieldSelect : List CustomField -> FieldSelect mkFieldSelect fields = { selected = Nothing - , dropdown = Comp.FixedDropdown.init (List.map mkItem fields) + , dropdown = Comp.FixedDropdown.init fields } @@ -145,11 +146,6 @@ type alias UpdateResult = } -mkItem : CustomField -> Comp.FixedDropdown.Item CustomField -mkItem f = - Comp.FixedDropdown.Item f (Maybe.withDefault f.name f.label) - - update : Flags -> Msg -> Model -> UpdateResult update = update1 False @@ -318,25 +314,33 @@ type alias ViewSettings = { showAddButton : Bool , classes : String , fieldIcon : CustomField -> Maybe String + , style : DS.DropdownStyle + , createCustomFieldTitle : String } -view2 : DS.DropdownStyle -> ViewSettings -> Model -> Html Msg -view2 ddstyle viewSettings model = +view2 : Texts -> ViewSettings -> Model -> Html Msg +view2 texts viewSettings model = div [ class viewSettings.classes ] - (viewMenuBar2 ddstyle viewSettings model - :: List.map (viewCustomField2 viewSettings model) (visibleFields model) + (viewMenuBar2 viewSettings model + :: List.map (viewCustomField2 texts viewSettings model) (visibleFields model) ) -viewMenuBar2 : DS.DropdownStyle -> ViewSettings -> Model -> Html Msg -viewMenuBar2 ddstyle viewSettings model = +viewMenuBar2 : ViewSettings -> Model -> Html Msg +viewMenuBar2 viewSettings model = let { dropdown, selected } = model.fieldSelect + ddstyle = + viewSettings.style + ddstyleFlex = - { ddstyle | root = ddstyle.root ++ " flex-grow" } + { display = \f -> Maybe.withDefault f.name f.label + , icon = \_ -> Nothing + , style = { ddstyle | root = ddstyle.root ++ " flex-grow" } + } in div [ classList @@ -348,11 +352,11 @@ viewMenuBar2 ddstyle viewSettings model = (Comp.FixedDropdown.viewStyled2 ddstyleFlex False - (Maybe.map mkItem selected) + selected dropdown ) :: (if viewSettings.showAddButton then - [ addFieldLink2 "ml-1" model + [ addFieldLink2 viewSettings.createCustomFieldTitle "ml-1" model ] else @@ -361,8 +365,8 @@ viewMenuBar2 ddstyle viewSettings model = ) -viewCustomField2 : ViewSettings -> Model -> CustomField -> Html Msg -viewCustomField2 viewSettings model field = +viewCustomField2 : Texts -> ViewSettings -> Model -> CustomField -> Html Msg +viewCustomField2 texts viewSettings model field = let visibleField = Dict.get field.name model.visibleFields @@ -370,7 +374,8 @@ viewCustomField2 viewSettings model field = case visibleField of Just vf -> Html.map (CustomFieldInputMsg field) - (Comp.CustomFieldInput.view2 "mt-2" + (Comp.CustomFieldInput.view2 texts.customFieldInput + "mt-2" (viewSettings.fieldIcon vf.field) vf.inputModel ) @@ -379,8 +384,8 @@ viewCustomField2 viewSettings model field = span [] [] -addFieldLink2 : String -> Model -> Html Msg -addFieldLink2 classes _ = +addFieldLink2 : String -> String -> Model -> Html Msg +addFieldLink2 titleStr classes _ = a [ class classes , class S.secondaryButton @@ -388,7 +393,7 @@ addFieldLink2 classes _ = -- , class "absolute -right-12 top-0" , href "#" , onClick CreateNewField - , title "Create a new custom field" + , title titleStr ] [ i [ class "fa fa-plus" ] [] ] diff --git a/modules/webapp/src/main/elm/Comp/CustomFieldTable.elm b/modules/webapp/src/main/elm/Comp/CustomFieldTable.elm index 890fc0d1..cb51674f 100644 --- a/modules/webapp/src/main/elm/Comp/CustomFieldTable.elm +++ b/modules/webapp/src/main/elm/Comp/CustomFieldTable.elm @@ -11,7 +11,7 @@ import Api.Model.CustomField exposing (CustomField) import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onClick) +import Messages.Comp.CustomFieldTable exposing (Texts) import Styles as S import Util.Time @@ -45,17 +45,17 @@ update msg model = --- View2 -view2 : Model -> List CustomField -> Html Msg -view2 _ items = +view2 : Texts -> Model -> List CustomField -> Html Msg +view2 texts _ items = div [] [ table [ class S.tableMain ] [ thead [] [ tr [] [ th [] [] - , th [ class "text-left" ] [ text "Name/Label" ] - , th [ class "text-left" ] [ text "Format" ] - , th [ class "text-center hidden sm:table-cell" ] [ text "#Usage" ] - , th [ class "text-center hidden sm:table-cell" ] [ text "Created" ] + , th [ class "text-left" ] [ text texts.nameLabel ] + , th [ class "text-left" ] [ text texts.format ] + , th [ class "text-center hidden sm:table-cell" ] [ text texts.usageCount ] + , th [ class "text-center hidden sm:table-cell" ] [ text texts.basics.created ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/DetailEdit.elm b/modules/webapp/src/main/elm/Comp/DetailEdit.elm index 83950bff..a57770d7 100644 --- a/modules/webapp/src/main/elm/Comp/DetailEdit.elm +++ b/modules/webapp/src/main/elm/Comp/DetailEdit.elm @@ -47,6 +47,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Http +import Messages.Comp.DetailEdit exposing (Texts) import Styles as S import Util.Http @@ -639,10 +640,10 @@ update flags msg model = --- View2 -view2 : List (Attribute Msg) -> UiSettings -> Model -> Html Msg -view2 attr settings model = +view2 : Texts -> List (Attribute Msg) -> UiSettings -> Model -> Html Msg +view2 texts attr settings model = div attr - (viewIntern2 settings True model) + (viewIntern2 texts settings True model) formHeading : String -> Model -> Html msg @@ -668,8 +669,8 @@ formHeading classes model = ] -viewModal2 : UiSettings -> Maybe Model -> Html Msg -viewModal2 settings mm = +viewModal2 : Texts -> UiSettings -> Maybe Model -> Html Msg +viewModal2 texts settings mm = let hidden = mm == Nothing @@ -710,7 +711,7 @@ viewModal2 settings mm = , div [ class "scrolling content" ] (case mm of Just model -> - viewIntern2 settings False model + viewIntern2 texts settings False model Nothing -> [] @@ -718,7 +719,7 @@ viewModal2 settings mm = , div [ class "flex flex-row space-x-2" ] (case mm of Just model -> - viewButtons2 model + viewButtons2 texts model Nothing -> [] @@ -727,10 +728,10 @@ viewModal2 settings mm = ] -viewButtons2 : Model -> List (Html Msg) -viewButtons2 model = +viewButtons2 : Texts -> Model -> List (Html Msg) +viewButtons2 texts model = [ B.primaryButton - { label = "Submit" + { label = texts.basics.submit , icon = if model.submitting || model.loading then "fa fa-circle-notch animate-spin" @@ -742,7 +743,7 @@ viewButtons2 model = , attrs = [ href "#" ] } , B.secondaryButton - { label = "Cancel" + { label = texts.basics.cancel , handler = onClick Cancel , disabled = False , icon = "fa fa-times" @@ -751,8 +752,8 @@ viewButtons2 model = ] -viewIntern2 : UiSettings -> Bool -> Model -> List (Html Msg) -viewIntern2 settings withButtons model = +viewIntern2 : Texts -> UiSettings -> Bool -> Model -> List (Html Msg) +viewIntern2 texts settings withButtons model = [ div [ classList [ ( S.errorMessage, Maybe.map .success model.result == Just False ) @@ -766,24 +767,25 @@ viewIntern2 settings withButtons model = ] , case model.form of TM tm -> - Html.map TagMsg (Comp.TagForm.view2 tm) + Html.map TagMsg (Comp.TagForm.view2 texts.tagForm tm) PMR pm -> - Html.map PersonMsg (Comp.PersonForm.view2 True settings pm) + Html.map PersonMsg (Comp.PersonForm.view2 texts.personForm True settings pm) PMC pm -> - Html.map PersonMsg (Comp.PersonForm.view2 True settings pm) + Html.map PersonMsg (Comp.PersonForm.view2 texts.personForm True settings pm) OM om -> - Html.map OrgMsg (Comp.OrgForm.view2 True settings om) + Html.map OrgMsg (Comp.OrgForm.view2 texts.orgForm True settings om) EM em -> - Html.map EquipMsg (Comp.EquipmentForm.view2 em) + Html.map EquipMsg (Comp.EquipmentForm.view2 texts.equipmentForm em) CFM fm -> div [] (List.map (Html.map CustomFieldMsg) (Comp.CustomFieldForm.view2 + texts.customFieldForm { classes = "" , showControls = False } @@ -793,7 +795,7 @@ viewIntern2 settings withButtons model = ] ++ (if withButtons then [ div [ class "flex flex-row space-x-2" ] - (viewButtons2 model) + (viewButtons2 texts model) ] else diff --git a/modules/webapp/src/main/elm/Comp/Dropdown.elm b/modules/webapp/src/main/elm/Comp/Dropdown.elm index 5da93ae2..9e1b19e0 100644 --- a/modules/webapp/src/main/elm/Comp/Dropdown.elm +++ b/modules/webapp/src/main/elm/Comp/Dropdown.elm @@ -2,6 +2,7 @@ module Comp.Dropdown exposing ( Model , Msg(..) , Option + , ViewSettings , getSelected , isDropdownChangeMsg , makeModel @@ -10,16 +11,13 @@ module Comp.Dropdown exposing , makeSingleList , mkOption , notSelected - , orgDropdown + , orgFormViewSettings , setMkOption , update , view2 , viewSingle2 ) -{-| This needs to be rewritten from scratch! --} - import Api.Model.IdName exposing (IdName) import Data.DropdownStyle as DS import Data.UiSettings exposing (UiSettings) @@ -31,32 +29,8 @@ import Util.Html exposing (onKeyUp) import Util.List -orgDropdown : Model IdName -orgDropdown = - makeModel - { multiple = False - , searchable = \n -> n > 0 - , makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , labelColor = \_ -> \_ -> "" - , placeholder = "Choose an organization" - } - - -type alias Option = - { value : String - , text : String - , additional : String - } - - -mkOption : String -> String -> Option -mkOption value text = - Option value text "" - - type alias Item a = { value : a - , option : Option , visible : Bool , selected : Bool , active : Bool @@ -66,7 +40,6 @@ type alias Item a = makeItem : Model a -> a -> Item a makeItem model val = { value = val - , option = model.makeOption val , visible = True , selected = List.any (\i -> i.value == val) model.selected @@ -78,26 +51,15 @@ type alias Model a = { multiple : Bool , selected : List (Item a) , available : List (Item a) - , makeOption : a -> Option , menuOpen : Bool , filterString : String - , labelColor : a -> UiSettings -> String , searchable : Int -> Bool - , placeholder : String } -setMkOption : (a -> Option) -> Model a -> Model a -setMkOption mkopt model = - { model | makeOption = mkopt } - - makeModel : { multiple : Bool , searchable : Int -> Bool - , makeOption : a -> Option - , labelColor : a -> UiSettings -> String - , placeholder : String } -> Model a makeModel input = @@ -105,45 +67,28 @@ makeModel input = , searchable = input.searchable , selected = [] , available = [] - , makeOption = input.makeOption , menuOpen = False , filterString = "" - , labelColor = input.labelColor - , placeholder = input.placeholder } -makeSingle : - { makeOption : a -> Option - , placeholder : String - } - -> Model a -makeSingle opts = +makeSingle : Model a +makeSingle = makeModel { multiple = False , searchable = \n -> n > 0 - , makeOption = opts.makeOption - , labelColor = \_ -> \_ -> "" - , placeholder = - if opts.placeholder == "" then - "Select…" - - else - opts.placeholder } makeSingleList : - { makeOption : a -> Option - , placeholder : String - , options : List a + { options : List a , selected : Maybe a } -> Model a makeSingleList opts = let m = - makeSingle { makeOption = opts.makeOption, placeholder = opts.placeholder } + makeSingle m2 = { m | available = List.map (makeItem m) opts.options } @@ -156,18 +101,11 @@ makeSingleList opts = m3 -makeMultiple : - { makeOption : a -> Option - , labelColor : a -> UiSettings -> String - } - -> Model a -makeMultiple opts = +makeMultiple : Model a +makeMultiple = makeModel { multiple = True , searchable = \n -> n > 0 - , makeOption = opts.makeOption - , labelColor = opts.labelColor - , placeholder = "" } @@ -186,9 +124,8 @@ type Msg a | SetSelection (List a) | ToggleMenu | AddItem (Item a) - | RemoveItem (Item a) | RemoveItem2 (Item a) - | Filter String + | Filter (a -> String) String | ShowMenu Bool | KeyPress Int @@ -215,17 +152,17 @@ deselectItem : Model a -> Item a -> Model a deselectItem model item = let value = - item.option.value + item.value sel = if model.multiple then - List.filter (\e -> e.option.value /= value) model.selected + List.filter (\e -> e.value /= value) model.selected else [] show e = - if e.option.value == value then + if e.value == value then { e | selected = False } else @@ -241,7 +178,7 @@ selectItem : Model a -> Item a -> Model a selectItem model item = let value = - item.option.value + item.value sel = if model.multiple then @@ -251,7 +188,7 @@ selectItem model item = [ item ] hide e = - if e.option.value == value then + if e.value == value then { e | selected = True } else if model.multiple then @@ -266,13 +203,13 @@ selectItem model item = { model | selected = sel, available = avail } -filterOptions : String -> List (Item a) -> List (Item a) -filterOptions str list = - List.map (\e -> { e | visible = Simple.Fuzzy.match str e.option.text, active = False }) list +filterOptions : String -> (a -> String) -> List (Item a) -> List (Item a) +filterOptions str mkText list = + List.map (\e -> { e | visible = Simple.Fuzzy.match str (mkText e.value), active = False }) list -applyFilter : String -> Model a -> Model a -applyFilter str model = +applyFilter : String -> (a -> String) -> Model a -> Model a +applyFilter str mkText model = let selected = if str /= "" && not model.multiple then @@ -281,7 +218,12 @@ applyFilter str model = else model.selected in - { model | filterString = str, available = filterOptions str model.available, selected = selected } + { model | filterString = str, available = filterOptions str mkText model.available, selected = selected } + + +clearFilter : Model a -> Model a +clearFilter model = + { model | filterString = "" } makeNextActive : (Int -> Int) -> Model a -> Model a @@ -299,7 +241,7 @@ makeNextActive nextEl model = |> Maybe.andThen (Util.List.get opts) merge item1 item2 = - { item2 | active = item1.option.value == item2.option.value } + { item2 | active = item1.value == item2.value } updateModel item = { model | available = List.map (merge item) model.available, menuOpen = True } @@ -325,7 +267,7 @@ selectActive model = in case current of Just item -> - selectItem model item |> applyFilter "" + selectItem model item |> clearFilter Nothing -> model @@ -337,9 +279,6 @@ isDropdownChangeMsg cm = AddItem _ -> True - RemoveItem _ -> - True - RemoveItem2 _ -> True @@ -375,34 +314,23 @@ update msg model = AddItem e -> let m = - selectItem model e |> applyFilter "" + selectItem model e |> clearFilter in ( { m | menuOpen = False }, Cmd.none ) - RemoveItem e -> - let - m = - deselectItem model e |> applyFilter "" - in - ( -- Setting to True, because parent click sets it to False… ugly - { m | menuOpen = True } - , Cmd.none - ) - RemoveItem2 e -> let m = - deselectItem model e |> applyFilter "" + deselectItem model e |> clearFilter in - ( -- Hack above only needed with semanticui - m + ( m , Cmd.none ) - Filter str -> + Filter f str -> let m = - applyFilter str model + applyFilter str f model in ( { m | menuOpen = True }, Cmd.none ) @@ -438,7 +366,7 @@ update msg model = [ e ] -> let ( m_, c_ ) = - update (RemoveItem e) model + update (RemoveItem2 e) model in ( { m_ | menuOpen = False }, c_ ) @@ -463,32 +391,65 @@ update msg model = -- View2 -view2 : DS.DropdownStyle -> UiSettings -> Model a -> Html (Msg a) -view2 style settings model = +type alias Option = + { text : String + , additional : String + } + + +mkOption : String -> Option +mkOption text = + Option text "" + + +type alias ViewSettings a = + { makeOption : a -> Option + , placeholder : String + , labelColor : a -> UiSettings -> String + , style : DS.DropdownStyle + } + + +orgFormViewSettings : String -> DS.DropdownStyle -> ViewSettings IdName +orgFormViewSettings placeholder ds = + { makeOption = \e -> { text = e.name, additional = "" } + , labelColor = \_ -> \_ -> "" + , placeholder = placeholder + , style = ds + } + + +setMkOption : (a -> Option) -> ViewSettings a -> ViewSettings a +setMkOption mkopt model = + { model | makeOption = mkopt } + + +view2 : ViewSettings a -> UiSettings -> Model a -> Html (Msg a) +view2 cfg settings model = if model.multiple then - viewMultiple2 style settings model + viewMultiple2 cfg settings model else - viewSingle2 style model + viewSingle2 cfg model -viewSingle2 : DS.DropdownStyle -> Model a -> Html (Msg a) -viewSingle2 style model = +viewSingle2 : ViewSettings a -> Model a -> Html (Msg a) +viewSingle2 cfg model = let renderItem item = a [ href "#" - , class style.item + , class cfg.style.item , classList - [ ( style.itemActive, item.active ) + [ ( cfg.style.itemActive, item.active ) , ( "font-semibold", item.selected ) ] , onClick (AddItem item) , onKeyUp KeyPress ] - [ text item.option.text + [ text <| (.value >> cfg.makeOption >> .text) item , span [ class "text-gray-400 float-right" ] - [ text item.option.additional + [ text <| (.value >> cfg.makeOption >> .additional) item ] ] @@ -500,7 +461,7 @@ viewSingle2 style model = , onKeyUp KeyPress ] [ div - [ class style.link + [ class cfg.style.link ] [ a [ class "flex-grow" @@ -514,8 +475,8 @@ viewSingle2 style model = , onClick ToggleMenu , href "#" ] - [ Maybe.map (.option >> .text) sel - |> Maybe.withDefault model.placeholder + [ Maybe.map (.value >> cfg.makeOption >> .text) sel + |> Maybe.withDefault cfg.placeholder |> text ] , a @@ -532,11 +493,11 @@ viewSingle2 style model = ] , input [ type_ "text" - , placeholder model.placeholder - , onInput Filter + , placeholder cfg.placeholder + , onInput (Filter (cfg.makeOption >> .text)) , value model.filterString , class "inline-block border-0 px-0 w-full py-0 focus:ring-0 " - , class style.input + , class cfg.style.input , classList [ ( "hidden", not (model.menuOpen && isSearchable model) ) ] ] [] @@ -550,43 +511,43 @@ viewSingle2 style model = ] ] , div - [ class style.menu + [ class cfg.style.menu , classList [ ( "hidden", not model.menuOpen ) ] ] (getOptions model |> List.map renderItem) ] -viewMultiple2 : DS.DropdownStyle -> UiSettings -> Model a -> Html (Msg a) -viewMultiple2 style settings model = +viewMultiple2 : ViewSettings a -> UiSettings -> Model a -> Html (Msg a) +viewMultiple2 cfg settings model = let renderItem item = a [ href "#" - , class style.item + , class cfg.style.item , classList - [ ( style.itemActive, item.active ) + [ ( cfg.style.itemActive, item.active ) , ( "font-semibold", item.selected ) ] , onClick (AddItem item) , onKeyUp KeyPress ] - [ text item.option.text + [ text <| (.value >> cfg.makeOption >> .text) item , span [ class "text-gray-400 float-right" ] - [ text item.option.additional + [ text <| (.value >> cfg.makeOption >> .additional) item ] ] renderSelectMultiple : Item a -> Html (Msg a) renderSelectMultiple item = a - [ class (model.labelColor item.value settings) + [ class (cfg.labelColor item.value settings) , class "label font-medium inline-flex relative items-center hover:shadow-md mt-1 mr-1" - , onClick (RemoveItem item) + , onClick (RemoveItem2 item) , href "#" ] [ span [ class "pl-4" ] - [ text item.option.text + [ text <| (.value >> cfg.makeOption >> .text) item ] , span [ class "opacity-75 absolute left-2 my-auto" ] [ i [ class "fa fa-times" ] [] @@ -598,7 +559,7 @@ viewMultiple2 style settings model = , onKeyUp KeyPress ] [ div - [ class style.link + [ class cfg.style.link , class "flex inline-flex flex-wrap items-center" ] [ div @@ -609,10 +570,10 @@ viewMultiple2 style settings model = , input [ type_ "text" , placeholder "Search…" - , onInput Filter + , onInput (Filter (cfg.makeOption >> .text)) , value model.filterString , class "inline-flex w-16 border-0 px-0 focus:ring-0 h-6" - , class style.input + , class cfg.style.input ] [] , a @@ -629,7 +590,7 @@ viewMultiple2 style settings model = ] ] , div - [ class style.menu + [ class cfg.style.menu , classList [ ( "hidden", not model.menuOpen ) ] ] (getOptions model |> List.map renderItem) diff --git a/modules/webapp/src/main/elm/Comp/Dropzone.elm b/modules/webapp/src/main/elm/Comp/Dropzone.elm index e8a8b71a..527d4471 100644 --- a/modules/webapp/src/main/elm/Comp/Dropzone.elm +++ b/modules/webapp/src/main/elm/Comp/Dropzone.elm @@ -18,6 +18,7 @@ import File.Select import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (..) +import Messages.Comp.Dropzone exposing (Texts) import Styles as S import Util.Html exposing (onDragEnter, onDragLeave, onDragOver, onDropFiles) @@ -124,8 +125,8 @@ filterMime model files = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = div [ classList [ ( "bg-opacity-100 bg-blue-100 dark:bg-lightblue-800", model.state.hover ) @@ -144,24 +145,23 @@ view2 model = ] [ i [ class "fa fa-mouse-pointer" ] [] , div [ class "ml-3" ] - [ text "Drop files here" + [ text texts.dropFilesHere ] ] , B.horizontalDivider - { label = "Or" + { label = texts.or , topCss = "w-2/3 mb-4 hidden md:inline-flex" , labelCss = "px-4 bg-gray-200 bg-opacity-50" , lineColor = "bg-gray-300 dark:bg-bluegray-600" } , B.primaryBasicButton - { label = "Select ..." + { label = texts.select , icon = "fa fa-folder-open font-thin" , handler = onClick PickFiles , attrs = [ href "#" ] , disabled = not model.state.active } , div [ class "text-center opacity-75 text-sm mt-4" ] - [ text "Choose document files (pdf, docx, txt, html, …). " - , text "Archives (zip and eml) are extracted." + [ text texts.selectInfo ] ] diff --git a/modules/webapp/src/main/elm/Comp/EmailInput.elm b/modules/webapp/src/main/elm/Comp/EmailInput.elm index 67cfe6a9..92b5cca6 100644 --- a/modules/webapp/src/main/elm/Comp/EmailInput.elm +++ b/modules/webapp/src/main/elm/Comp/EmailInput.elm @@ -1,6 +1,7 @@ module Comp.EmailInput exposing ( Model , Msg + , ViewSettings , init , update , view2 @@ -137,10 +138,16 @@ update flags current msg model = --- View2 -view2 : DS.DropdownStyle -> List String -> Model -> Html Msg -view2 style values model = +type alias ViewSettings = + { placeholder : String + , style : DS.DropdownStyle + } + + +view2 : ViewSettings -> List String -> Model -> Html Msg +view2 cfg values model = div [ class "text-sm flex-row space-x-2 relative" ] - [ div [ class style.link ] + [ div [ class cfg.style.link ] [ div [ class "flex flex-row space-x-2 mr-2" , classList [ ( "hidden", List.isEmpty values ) ] @@ -149,7 +156,7 @@ view2 style values model = , input [ type_ "text" , value model.input - , placeholder "Recipients…" + , placeholder cfg.placeholder , onKeyUp KeyPress , onInput SetInput , class "inline-flex w-24 border-0 px-0 focus:ring-0 h-6 text-sm" @@ -157,7 +164,7 @@ view2 style values model = ] [] ] - , renderMenu2 style model + , renderMenu2 cfg.style model ] diff --git a/modules/webapp/src/main/elm/Comp/EmailSettingsForm.elm b/modules/webapp/src/main/elm/Comp/EmailSettingsForm.elm index 3045d045..11d2f975 100644 --- a/modules/webapp/src/main/elm/Comp/EmailSettingsForm.elm +++ b/modules/webapp/src/main/elm/Comp/EmailSettingsForm.elm @@ -21,6 +21,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.EmailSettingsForm exposing (Texts) import Styles as S import Util.Maybe @@ -46,7 +47,7 @@ emptyModel = { settings = Api.Model.EmailSettings.empty , name = "" , host = "" - , portField = Comp.IntField.init (Just 0) Nothing True "SMTP Port" + , portField = Comp.IntField.init (Just 0) Nothing True , portNum = Nothing , user = Nothing , passField = Comp.PasswordInput.init @@ -55,14 +56,7 @@ emptyModel = , replyTo = Nothing , sslType = Comp.Dropdown.makeSingleList - { makeOption = - \s -> - { value = Data.SSLType.toString s - , text = Data.SSLType.label s - , additional = "" - } - , placeholder = "" - , options = Data.SSLType.all + { options = Data.SSLType.all , selected = Just Data.SSLType.None } , ignoreCertificates = False @@ -74,7 +68,7 @@ init ems = { settings = ems , name = ems.name , host = ems.smtpHost - , portField = Comp.IntField.init (Just 0) Nothing True "SMTP Port" + , portField = Comp.IntField.init (Just 0) Nothing True , portNum = ems.smtpPort , user = ems.smtpUser , passField = Comp.PasswordInput.init @@ -83,14 +77,7 @@ init ems = , replyTo = ems.replyTo , sslType = Comp.Dropdown.makeSingleList - { makeOption = - \s -> - { value = Data.SSLType.toString s - , text = Data.SSLType.label s - , additional = "" - } - , placeholder = "" - , options = Data.SSLType.all + { options = Data.SSLType.all , selected = Data.SSLType.fromString ems.sslType |> Maybe.withDefault Data.SSLType.None @@ -184,21 +171,33 @@ update msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = + let + sslCfg = + { makeOption = + \s -> + { text = texts.sslTypeLabel s + , additional = "" + } + , placeholder = "" + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in div [ class "grid grid-cols-4 gap-y-4 gap-x-2" ] [ div [ class "col-span-4" ] [ label [ class S.inputLabel ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , value model.name , onInput SetName - , placeholder "Connection name, e.g. 'gmail.com'" + , placeholder texts.connectionPlaceholder , class S.textInput , classList [ ( S.inputErrorBorder, model.name == "" ) ] ] @@ -207,17 +206,17 @@ view2 settings model = [ class S.message , class "mt-2" ] - [ text "The connection name must not contain whitespace or special characters." + [ text texts.connectionNameInfo ] ] , div [ class "col-span-3" ] [ label [ class S.inputLabel ] - [ text "SMTP Host" + [ text texts.smtpHost , B.inputRequired ] , input [ type_ "text" - , placeholder "SMTP host name, e.g. 'mail.gmail.com'" + , placeholder texts.smtpHostPlaceholder , value model.host , onInput SetHost , class S.textInput @@ -226,20 +225,23 @@ view2 settings model = [] ] , Html.map PortMsg - (Comp.IntField.viewWithInfo2 "" - model.portNum - "" + (Comp.IntField.view + { label = texts.smtpPort + , info = "" + , number = model.portNum + , classes = "" + } model.portField ) , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "SMTP User" + [ text texts.smtpUser ] , input [ type_ "text" - , placeholder "SMTP Username, e.g. 'your.name@gmail.com'" + , placeholder texts.smtpUserPlaceholder , Maybe.withDefault "" model.user |> value , onInput SetUser , class S.textInput @@ -248,10 +250,11 @@ view2 settings model = ] , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "SMTP Password" + [ text texts.smtpPassword ] , Html.map PassMsg (Comp.PasswordInput.view2 + { placeholder = texts.smtpPasswordPlaceholder } model.password False model.passField @@ -259,12 +262,12 @@ view2 settings model = ] , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "From Address" + [ text texts.fromAddress , B.inputRequired ] , input [ type_ "text" - , placeholder "Sender E-Mail address" + , placeholder texts.fromAddressPlaceholder , value model.from , onInput SetFrom , class S.textInput @@ -274,11 +277,11 @@ view2 settings model = ] , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "Reply-To" + [ text texts.replyTo ] , input [ type_ "text" - , placeholder "Optional reply-to E-Mail address" + , placeholder texts.replyToPlaceholder , Maybe.withDefault "" model.replyTo |> value , onInput SetReplyTo , class S.textInput @@ -287,11 +290,11 @@ view2 settings model = ] , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "SSL" + [ text texts.ssl ] , Html.map SSLTypeMsg (Comp.Dropdown.view2 - DS.mainStyle + sslCfg settings model.sslType ) @@ -300,7 +303,7 @@ view2 settings model = [ MB.viewItem <| MB.Checkbox { tagger = \_ -> ToggleCheckCert - , label = "Ignore certificate check" + , label = texts.ignoreCertCheck , value = model.ignoreCertificates , id = "smpt-no-cert-check" } diff --git a/modules/webapp/src/main/elm/Comp/EmailSettingsManage.elm b/modules/webapp/src/main/elm/Comp/EmailSettingsManage.elm index 97c5c46d..4e8d0c70 100644 --- a/modules/webapp/src/main/elm/Comp/EmailSettingsManage.elm +++ b/modules/webapp/src/main/elm/Comp/EmailSettingsManage.elm @@ -21,6 +21,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Http +import Messages.Comp.EmailSettingsManage exposing (Texts) import Styles as S import Util.Http @@ -206,71 +207,76 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = case model.viewMode of Table -> - viewTable2 model + viewTable2 texts model Form -> - viewForm2 settings model + viewForm2 texts settings model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNew - , title = "Add new SMTP settings" + , title = texts.addNewSmtpSettings , icon = Just "fa fa-plus" - , label = "New Settings" + , label = texts.newSettings } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.EmailSettingsTable.view2 model.tableModel) + , Html.map TableMsg + (Comp.EmailSettingsTable.view2 texts.settingsTable + model.tableModel + ) ] -viewForm2 : UiSettings -> Model -> Html Msg -viewForm2 settings model = +viewForm2 : Texts -> UiSettings -> Model -> Html Msg +viewForm2 texts settings model = let dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete these connection?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteConnection + texts.basics.yes + texts.basics.no in div [ class "flex flex-col md:relative" ] [ MB.view { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if model.formModel.settings.name /= "" then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this settings entry" + , title = texts.deleteThisEntry , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -288,12 +294,18 @@ viewForm2 settings model = [ Maybe.withDefault "" model.formError |> text ] , Html.map FormMsg - (Comp.EmailSettingsForm.view2 settings model.formModel) + (Comp.EmailSettingsForm.view2 texts.settingsForm + settings + model.formModel + ) , Html.map YesNoMsg (Comp.YesNoDimmer.viewN True dimmerSettings model.deleteConfirm ) - , B.loadingDimmer model.loading + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/EmailSettingsTable.elm b/modules/webapp/src/main/elm/Comp/EmailSettingsTable.elm index 4cf15b04..44748906 100644 --- a/modules/webapp/src/main/elm/Comp/EmailSettingsTable.elm +++ b/modules/webapp/src/main/elm/Comp/EmailSettingsTable.elm @@ -11,6 +11,7 @@ import Api.Model.EmailSettings exposing (EmailSettings) import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.EmailSettingsTable exposing (Texts) import Styles as S @@ -47,15 +48,15 @@ update msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "" ] [] - , th [ class "text-left mr-2" ] [ text "Name" ] - , th [ class "text-left mr-2" ] [ text "Host/Port" ] - , th [ class "text-left mr-2 hidden sm:table-cell" ] [ text "From" ] + , th [ class "text-left mr-2" ] [ text texts.basics.name ] + , th [ class "text-left mr-2" ] [ text texts.hostPort ] + , th [ class "text-left mr-2 hidden sm:table-cell" ] [ text texts.from ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/EquipmentForm.elm b/modules/webapp/src/main/elm/Comp/EquipmentForm.elm index 2968db76..12764637 100644 --- a/modules/webapp/src/main/elm/Comp/EquipmentForm.elm +++ b/modules/webapp/src/main/elm/Comp/EquipmentForm.elm @@ -11,11 +11,13 @@ module Comp.EquipmentForm exposing import Api.Model.Equipment exposing (Equipment) import Comp.Basic as B import Comp.FixedDropdown +import Data.DropdownStyle as DS import Data.EquipmentUse exposing (EquipmentUse) import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.EquipmentForm exposing (Texts) import Styles as S import Util.Maybe @@ -36,9 +38,7 @@ emptyModel = , notes = Nothing , use = Data.EquipmentUse.Concerning , useModel = - Comp.FixedDropdown.initMap - Data.EquipmentUse.label - Data.EquipmentUse.all + Comp.FixedDropdown.init Data.EquipmentUse.all } @@ -100,21 +100,28 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = + let + equipUseCfg = + { display = texts.equipmentUseLabel + , icon = \_ -> Nothing + , style = DS.mainStyle + } + in div [ class "flex flex-col" ] [ div [ class "mb-4" ] [ label [ for "equipname" , class S.inputLabel ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , onInput SetName - , placeholder "Name" + , placeholder texts.basics.name , value model.name , name "equipname" , class S.textInput @@ -130,21 +137,21 @@ view2 model = [ label [ class S.inputLabel ] - [ text "Use" ] + [ text texts.use ] , Html.map UseDropdownMsg - (Comp.FixedDropdown.view2 (makeUseItem model) model.useModel) + (Comp.FixedDropdown.viewStyled2 equipUseCfg False (Just model.use) model.useModel) , span [ class "opacity-50 text-sm" ] [ case model.use of Data.EquipmentUse.Concerning -> - text "Use as concerning equipment" + text texts.useAsConcerning Data.EquipmentUse.Disabled -> - text "Do not use for suggestions." + text texts.useNotSuggestions ] ] , div [ class "mb-4" ] [ h3 [ class S.header3 ] - [ text "Notes" + [ text texts.notes ] , div [ class "" ] [ textarea @@ -156,9 +163,3 @@ view2 model = ] ] ] - - -makeUseItem : Model -> Maybe (Comp.FixedDropdown.Item EquipmentUse) -makeUseItem model = - Just <| - Comp.FixedDropdown.Item model.use (Data.EquipmentUse.label model.use) diff --git a/modules/webapp/src/main/elm/Comp/EquipmentManage.elm b/modules/webapp/src/main/elm/Comp/EquipmentManage.elm index 27df512b..67976ee9 100644 --- a/modules/webapp/src/main/elm/Comp/EquipmentManage.elm +++ b/modules/webapp/src/main/elm/Comp/EquipmentManage.elm @@ -20,6 +20,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onSubmit) import Http +import Messages.Comp.EquipmentManage exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -204,38 +205,41 @@ update flags msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = if model.viewMode == Table then - viewTable2 model + viewTable2 texts model else - viewForm2 model + viewForm2 texts model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col" ] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNewEquipment - , title = "Create a new equipment" + , title = texts.createNewEquipment , icon = Just "fa fa-plus" - , label = "New Equipment" + , label = texts.newEquipment } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.EquipmentTable.view2 model.tableModel) + , Html.map TableMsg + (Comp.EquipmentTable.view2 texts.equipmentTable + model.tableModel + ) , div [ classList [ ( "ui dimmer", True ) @@ -247,14 +251,16 @@ viewTable2 model = ] -viewForm2 : Model -> Html Msg -viewForm2 model = +viewForm2 : Texts -> Model -> Html Msg +viewForm2 texts model = let newEquipment = model.formModel.equipment.id == "" dimmerSettings2 = - Comp.YesNoDimmer.defaultSettings2 "Really delete this equipment?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteEquipment + texts.basics.yes + texts.basics.no in Html.form [ class "relative flex flex-col" @@ -268,14 +274,14 @@ viewForm2 model = ) , if newEquipment then h1 [ class S.header2 ] - [ text "Create new equipment" + [ text texts.createNewEquipment ] else h1 [ class S.header2 ] [ text model.formModel.equipment.name , div [ class "opacity-50 text-sm" ] - [ text "Id: " + [ text (texts.basics.id ++ ": ") , text model.formModel.equipment.id ] ] @@ -283,24 +289,24 @@ viewForm2 model = { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if not newEquipment then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this equipment" + , title = texts.deleteThisEquipment , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -317,6 +323,9 @@ viewForm2 model = ] [ Maybe.withDefault "" model.formError |> text ] - , Html.map FormMsg (Comp.EquipmentForm.view2 model.formModel) - , B.loadingDimmer model.loading + , Html.map FormMsg (Comp.EquipmentForm.view2 texts.equipmentForm model.formModel) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/EquipmentTable.elm b/modules/webapp/src/main/elm/Comp/EquipmentTable.elm index aabaccaa..7162025a 100644 --- a/modules/webapp/src/main/elm/Comp/EquipmentTable.elm +++ b/modules/webapp/src/main/elm/Comp/EquipmentTable.elm @@ -12,7 +12,7 @@ import Data.EquipmentUse import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onClick) +import Messages.Comp.EquipmentTable exposing (Texts) import Styles as S @@ -52,25 +52,25 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "" ] [] , th [ class "text-left pr-1 md:px-2 w-20" ] - [ text "Use" + [ text texts.use ] - , th [ class "text-left" ] [ text "Name" ] + , th [ class "text-left" ] [ text texts.basics.name ] ] ] , tbody [] - (List.map (renderEquipmentLine2 model) model.equips) + (List.map (renderEquipmentLine2 texts model) model.equips) ] -renderEquipmentLine2 : Model -> Equipment -> Html Msg -renderEquipmentLine2 model equip = +renderEquipmentLine2 : Texts -> Model -> Equipment -> Html Msg +renderEquipmentLine2 texts model equip = tr [ classList [ ( "active", model.selected == Just equip ) ] , class S.tableRow @@ -80,7 +80,7 @@ renderEquipmentLine2 model equip = [ div [ class "label inline-flex text-sm" ] [ Data.EquipmentUse.fromString equip.use |> Maybe.withDefault Data.EquipmentUse.Concerning - |> Data.EquipmentUse.label + |> texts.equipmentUseLabel |> text ] ] diff --git a/modules/webapp/src/main/elm/Comp/FieldListSelect.elm b/modules/webapp/src/main/elm/Comp/FieldListSelect.elm index 7cfc20a9..50f72c49 100644 --- a/modules/webapp/src/main/elm/Comp/FieldListSelect.elm +++ b/modules/webapp/src/main/elm/Comp/FieldListSelect.elm @@ -1,6 +1,7 @@ module Comp.FieldListSelect exposing ( Model , Msg + , ViewSettings , update , view2 ) @@ -49,17 +50,23 @@ addField selected field = --- View2 -view2 : String -> Model -> Html Msg -view2 classes selected = +type alias ViewSettings = + { fieldLabel : Field -> String + , classes : String + } + + +view2 : ViewSettings -> Model -> Html Msg +view2 cfg selected = div [ class "flex flex-col space-y-4 md:space-y-2" - , class classes + , class cfg.classes ] - (List.map (fieldCheckbox2 selected) Data.Fields.all) + (List.map (fieldCheckbox2 cfg selected) Data.Fields.all) -fieldCheckbox2 : Model -> Field -> Html Msg -fieldCheckbox2 selected field = +fieldCheckbox2 : ViewSettings -> Model -> Field -> Html Msg +fieldCheckbox2 cfg selected field = let isChecked = List.member field selected @@ -69,5 +76,5 @@ fieldCheckbox2 selected field = { id = "field-toggle-" ++ Data.Fields.toString field , value = isChecked , tagger = \_ -> Toggle field - , label = Data.Fields.label field + , label = cfg.fieldLabel field } diff --git a/modules/webapp/src/main/elm/Comp/FixedDropdown.elm b/modules/webapp/src/main/elm/Comp/FixedDropdown.elm index 5d94d369..6b0c5899 100644 --- a/modules/webapp/src/main/elm/Comp/FixedDropdown.elm +++ b/modules/webapp/src/main/elm/Comp/FixedDropdown.elm @@ -2,12 +2,9 @@ module Comp.FixedDropdown exposing ( Item , Model , Msg + , ViewSettings , init - , initMap - , initString - , initTuple , update - , view2 , viewStyled2 ) @@ -22,7 +19,6 @@ import Util.List type alias Item a = { id : a - , display : String } @@ -39,31 +35,17 @@ type Msg a | KeyPress (Maybe KeyCode) -init : List (Item a) -> Model a -init options = +initItems : List (Item a) -> Model a +initItems options = { options = options , menuOpen = False , selected = Nothing } -initString : List String -> Model String -initString strings = - init <| List.map (\s -> Item s s) strings - - -initMap : (a -> String) -> List a -> Model a -initMap elToString els = - init <| List.map (\a -> Item a (elToString a)) els - - -initTuple : List ( String, a ) -> Model a -initTuple tuples = - let - mkItem ( txt, id ) = - Item id txt - in - init <| List.map mkItem tuples +init : List a -> Model a +init els = + List.map Item els |> initItems isSelected : Model a -> Item a -> Bool @@ -167,28 +149,48 @@ update msg model = --- View2 -viewStyled2 : DS.DropdownStyle -> Bool -> Maybe (Item a) -> Model a -> Html (Msg a) -viewStyled2 style error sel model = +type alias ViewSettings a = + { display : a -> String + , icon : a -> Maybe String + , style : DS.DropdownStyle + } + + +viewStyled2 : ViewSettings a -> Bool -> Maybe a -> Model a -> Html (Msg a) +viewStyled2 cfg error sel model = let + iconItem id = + span + [ classList [ ( "hidden", cfg.icon id == Nothing ) ] + , class (Maybe.withDefault "" (cfg.icon id)) + , class "mr-2" + ] + [] + renderItem item = a [ href "#" - , class style.item + , class cfg.style.item , classList - [ ( style.itemActive, isSelected model item ) - , ( "font-semibold", Just item == sel ) + [ ( cfg.style.itemActive, isSelected model item ) + , ( "font-semibold", Just item.id == sel ) ] , onClick (SelectItem2 item) ] - [ text item.display + [ iconItem item.id + , text (cfg.display item.id) ] + + selIcon = + Maybe.map iconItem sel + |> Maybe.withDefault (span [ class "hidden" ] []) in div - [ class ("relative " ++ style.root) + [ class ("relative " ++ cfg.style.root) , onKeyUpCode KeyPress ] [ a - [ class style.link + [ class cfg.style.link , classList [ ( S.inputErrorBorder, error ) ] , tabindex 0 , onClick ToggleMenu @@ -200,7 +202,8 @@ viewStyled2 style error sel model = [ ( "opacity-50", sel == Nothing ) ] ] - [ Maybe.map .display sel + [ selIcon + , Maybe.map cfg.display sel |> Maybe.withDefault "Select…" |> text ] @@ -211,13 +214,8 @@ viewStyled2 style error sel model = ] ] , div - [ class style.menu + [ class cfg.style.menu , classList [ ( "hidden", not model.menuOpen ) ] ] (List.map renderItem model.options) ] - - -view2 : Maybe (Item a) -> Model a -> Html (Msg a) -view2 = - viewStyled2 DS.mainStyle False diff --git a/modules/webapp/src/main/elm/Comp/FolderDetail.elm b/modules/webapp/src/main/elm/Comp/FolderDetail.elm index 5e4a38af..7c8f4cd8 100644 --- a/modules/webapp/src/main/elm/Comp/FolderDetail.elm +++ b/modules/webapp/src/main/elm/Comp/FolderDetail.elm @@ -18,11 +18,13 @@ import Comp.Basic as B import Comp.FixedDropdown import Comp.MenuBar as MB import Comp.YesNoDimmer +import Data.DropdownStyle as DS import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Http +import Messages.Comp.FolderDetail exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -65,8 +67,7 @@ init users folder = , members = folder.members , users = users , memberDropdown = - Comp.FixedDropdown.initMap .name - (makeOptions users folder) + Comp.FixedDropdown.init (makeOptions users folder) , selectedMember = Nothing , loading = False , deleteDimmer = Comp.YesNoDimmer.emptyModel @@ -275,13 +276,8 @@ update flags msg model = --- View2 -makeItem : IdName -> Comp.FixedDropdown.Item IdName -makeItem idn = - Comp.FixedDropdown.Item idn idn.name - - -view2 : Flags -> Model -> Html Msg -view2 flags model = +view2 : Texts -> Flags -> Model -> Html Msg +view2 texts flags model = let isOwner = Maybe.map .user flags.account @@ -290,10 +286,12 @@ view2 flags model = dimmerSettings : Comp.YesNoDimmer.Settings dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this folder?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteThisFolder + texts.basics.yes + texts.basics.no in div [ class "flex flex-col md:relative" ] - (viewButtons2 model + (viewButtons2 texts model :: [ Html.map DeleteMsg (Comp.YesNoDimmer.viewN True @@ -304,26 +302,26 @@ view2 flags model = [ class "py-2 text-lg opacity-75" , classList [ ( "hidden", model.folder.id /= "" ) ] ] - [ text "You are automatically set as owner of this new folder." + [ text texts.autoOwnerInfo ] , div [ class "py-2 text-lg opacity-75" , classList [ ( "hidden", model.folder.id == "" ) ] ] - [ text "Modify this folder by changing the name or add/remove members." + [ text texts.modifyInfo ] , div [ class S.message , classList [ ( "hidden", model.folder.id == "" || isOwner ) ] ] - [ text "You are not the owner of this folder and therefore are not allowed to edit it." + [ text texts.notOwnerInfo ] , div [ class "mb-4 flex flex-col" ] [ label [ class S.inputLabel , for "folder-name" ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , div [ class "flex flex-row space-x-2" ] @@ -345,7 +343,7 @@ view2 flags model = ] [ i [ class "fa fa-save" ] [] , span [ class "ml-2 hidden sm:inline" ] - [ text "Save" + [ text texts.basics.submit ] ] ] @@ -363,12 +361,19 @@ view2 flags model = |> text ] ] - ++ viewMembers2 model + ++ viewMembers2 texts model ) -viewMembers2 : Model -> List (Html Msg) -viewMembers2 model = +viewMembers2 : Texts -> Model -> List (Html Msg) +viewMembers2 texts model = + let + folderCfg = + { display = .name + , icon = \_ -> Nothing + , style = DS.mainStyle + } + in if model.folder.id == "" then [] @@ -377,19 +382,21 @@ viewMembers2 model = [ class S.header3 , class "mt-4" ] - [ text "Members" + [ text texts.members ] , div [ class "flex flex-col space-y-2" ] [ div [ class "flex flex-row space-x-2" ] [ div [ class "flex-grow" ] [ Html.map MemberDropdownMsg - (Comp.FixedDropdown.view2 - (Maybe.map makeItem model.selectedMember) + (Comp.FixedDropdown.viewStyled2 + folderCfg + False + model.selectedMember model.memberDropdown ) ] , a - [ title "Add a new member" + [ title texts.addMember , onClick AddMember , class S.primaryButton , href "#" @@ -397,7 +404,7 @@ viewMembers2 model = ] [ i [ class "fa fa-plus" ] [] , span [ class "ml-2 hidden sm:inline" ] - [ text "Add" + [ text texts.add ] ] ] @@ -406,19 +413,19 @@ viewMembers2 model = [ class "flex flex-col space-y-4 md:space-y-2 mt-2" , class "px-2 border-0 border-l dark:border-bluegray-600" ] - (List.map viewMember2 model.members) + (List.map (viewMember2 texts) model.members) ] -viewMember2 : IdName -> Html Msg -viewMember2 member = +viewMember2 : Texts -> IdName -> Html Msg +viewMember2 texts member = div [ class "flex flex-row space-x-2 items-center" ] [ a [ class S.deleteLabel , href "#" - , title "Remove this member" + , title texts.removeMember , onClick (RemoveMember member) ] [ i [ class "fa fa-trash " ] [] @@ -429,23 +436,23 @@ viewMember2 member = ] -viewButtons2 : Model -> Html Msg -viewButtons2 model = +viewButtons2 : Texts -> Model -> Html Msg +viewButtons2 texts model = MB.view { start = [ MB.SecondaryButton { tagger = GoBack - , label = "Back" + , label = texts.basics.cancel , icon = Just "fa fa-arrow-left" - , title = "Back to list" + , title = texts.basics.backToList } ] , end = [ MB.CustomButton { tagger = RequestDelete - , label = "Delete" + , label = texts.basics.delete , icon = Just "fa fa-trash" - , title = "Delete this folder" + , title = texts.deleteThisFolder , inputClass = [ ( S.deleteButton, True ) , ( "hidden", model.folder.id == "" ) diff --git a/modules/webapp/src/main/elm/Comp/FolderManage.elm b/modules/webapp/src/main/elm/Comp/FolderManage.elm index cedb2c17..1264cb5c 100644 --- a/modules/webapp/src/main/elm/Comp/FolderManage.elm +++ b/modules/webapp/src/main/elm/Comp/FolderManage.elm @@ -20,6 +20,7 @@ import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) import Http +import Messages.Comp.FolderManage exposing (Texts) import Styles as S @@ -168,50 +169,54 @@ update flags msg model = --- View2 -view2 : Flags -> Model -> Html Msg -view2 flags model = +view2 : Texts -> Flags -> Model -> Html Msg +view2 texts flags model = case model.detailModel of Just dm -> - viewDetail2 flags dm + viewDetail2 texts flags dm Nothing -> - viewTable2 model + viewTable2 texts model -viewDetail2 : Flags -> Comp.FolderDetail.Model -> Html Msg -viewDetail2 flags model = +viewDetail2 : Texts -> Flags -> Comp.FolderDetail.Model -> Html Msg +viewDetail2 texts flags model = div [] [ if model.folder.id == "" then h3 [ class S.header2 ] - [ text "Create new Folder" + [ text texts.createNewFolder ] else h3 [ class S.header2 ] [ text model.folder.name , div [ class "opacity-50 text-sm" ] - [ text "Id: " + [ text (texts.basics.id ++ ": ") , text model.folder.id ] ] - , Html.map DetailMsg (Comp.FolderDetail.view2 flags model) + , Html.map DetailMsg + (Comp.FolderDetail.view2 texts.folderDetail + flags + model + ) ] -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col" ] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } , MB.Checkbox { tagger = \_ -> ToggleOwningOnly - , label = "Show owning folders only" + , label = texts.showOwningFoldersOnly , value = model.owningOnly , id = "folder-toggle-owner" } @@ -219,14 +224,19 @@ viewTable2 model = , end = [ MB.PrimaryButton { tagger = InitNewFolder - , title = "Create a new folder" + , title = texts.createNewFolder , icon = Just "fa fa-plus" - , label = "New Folder" + , label = texts.newFolder } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.FolderTable.view2 model.tableModel model.folders) + , Html.map TableMsg + (Comp.FolderTable.view2 + texts.folderTable + model.tableModel + model.folders + ) , div [ classList [ ( "ui dimmer", True ) diff --git a/modules/webapp/src/main/elm/Comp/FolderSelect.elm b/modules/webapp/src/main/elm/Comp/FolderSelect.elm index 3b65eff9..f7034af8 100644 --- a/modules/webapp/src/main/elm/Comp/FolderSelect.elm +++ b/modules/webapp/src/main/elm/Comp/FolderSelect.elm @@ -156,25 +156,20 @@ viewDrop2 dropModel constr model = highlightDrop = DD.getDropId dropModel == Just DD.FolderRemove in - div [ class "ui list" ] - [ div [ class "item" ] - [ i [ class "folder open icon" ] [] - , div [ class "content" ] - [ div - (classList - [ ( "hidden", True ) - , ( "current-drop-target", highlightDrop ) - ] - :: DD.droppable FolderDDMsg DD.FolderRemove - -- note: re-enable this when adding a "no-folder selection" - -- this enables a drop target that removes a folder - ) - [ text "Folders" - ] - , div [ class "flex flex-col space-y-2 md:space-y-1" ] - (renderItems2 dropModel constr model) + div [] + [ div + (classList + [ ( "hidden", True ) + , ( "current-drop-target", highlightDrop ) ] + :: DD.droppable FolderDDMsg DD.FolderRemove + -- note: re-enable this when adding a "no-folder selection" + -- this enables a drop target that removes a folder + ) + [ text "Folders" ] + , div [ class "flex flex-col space-y-2 md:space-y-1" ] + (renderItems2 dropModel constr model) ] diff --git a/modules/webapp/src/main/elm/Comp/FolderTable.elm b/modules/webapp/src/main/elm/Comp/FolderTable.elm index 7fa2ecf4..f598cf71 100644 --- a/modules/webapp/src/main/elm/Comp/FolderTable.elm +++ b/modules/webapp/src/main/elm/Comp/FolderTable.elm @@ -11,6 +11,7 @@ import Api.Model.FolderItem exposing (FolderItem) import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.FolderTable exposing (Texts) import Styles as S import Util.Time @@ -44,23 +45,27 @@ update msg model = --- View2 -view2 : Model -> List FolderItem -> Html Msg -view2 _ items = +view2 : Texts -> Model -> List FolderItem -> Html Msg +view2 texts _ items = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "w-px whitespace-nowrap pr-1 md:pr-3" ] [] - , th [ class "text-left" ] [ text "Name" ] + , th [ class "text-left" ] + [ text texts.basics.name + ] , th [ class "text-left hidden sm:table-cell" ] [ text "Owner" ] , th [ class "text-center" ] [ span [ class "hidden sm:inline" ] - [ text "#Member" + [ text texts.memberCount ] , span [ class "sm:hidden" ] [ text "#" ] ] - , th [ class "text-center" ] [ text "Created" ] + , th [ class "text-center" ] + [ text texts.basics.created + ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/ImapSettingsForm.elm b/modules/webapp/src/main/elm/Comp/ImapSettingsForm.elm index 8027b80f..3b7b6a73 100644 --- a/modules/webapp/src/main/elm/Comp/ImapSettingsForm.elm +++ b/modules/webapp/src/main/elm/Comp/ImapSettingsForm.elm @@ -21,6 +21,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.ImapSettingsForm exposing (Texts) import Styles as S import Util.Maybe @@ -45,21 +46,14 @@ emptyModel = { settings = Api.Model.ImapSettings.empty , name = "" , host = "" - , portField = Comp.IntField.init (Just 0) Nothing True "IMAP Port" + , portField = Comp.IntField.init (Just 0) Nothing True , portNum = Nothing , user = Nothing , passField = Comp.PasswordInput.init , password = Nothing , sslType = Comp.Dropdown.makeSingleList - { makeOption = - \s -> - { value = Data.SSLType.toString s - , text = Data.SSLType.label s - , additional = "" - } - , placeholder = "" - , options = Data.SSLType.all + { options = Data.SSLType.all , selected = Just Data.SSLType.None } , ignoreCertificates = False @@ -72,21 +66,14 @@ init ems = { settings = ems , name = ems.name , host = ems.imapHost - , portField = Comp.IntField.init (Just 0) Nothing True "IMAP Port" + , portField = Comp.IntField.init (Just 0) Nothing True , portNum = ems.imapPort , user = ems.imapUser , passField = Comp.PasswordInput.init , password = ems.imapPassword , sslType = Comp.Dropdown.makeSingleList - { makeOption = - \s -> - { value = Data.SSLType.toString s - , text = Data.SSLType.label s - , additional = "" - } - , placeholder = "" - , options = Data.SSLType.all + { options = Data.SSLType.all , selected = Data.SSLType.fromString ems.sslType |> Maybe.withDefault Data.SSLType.None @@ -176,20 +163,32 @@ update msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = + let + sslCfg = + { makeOption = + \s -> + { text = texts.sslTypeLabel s + , additional = "" + } + , placeholder = "" + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in div [ class "grid grid-cols-4 gap-y-4 gap-x-2" ] [ div [ class "col-span-4" ] [ label [ class S.inputLabel ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , value model.name , onInput SetName - , placeholder "Connection name, e.g. 'gmail.com'" + , placeholder texts.connectionNamePlaceholder , class S.textInput , classList [ ( S.inputErrorBorder, model.name == "" ) ] ] @@ -198,17 +197,17 @@ view2 settings model = [ class S.message , class "mt-2" ] - [ text "The connection name must not contain whitespace or special characters." + [ text texts.connectionNameInfo ] ] , div [ class "col-span-3" ] [ label [ class S.inputLabel ] - [ text "IMAP Host" + [ text texts.imapHost , B.inputRequired ] , input [ type_ "text" - , placeholder "IMAP host name, e.g. 'mail.gmail.com'" + , placeholder texts.imapHostPlaceholder , value model.host , onInput SetHost , class S.textInput @@ -217,18 +216,21 @@ view2 settings model = [] ] , Html.map PortMsg - (Comp.IntField.viewWithInfo2 "" - model.portNum - "" + (Comp.IntField.view + { label = texts.imapPort + , info = "" + , number = model.portNum + , classes = "" + } model.portField ) , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "IMAP User" + [ text texts.imapUser ] , input [ type_ "text" - , placeholder "IMAP Username, e.g. 'your.name@gmail.com'" + , placeholder texts.imapUserPlaceholder , Maybe.withDefault "" model.user |> value , onInput SetUser , class S.textInput @@ -237,9 +239,10 @@ view2 settings model = ] , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "IMAP Password" ] + [ text texts.imapPassword ] , Html.map PassMsg (Comp.PasswordInput.view2 + { placeholder = texts.imapPasswordPlaceholder } model.password False model.passField @@ -247,11 +250,11 @@ view2 settings model = ] , div [ class "col-span-4 sm:col-span-2" ] [ label [ class S.inputLabel ] - [ text "SSL" + [ text texts.ssl ] , Html.map SSLTypeMsg (Comp.Dropdown.view2 - DS.mainStyle + sslCfg settings model.sslType ) @@ -260,7 +263,7 @@ view2 settings model = [ MB.viewItem <| MB.Checkbox { tagger = \_ -> ToggleCheckCert - , label = "Ignore certificate check" + , label = texts.ignoreCertCheck , value = model.ignoreCertificates , id = "imap-no-cert-check" } @@ -269,12 +272,12 @@ view2 settings model = [ MB.viewItem <| MB.Checkbox { tagger = \_ -> ToggleUseOAuth - , label = "Enable OAuth2 authentication" + , label = texts.enableOAuth2 , value = model.useOAuthToken , id = "imap-use-oauth" } , div [ class "opacity-50 text-sm" ] - [ text "Enabling this, allows to connect via XOAuth using the password as access token." + [ text texts.oauth2Info ] ] ] diff --git a/modules/webapp/src/main/elm/Comp/ImapSettingsManage.elm b/modules/webapp/src/main/elm/Comp/ImapSettingsManage.elm index a36dfb58..146898ef 100644 --- a/modules/webapp/src/main/elm/Comp/ImapSettingsManage.elm +++ b/modules/webapp/src/main/elm/Comp/ImapSettingsManage.elm @@ -21,6 +21,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Http +import Messages.Comp.ImapSettingsManage exposing (Texts) import Styles as S import Util.Http @@ -206,74 +207,77 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = case model.viewMode of Table -> - viewTable2 model + viewTable2 texts model Form -> - viewForm2 settings model + viewForm2 texts settings model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNew - , title = "Add new SMTP settings" + , title = texts.addNewImapSettings , icon = Just "fa fa-plus" - , label = "New Settings" + , label = texts.newSettings } ] , rootClasses = "mb-4" } , Html.map TableMsg (Comp.ImapSettingsTable.view2 + texts.imapTable model.tableModel ) ] -viewForm2 : UiSettings -> Model -> Html Msg -viewForm2 settings model = +viewForm2 : Texts -> UiSettings -> Model -> Html Msg +viewForm2 texts settings model = let dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this mail-box connection?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteSettings + texts.basics.yes + texts.basics.no in div [ class "flex flex-col md:relative" ] [ MB.view { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if model.formModel.settings.name /= "" then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this settings entry" + , title = texts.deleteThisEntry , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -292,6 +296,7 @@ viewForm2 settings model = ] , Html.map FormMsg (Comp.ImapSettingsForm.view2 + texts.imapForm settings model.formModel ) @@ -301,5 +306,8 @@ viewForm2 settings model = dimmerSettings model.deleteConfirm ) - , B.loadingDimmer model.loading + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/ImapSettingsTable.elm b/modules/webapp/src/main/elm/Comp/ImapSettingsTable.elm index e6a708e7..d0070578 100644 --- a/modules/webapp/src/main/elm/Comp/ImapSettingsTable.elm +++ b/modules/webapp/src/main/elm/Comp/ImapSettingsTable.elm @@ -11,6 +11,7 @@ import Api.Model.ImapSettings exposing (ImapSettings) import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.ImapSettingsTable exposing (Texts) import Styles as S @@ -47,14 +48,14 @@ update msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] [ th [] [] - , th [ class "text-left mr-2" ] [ text "Name" ] - , th [ class "text-left mr-2" ] [ text "Host/Port" ] + , th [ class "text-left mr-2" ] [ text texts.basics.name ] + , th [ class "text-left mr-2" ] [ text texts.hostPort ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/IntField.elm b/modules/webapp/src/main/elm/Comp/IntField.elm index 986f40da..1ecbac18 100644 --- a/modules/webapp/src/main/elm/Comp/IntField.elm +++ b/modules/webapp/src/main/elm/Comp/IntField.elm @@ -1,9 +1,10 @@ module Comp.IntField exposing ( Model , Msg + , ViewSettings , init , update - , viewWithInfo2 + , view ) import Html exposing (..) @@ -16,7 +17,6 @@ import Styles as S type alias Model = { min : Maybe Int , max : Maybe Int - , label : String , error : Maybe String , lastInput : String , optional : Bool @@ -27,11 +27,10 @@ type Msg = SetValue String -init : Maybe Int -> Maybe Int -> Bool -> String -> Model -init min max opt label = +init : Maybe Int -> Maybe Int -> Bool -> Model +init min max opt = { min = min , max = max - , label = label , error = Nothing , lastInput = "" , optional = opt @@ -98,20 +97,28 @@ update msg model = --- View2 -viewWithInfo2 : String -> Maybe Int -> String -> Model -> Html Msg -viewWithInfo2 info nval classes model = +type alias ViewSettings = + { label : String + , info : String + , number : Maybe Int + , classes : String + } + + +view : ViewSettings -> Model -> Html Msg +view cfg model = div [ classList - [ ( classes, True ) + [ ( cfg.classes, True ) , ( "error", model.error /= Nothing ) ] ] [ label [ class S.inputLabel ] - [ text model.label + [ text cfg.label ] , input [ type_ "text" - , Maybe.map String.fromInt nval + , Maybe.map String.fromInt cfg.number |> Maybe.withDefault model.lastInput |> value , onInput SetValue @@ -120,11 +127,11 @@ viewWithInfo2 info nval classes model = [] , span [ classList - [ ( "hidden", info == "" ) + [ ( "hidden", cfg.info == "" ) ] , class "opacity-50 text-sm" ] - [ Markdown.toHtml [] info + [ Markdown.toHtml [] cfg.info ] , div [ classList @@ -135,3 +142,16 @@ viewWithInfo2 info nval classes model = [ Maybe.withDefault "" model.error |> text ] ] + + +viewWithInfo2 : String -> String -> Maybe Int -> String -> Model -> Html Msg +viewWithInfo2 label info nval classes model = + let + cfg = + { label = label + , info = info + , number = nval + , classes = classes + } + in + view cfg model diff --git a/modules/webapp/src/main/elm/Comp/ItemCard.elm b/modules/webapp/src/main/elm/Comp/ItemCard.elm index b361830f..175ef0e6 100644 --- a/modules/webapp/src/main/elm/Comp/ItemCard.elm +++ b/modules/webapp/src/main/elm/Comp/ItemCard.elm @@ -23,6 +23,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Markdown +import Messages.Comp.ItemCard exposing (Texts) import Page exposing (Page(..)) import Set exposing (Set) import Styles as S @@ -135,12 +136,11 @@ update ddm msg model = ---- View --- View2 -view2 : ViewConfig -> UiSettings -> Model -> ItemLight -> Html Msg -view2 cfg settings model item = +view2 : Texts -> ViewConfig -> UiSettings -> Model -> ItemLight -> Html Msg +view2 texts cfg settings model item = let isConfirmed = item.state /= "created" @@ -200,11 +200,11 @@ view2 cfg settings model item = [ previewImage2 settings cardAction model item ] ) - ++ [ mainContent2 cardAction cardColor isConfirmed settings cfg item - , metaDataContent2 settings item + ++ [ mainContent2 texts cardAction cardColor isConfirmed settings cfg item + , metaDataContent2 texts settings item , notesContent2 settings item , fulltextResultsContent2 item - , previewMenu2 settings model item (currentAttachment model item) + , previewMenu2 texts settings model item (currentAttachment model item) , selectedDimmer ] ) @@ -221,8 +221,8 @@ fulltextResultsContent2 item = (List.map renderHighlightEntry2 item.highlighting) -metaDataContent2 : UiSettings -> ItemLight -> Html Msg -metaDataContent2 settings item = +metaDataContent2 : Texts -> UiSettings -> ItemLight -> Html Msg +metaDataContent2 texts settings item = let fieldHidden f = Data.UiSettings.fieldHidden settings f @@ -234,7 +234,7 @@ metaDataContent2 settings item = [ ( "hidden", fieldHidden Data.Fields.Folder ) ] , class "hover:opacity-60" - , title "Folder" + , title texts.basics.folder ] [ Icons.folderIcon2 "mr-2" , Comp.LinkTarget.makeFolderLink item @@ -273,8 +273,16 @@ notesContent2 settings item = ] -mainContent2 : List (Attribute Msg) -> String -> Bool -> UiSettings -> ViewConfig -> ItemLight -> Html Msg -mainContent2 cardAction cardColor isConfirmed settings _ item = +mainContent2 : + Texts + -> List (Attribute Msg) + -> String + -> Bool + -> UiSettings + -> ViewConfig + -> ItemLight + -> Html Msg +mainContent2 texts cardAction cardColor isConfirmed settings _ item = let dirIcon = i @@ -303,7 +311,7 @@ mainContent2 cardAction cardColor isConfirmed settings _ item = && fieldHidden Data.Fields.CorrPerson ) ] - , title "Correspondent" + , title texts.basics.correspondent ] (Icons.correspondentIcon2 "mr-2 w-4 text-center" :: Comp.LinkTarget.makeCorrLink item [ ( "hover:opacity-75", True ) ] SetLinkTarget @@ -315,7 +323,7 @@ mainContent2 cardAction cardColor isConfirmed settings _ item = && fieldHidden Data.Fields.ConcEquip ) ] - , title "Concerning" + , title texts.basics.concerning ] (Icons.concernedIcon2 "mr-2 w-4 text-center" :: Comp.LinkTarget.makeConcLink item [ ( "hover:opacity-75", True ) ] SetLinkTarget @@ -332,7 +340,7 @@ mainContent2 cardAction cardColor isConfirmed settings _ item = , ( cardColor, True ) , ( "hidden", isConfirmed ) ] - , title "New" + , title texts.new ] [ i [ class "ml-2 fa fa-exclamation-circle" ] [] ] @@ -432,8 +440,8 @@ previewImage2 settings cardAction model item = ] -previewMenu2 : UiSettings -> Model -> ItemLight -> Maybe AttachmentLight -> Html Msg -previewMenu2 settings model item mainAttach = +previewMenu2 : Texts -> UiSettings -> Model -> ItemLight -> Maybe AttachmentLight -> Html Msg +previewMenu2 texts settings model item mainAttach = let pageCount = Maybe.andThen .pageCount mainAttach @@ -470,7 +478,7 @@ previewMenu2 settings model item mainAttach = ) ] , class "label font-semibold text-sm border-gray-300 dark:border-bluegray-600" - , title ("Due on " ++ dueDate) + , title (texts.dueOn ++ " " ++ dueDate) ] [ Icons.dueDateIcon2 "mr-2" , text (" " ++ dueDate) @@ -482,7 +490,7 @@ previewMenu2 settings model item mainAttach = , class "px-2 py-1 border rounded " , href attachUrl , target "_self" - , title "Open attachment file" + , title texts.openAttachmentFile ] [ i [ class "fa fa-eye" ] [] ] @@ -490,7 +498,7 @@ previewMenu2 settings model item mainAttach = [ class S.secondaryBasicButtonPlain , class "px-2 py-1 border rounded ml-2" , Page.href (ItemDetailPage item.id) - , title "Go to detail view" + , title texts.gotoDetail ] [ i [ class "fa fa-edit" ] [] ] @@ -510,7 +518,7 @@ previewMenu2 settings model item mainAttach = [ a [ class S.secondaryBasicButtonPlain , class "px-2 py-1 border rounded-l block" - , title "Cycle attachments" + , title texts.cycleAttachments , href "#" , onClick (CyclePreview item) ] diff --git a/modules/webapp/src/main/elm/Comp/ItemCardList.elm b/modules/webapp/src/main/elm/Comp/ItemCardList.elm index e3432c19..0894d711 100644 --- a/modules/webapp/src/main/elm/Comp/ItemCardList.elm +++ b/modules/webapp/src/main/elm/Comp/ItemCardList.elm @@ -22,6 +22,7 @@ import Data.UiSettings exposing (UiSettings) import Dict exposing (Dict) import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.ItemCardList exposing (Texts) import Page exposing (Page(..)) import Styles as S import Util.ItemDragDrop as DD @@ -148,19 +149,19 @@ type alias ViewConfig = } -view2 : ViewConfig -> UiSettings -> Model -> Html Msg -view2 cfg settings model = +view2 : Texts -> ViewConfig -> UiSettings -> Model -> Html Msg +view2 texts cfg settings model = div [ classList [ ( "ds-item-list", True ) , ( "ds-multi-select-mode", isMultiSelectMode cfg ) ] ] - (List.map (viewGroup2 model cfg settings) model.results.groups) + (List.map (viewGroup2 texts model cfg settings) model.results.groups) -viewGroup2 : Model -> ViewConfig -> UiSettings -> ItemLightGroup -> Html Msg -viewGroup2 model cfg settings group = +viewGroup2 : Texts -> Model -> ViewConfig -> UiSettings -> ItemLightGroup -> Html Msg +viewGroup2 texts model cfg settings group = div [ class "ds-item-group" ] [ div [ class "flex py-0 mt-2 flex flex-row items-center" @@ -185,12 +186,12 @@ viewGroup2 model cfg settings group = [] ] , div [ class "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-2" ] - (List.map (viewItem2 model cfg settings) group.items) + (List.map (viewItem2 texts model cfg settings) group.items) ] -viewItem2 : Model -> ViewConfig -> UiSettings -> ItemLight -> Html Msg -viewItem2 model cfg settings item = +viewItem2 : Texts -> Model -> ViewConfig -> UiSettings -> ItemLight -> Html Msg +viewItem2 texts model cfg settings item = let currentClass = if cfg.current == Just item.id then @@ -207,7 +208,7 @@ viewItem2 model cfg settings item = |> Maybe.withDefault Comp.ItemCard.init cardHtml = - Comp.ItemCard.view2 vvcfg settings cardModel item + Comp.ItemCard.view2 texts.itemCard vvcfg settings cardModel item in Html.map (ItemCardMsg item) cardHtml diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail.elm b/modules/webapp/src/main/elm/Comp/ItemDetail.elm index b295c7a9..89f354ad 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail.elm @@ -13,6 +13,7 @@ import Data.Flags exposing (Flags) import Data.ItemNav exposing (ItemNav) import Data.UiSettings exposing (UiSettings) import Html exposing (..) +import Messages.Comp.ItemDetail exposing (Texts) import Page exposing (Page(..)) @@ -30,6 +31,6 @@ update = Comp.ItemDetail.Update.update -view2 : ItemNav -> UiSettings -> Model -> Html Msg +view2 : Texts -> ItemNav -> UiSettings -> Model -> Html Msg view2 = Comp.ItemDetail.View2.view diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/AddFilesForm.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/AddFilesForm.elm index bebc9622..5c6e9c25 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/AddFilesForm.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/AddFilesForm.elm @@ -3,20 +3,20 @@ module Comp.ItemDetail.AddFilesForm exposing (view) import Comp.Dropzone import Comp.ItemDetail.Model exposing (..) import Comp.Progress -import Data.DropdownStyle import Dict import File exposing (File) import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onCheck, onClick, onInput) +import Html.Events exposing (onClick) +import Messages.Comp.ItemDetail.AddFilesForm exposing (Texts) import Set import Styles as S import Util.File exposing (makeFileId) import Util.Size -view : Model -> Html Msg -view model = +view : Texts -> Model -> Html Msg +view texts model = div [ classList [ ( "hidden", not model.addFilesOpen ) @@ -25,24 +25,24 @@ view model = , class S.box ] [ div [ class "text-lg font-bold" ] - [ text "Add more files to this item" + [ text texts.addMoreFilesToItem ] , Html.map AddFilesMsg - (Comp.Dropzone.view2 model.addFilesModel) + (Comp.Dropzone.view2 texts.dropzone model.addFilesModel) , div [ class "flex flex-row space-x-2 mt-2" ] [ button [ class S.primaryButton , href "#" , onClick AddFilesSubmitUpload ] - [ text "Submit" + [ text texts.basics.submit ] , button [ class S.secondaryButton , href "#" , onClick AddFilesReset ] - [ text "Reset" + [ text texts.reset ] ] , div @@ -52,14 +52,13 @@ view model = ] , class "mt-2" ] - [ text "All files have been uploaded. They are being processed, some data " - , text "may not be available immediately. " + [ text texts.filesSubmittedInfo , a [ class S.successMessageLink , href "#" , onClick ReloadItem ] - [ text "Refresh now" + [ text texts.refreshNow ] ] , div diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/EditForm.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/EditForm.elm index 1793d875..cae38fcd 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/EditForm.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/EditForm.elm @@ -3,7 +3,7 @@ module Comp.ItemDetail.EditForm exposing (formTabs, view2) import Comp.CustomFieldMultiInput import Comp.DatePicker import Comp.Dropdown -import Comp.ItemDetail.FieldTabState as FTabState +import Comp.ItemDetail.FieldTabState as FTabState exposing (EditTab(..)) import Comp.ItemDetail.Model exposing ( Model @@ -14,8 +14,10 @@ import Comp.ItemDetail.Model ) import Comp.KeyInput import Comp.Tabs as TB +import Data.Direction import Data.DropdownStyle import Data.Fields +import Data.Flags exposing (Flags) import Data.Icons as Icons import Data.UiSettings exposing (UiSettings) import Dict @@ -23,15 +25,18 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Markdown +import Messages.Comp.ItemDetail.EditForm exposing (Texts) import Page exposing (Page(..)) import Set exposing (Set) import Styles as S import Util.Folder +import Util.Person +import Util.Tag import Util.Time -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> Flags -> UiSettings -> Model -> Html Msg +view2 texts flags settings model = let keyAttr = if settings.itemDetailShortcuts then @@ -44,10 +49,10 @@ view2 settings model = TB.searchMenuStyle tabs = - formTabs settings model + formTabs texts flags settings model allTabNames = - List.map .title tabs + List.map .name tabs |> Set.fromList in div (class "flex flex-col relative" :: keyAttr) @@ -57,8 +62,8 @@ view2 settings model = ] -formTabs : UiSettings -> Model -> List (TB.Tab Msg) -formTabs settings model = +formTabs : Texts -> Flags -> UiSettings -> Model -> List (TB.Tab Msg) +formTabs texts flags settings model = let dds = Data.DropdownStyle.sidebarStyle @@ -92,10 +97,12 @@ formTabs settings model = Data.UiSettings.fieldVisible settings field customFieldSettings = - Comp.CustomFieldMultiInput.ViewSettings - True - "field" - (\f -> Dict.get f.id model.customFieldSavingIcon) + { showAddButton = True + , classes = "" + , fieldIcon = \f -> Dict.get f.id model.customFieldSavingIcon + , style = dds + , createCustomFieldTitle = texts.createNewCustomField + } optional fields html = if @@ -106,8 +113,41 @@ formTabs settings model = else span [ class "invisible hidden" ] [] + + directionCfg = + { makeOption = + \entry -> + { text = Data.Direction.toString entry + , additional = "" + } + , placeholder = texts.chooseDirection + , labelColor = \_ -> \_ -> "" + , style = dds + } + + folderCfg = + { makeOption = Util.Folder.mkFolderOption flags model.allFolders + , placeholder = texts.selectPlaceholder + , labelColor = \_ -> \_ -> "" + , style = dds + } + + idNameCfg = + { makeOption = \e -> { text = e.name, additional = "" } + , labelColor = \_ -> \_ -> "" + , placeholder = texts.selectPlaceholder + , style = dds + } + + personCfg = + { makeOption = \p -> Util.Person.mkPersonOption p model.allPersons + , labelColor = \_ -> \_ -> "" + , placeholder = texts.selectPlaceholder + , style = dds + } in - [ { title = "Name" + [ { name = FTabState.tabName TabName + , title = texts.basics.name , titleRight = [] , info = Nothing , body = @@ -133,7 +173,8 @@ formTabs settings model = ] ] } - , { title = "Date" + , { name = FTabState.tabName TabDate + , title = texts.basics.date , titleRight = [] , info = Nothing , body = @@ -154,16 +195,21 @@ formTabs settings model = ] , Icons.dateIcon2 S.dateInputIcon ] - , renderItemDateSuggestions model + , renderItemDateSuggestions texts model ] ] } - , { title = "Tags" + , { name = FTabState.tabName TabTags + , title = texts.basics.tags , titleRight = [] , info = Nothing , body = [ div [ class "mb-4 flex flex-col" ] - [ Html.map TagDropdownMsg (Comp.Dropdown.view2 dds settings model.tagModel) + [ Html.map TagDropdownMsg + (Comp.Dropdown.view2 (Util.Tag.tagSettings texts.basics.chooseTag dds) + settings + model.tagModel + ) , div [ class "flex flex-row items-center justify-end" ] [ a [ class S.secondaryButton @@ -177,14 +223,15 @@ formTabs settings model = ] ] } - , { title = "Folder" + , { name = FTabState.tabName TabFolder + , title = texts.basics.folder , titleRight = [] , info = Nothing , body = [ div [ class "mb-4" ] [ Html.map FolderDropdownMsg (Comp.Dropdown.view2 - dds + folderCfg settings model.folderModel ) @@ -194,30 +241,28 @@ formTabs settings model = , ( "hidden", isFolderMember model ) ] ] - [ Markdown.toHtml [] """ -You are **not a member** of this folder. This item will be **hidden** -from any search now. Use a folder where you are a member of to make this -item visible. This message will disappear then. - """ + [ Markdown.toHtml [] texts.folderNotOwnerWarning ] ] ] } - , { title = "Custom Fields" + , { name = FTabState.tabName TabCustomFields + , title = texts.basics.customFields , titleRight = [] , info = Nothing , body = [ div [ class "mb-4" ] [ Html.map CustomFieldMsg (Comp.CustomFieldMultiInput.view2 - dds + texts.customFieldInput customFieldSettings model.customFieldsModel ) ] ] } - , { title = "Due Date" + , { name = FTabState.tabName TabDueDate + , title = texts.dueDateTab , titleRight = [] , info = Nothing , body = @@ -238,11 +283,12 @@ item visible. This message will disappear then. ] , Icons.dueDateIcon2 S.dateInputIcon ] - , renderDueDateSuggestions model + , renderDueDateSuggestions texts model ] ] } - , { title = "Correspondent" + , { name = FTabState.tabName TabCorrespondent + , title = texts.basics.correspondent , titleRight = [] , info = Nothing , body = @@ -250,25 +296,34 @@ item visible. This message will disappear then. div [ class "mb-4" ] [ label [ class S.inputLabel ] [ Icons.organizationIcon2 "mr-2" - , text "Organization" - , addIconLink "Add new organization" StartCorrOrgModal - , editIconLink "Edit organization" model.corrOrgModel StartEditCorrOrgModal + , text texts.basics.organization + , addIconLink texts.addNewOrg StartCorrOrgModal + , editIconLink texts.editOrg model.corrOrgModel StartEditCorrOrgModal ] - , Html.map OrgDropdownMsg (Comp.Dropdown.view2 dds settings model.corrOrgModel) - , renderOrgSuggestions model + , Html.map OrgDropdownMsg + (Comp.Dropdown.view2 + (Comp.Dropdown.orgFormViewSettings texts.chooseOrg dds) + settings + model.corrOrgModel + ) + , renderOrgSuggestions texts model ] , optional [ Data.Fields.CorrPerson ] <| div [ class "mb-4" ] [ label [ class S.inputLabel ] [ Icons.personIcon2 "mr-2" - , text "Person" - , addIconLink "Add new correspondent person" StartCorrPersonModal - , editIconLink "Edit person" + , text texts.basics.person + , addIconLink texts.addNewCorrespondentPerson StartCorrPersonModal + , editIconLink texts.editPerson model.corrPersonModel (StartEditPersonModal model.corrPersonModel) ] - , Html.map CorrPersonMsg (Comp.Dropdown.view2 dds settings model.corrPersonModel) - , renderCorrPersonSuggestions model + , Html.map CorrPersonMsg + (Comp.Dropdown.view2 personCfg + settings + model.corrPersonModel + ) + , renderCorrPersonSuggestions texts model , div [ classList [ ( "hidden", personMatchesOrg model ) @@ -277,12 +332,13 @@ item visible. This message will disappear then. , class "my-2" ] [ i [ class "fa fa-info mr-2 " ] [] - , text "The selected person doesn't belong to the selected organization." + , text texts.personOrgInfo ] ] ] } - , { title = "Concerning" + , { name = FTabState.tabName TabConcerning + , title = texts.basics.concerning , titleRight = [] , info = Nothing , body = @@ -290,48 +346,49 @@ item visible. This message will disappear then. div [ class "mb-4" ] [ label [ class S.inputLabel ] [ Icons.personIcon2 "mr-2" - , text "Person" - , addIconLink "Add new concerning person" StartConcPersonModal - , editIconLink "Edit person" + , text texts.basics.person + , addIconLink texts.addNewConcerningPerson StartConcPersonModal + , editIconLink texts.editPerson model.concPersonModel (StartEditPersonModal model.concPersonModel) ] , Html.map ConcPersonMsg (Comp.Dropdown.view2 - dds + personCfg settings model.concPersonModel ) - , renderConcPersonSuggestions model + , renderConcPersonSuggestions texts model ] , optional [ Data.Fields.ConcEquip ] <| div [ class "mb-4" ] [ label [ class S.inputLabel ] [ Icons.equipmentIcon2 "mr-2" - , text "Equipment" - , addIconLink "Add new equipment" StartEquipModal - , editIconLink "Edit equipment" + , text texts.basics.equipment + , addIconLink texts.addNewEquipment StartEquipModal + , editIconLink texts.editEquipment model.concEquipModel StartEditEquipModal ] , Html.map ConcEquipMsg (Comp.Dropdown.view2 - dds + idNameCfg settings model.concEquipModel ) - , renderConcEquipSuggestions model + , renderConcEquipSuggestions texts model ] ] } - , { title = "Direction" + , { name = FTabState.tabName TabDirection + , title = texts.basics.direction , titleRight = [] , info = Nothing , body = [ div [ class "mb-4" ] [ Html.map DirDropdownMsg (Comp.Dropdown.view2 - dds + directionCfg settings model.directionModel ) @@ -341,8 +398,8 @@ item visible. This message will disappear then. ] -renderSuggestions : Model -> (a -> String) -> List a -> (a -> Msg) -> Html Msg -renderSuggestions model mkName idnames tagger = +renderSuggestions : Texts -> Model -> (a -> String) -> List a -> (a -> Msg) -> Html Msg +renderSuggestions texts model mkName idnames tagger = div [ classList [ ( "hidden", model.item.state /= "created" ) @@ -350,7 +407,7 @@ renderSuggestions model mkName idnames tagger = , class "flex flex-col text-sm" ] [ div [ class "font-bold my-1" ] - [ text "Suggestions" + [ text texts.suggestions ] , ul [ class "list-disc ml-6" ] <| (idnames @@ -369,49 +426,55 @@ renderSuggestions model mkName idnames tagger = ] -renderOrgSuggestions : Model -> Html Msg -renderOrgSuggestions model = - renderSuggestions model +renderOrgSuggestions : Texts -> Model -> Html Msg +renderOrgSuggestions texts model = + renderSuggestions texts + model .name (List.take 6 model.itemProposals.corrOrg) SetCorrOrgSuggestion -renderCorrPersonSuggestions : Model -> Html Msg -renderCorrPersonSuggestions model = - renderSuggestions model +renderCorrPersonSuggestions : Texts -> Model -> Html Msg +renderCorrPersonSuggestions texts model = + renderSuggestions texts + model .name (List.take 6 model.itemProposals.corrPerson) SetCorrPersonSuggestion -renderConcPersonSuggestions : Model -> Html Msg -renderConcPersonSuggestions model = - renderSuggestions model +renderConcPersonSuggestions : Texts -> Model -> Html Msg +renderConcPersonSuggestions texts model = + renderSuggestions texts + model .name (List.take 6 model.itemProposals.concPerson) SetConcPersonSuggestion -renderConcEquipSuggestions : Model -> Html Msg -renderConcEquipSuggestions model = - renderSuggestions model +renderConcEquipSuggestions : Texts -> Model -> Html Msg +renderConcEquipSuggestions texts model = + renderSuggestions texts + model .name (List.take 6 model.itemProposals.concEquipment) SetConcEquipSuggestion -renderItemDateSuggestions : Model -> Html Msg -renderItemDateSuggestions model = - renderSuggestions model +renderItemDateSuggestions : Texts -> Model -> Html Msg +renderItemDateSuggestions texts model = + renderSuggestions texts + model Util.Time.formatDate (List.take 6 model.itemProposals.itemDate) SetItemDateSuggestion -renderDueDateSuggestions : Model -> Html Msg -renderDueDateSuggestions model = - renderSuggestions model +renderDueDateSuggestions : Texts -> Model -> Html Msg +renderDueDateSuggestions texts model = + renderSuggestions texts + model Util.Time.formatDate (List.take 6 model.itemProposals.dueDate) SetDueDateSuggestion @@ -445,4 +508,4 @@ tabState settings allNames model = FTabState.tabState settings openTabs Nothing - (.title >> ToggleAkkordionTab) + (.name >> ToggleAkkordionTab) diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/FieldTabState.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/FieldTabState.elm index 8952f2b5..0a3c48cf 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/FieldTabState.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/FieldTabState.elm @@ -1,4 +1,4 @@ -module Comp.ItemDetail.FieldTabState exposing (tabState) +module Comp.ItemDetail.FieldTabState exposing (EditTab(..), allTabs, findTab, tabName, tabState) import Comp.CustomFieldMultiInput import Comp.Tabs as TB @@ -7,6 +7,102 @@ import Data.UiSettings exposing (UiSettings) import Set exposing (Set) +type EditTab + = TabName + | TabDate + | TabTags + | TabFolder + | TabCustomFields + | TabDueDate + | TabCorrespondent + | TabConcerning + | TabDirection + | TabConfirmUnconfirm + + +allTabs : List EditTab +allTabs = + [ TabName + , TabDate + , TabTags + , TabFolder + , TabCustomFields + , TabDueDate + , TabCorrespondent + , TabConcerning + , TabDirection + , TabConfirmUnconfirm + ] + + +tabName : EditTab -> String +tabName tab = + case tab of + TabName -> + "name" + + TabTags -> + "tags" + + TabDate -> + "date" + + TabFolder -> + "folder" + + TabCustomFields -> + "custom-fields" + + TabDueDate -> + "due-date" + + TabCorrespondent -> + "correspondent" + + TabConcerning -> + "concerning" + + TabDirection -> + "direction" + + TabConfirmUnconfirm -> + "confirm-unconfirm" + + +findTab : TB.Tab msg -> Maybe EditTab +findTab tab = + case tab.name of + "name" -> + Just TabName + + "tags" -> + Just TabTags + + "date" -> + Just TabDate + + "folder" -> + Just TabFolder + + "custom-fields" -> + Just TabCustomFields + + "due-date" -> + Just TabDueDate + + "correspondent" -> + Just TabCorrespondent + + "concerning" -> + Just TabConcerning + + "direction" -> + Just TabDirection + + _ -> + Nothing + + tabState : UiSettings -> Set String @@ -20,32 +116,32 @@ tabState settings openTabs cfmodel toggle tab = Data.UiSettings.fieldHidden settings f hidden = - case tab.title of - "Tags" -> + case findTab tab of + Just TabTags -> isHidden Data.Fields.Tag - "Folder" -> + Just TabFolder -> isHidden Data.Fields.Folder - "Correspondent" -> + Just TabCorrespondent -> isHidden Data.Fields.CorrOrg && isHidden Data.Fields.CorrPerson - "Concerning" -> + Just TabConcerning -> isHidden Data.Fields.ConcEquip && isHidden Data.Fields.ConcPerson - "Custom Fields" -> + Just TabCustomFields -> isHidden Data.Fields.CustomFields || (Maybe.map Comp.CustomFieldMultiInput.isEmpty cfmodel |> Maybe.withDefault False ) - "Date" -> + Just TabDate -> isHidden Data.Fields.Date - "Due Date" -> + Just TabDueDate -> isHidden Data.Fields.DueDate - "Direction" -> + Just TabDirection -> isHidden Data.Fields.Direction _ -> @@ -55,7 +151,7 @@ tabState settings openTabs cfmodel toggle tab = if hidden then TB.Hidden - else if Set.member tab.title openTabs then + else if Set.member tab.name openTabs then TB.Open else diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/ItemInfoHeader.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/ItemInfoHeader.elm index 30e11f49..08142a41 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/ItemInfoHeader.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/ItemInfoHeader.elm @@ -15,19 +15,20 @@ import Data.Icons as Icons import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.ItemDetail.ItemInfoHeader exposing (Texts) import Page exposing (Page(..)) import Styles as S import Util.Maybe import Util.Time -view : UiSettings -> Model -> Html Msg -view settings model = +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = let date = ( div [ class "ml-2 sm:ml-0 whitespace-nowrap py-1 whitespace-nowrap opacity-75" - , title "Item Date" + , title texts.itemDate ] [ Icons.dateIcon2 "mr-2" , Maybe.withDefault model.item.created model.item.itemDate @@ -47,7 +48,7 @@ view settings model = ( div [ class "ml-2 sm:ml-4 py-1 max-w-min whitespace-nowrap opacity-100" , class S.basicLabel - , title "Due Date" + , title texts.dueDate ] [ Icons.dueDateIcon2 "mr-2" , Maybe.map Util.Time.formatDate model.item.dueDate @@ -61,7 +62,7 @@ view settings model = corr = ( div [ class itemStyle - , title "Correspondent" + , title texts.basics.correspondent ] (Icons.correspondentIcon2 "mr-2" :: Comp.LinkTarget.makeCorrLink model.item @@ -75,7 +76,7 @@ view settings model = conc = ( div [ class itemStyle - , title "Concerning" + , title texts.basics.concerning ] (Icons.concernedIcon2 "mr-2" :: Comp.LinkTarget.makeConcLink model.item @@ -89,7 +90,7 @@ view settings model = itemfolder = ( div [ class itemStyle - , title "Folder" + , title texts.basics.folder ] [ Icons.folderIcon2 "mr-2" , Comp.LinkTarget.makeFolderLink model.item @@ -102,7 +103,7 @@ view settings model = src = ( div [ class itemStyle - , title "Source" + , title texts.source ] [ Icons.sourceIcon2 "mr-2" , Comp.LinkTarget.makeSourceLink [ ( linkStyle, True ) ] @@ -132,7 +133,7 @@ view settings model = ] , class "ml-3 text-base label bg-blue-500 dark:bg-lightblue-500 text-white rounded-lg" ] - [ text "New" + [ text texts.new , i [ class "fa fa-exclamation ml-2" ] [] ] ] diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm index 74a46d5f..02e2e2d8 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/Model.elm @@ -39,7 +39,6 @@ import Comp.KeyInput import Comp.LinkTarget exposing (LinkTarget) import Comp.MarkdownInput import Comp.SentMails -import Comp.YesNoDimmer import Data.Direction exposing (Direction) import Data.Fields exposing (Field) import DatePicker exposing (DatePicker) @@ -136,45 +135,17 @@ emptyModel = , visibleAttach = 0 , attachMenuOpen = False , menuOpen = False - , tagModel = - Util.Tag.makeDropdownModel2 + , tagModel = Util.Tag.makeDropdownModel , directionModel = Comp.Dropdown.makeSingleList - { makeOption = - \entry -> - { value = Data.Direction.toString entry - , text = Data.Direction.toString entry - , additional = "" - } - , options = Data.Direction.all - , placeholder = "Choose a direction…" + { options = Data.Direction.all , selected = Nothing } - , corrOrgModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , corrPersonModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , concPersonModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , concEquipModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , folderModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } + , corrOrgModel = Comp.Dropdown.makeSingle + , corrPersonModel = Comp.Dropdown.makeSingle + , concPersonModel = Comp.Dropdown.makeSingle + , concEquipModel = Comp.Dropdown.makeSingle + , folderModel = Comp.Dropdown.makeSingle , allFolders = [] , nameModel = "" , nameState = SaveSuccess diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/MultiEditMenu.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/MultiEditMenu.elm index 5a4703b9..3a8d6279 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/MultiEditMenu.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/MultiEditMenu.elm @@ -22,7 +22,7 @@ import Comp.CustomFieldMultiInput import Comp.DatePicker import Comp.DetailEdit import Comp.Dropdown exposing (isDropdownChangeMsg) -import Comp.ItemDetail.FieldTabState as FTabState +import Comp.ItemDetail.FieldTabState as FTabState exposing (EditTab(..), tabName) import Comp.ItemDetail.FormChange exposing (FormChange(..)) import Comp.Tabs as TB import Data.CustomFieldChange exposing (CustomFieldChange(..)) @@ -39,6 +39,7 @@ import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Http import Markdown +import Messages.Comp.ItemDetail.MultiEditMenu exposing (Texts) import Page exposing (Page(..)) import Set exposing (Set) import Styles as S @@ -117,45 +118,17 @@ type Msg init : Model init = - { tagModel = - Util.Tag.makeDropdownModel2 + { tagModel = Util.Tag.makeDropdownModel , directionModel = Comp.Dropdown.makeSingleList - { makeOption = - \entry -> - { value = Data.Direction.toString entry - , text = Data.Direction.toString entry - , additional = "" - } - , options = Data.Direction.all - , placeholder = "Choose a direction…" + { options = Data.Direction.all , selected = Nothing } - , corrOrgModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , corrPersonModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , concPersonModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , concEquipModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } - , folderModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } + , corrOrgModel = Comp.Dropdown.makeSingle + , corrPersonModel = Comp.Dropdown.makeSingle + , concPersonModel = Comp.Dropdown.makeSingle + , concEquipModel = Comp.Dropdown.makeSingle + , folderModel = Comp.Dropdown.makeSingle , allFolders = [] , nameModel = "" , nameSaveThrottle = Throttle.create 1 @@ -310,13 +283,7 @@ update flags msg model = GetFolderResp (Ok fs) -> let model_ = - { model - | allFolders = fs.items - , folderModel = - Comp.Dropdown.setMkOption - (mkFolderOption flags fs.items) - model.folderModel - } + { model | allFolders = fs.items } mkIdName fitem = IdName fitem.id fitem.name @@ -593,14 +560,14 @@ update flags msg model = in UpdateResult model_ cmd_ Sub.none change - ToggleAkkordionTab title -> + ToggleAkkordionTab name -> let tabs = - if Set.member title model.openTabs then - Set.remove title model.openTabs + if Set.member name model.openTabs then + Set.remove name model.openTabs else - Set.insert title model.openTabs + Set.insert name model.openTabs in UpdateResult { model | openTabs = tabs } Cmd.none Sub.none NoFormChange @@ -635,13 +602,13 @@ defaultViewConfig = --- View2 -view2 : ViewConfig -> UiSettings -> Model -> Html Msg +view2 : Texts -> Flags -> ViewConfig -> UiSettings -> Model -> Html Msg view2 = renderEditForm2 -renderEditForm2 : ViewConfig -> UiSettings -> Model -> Html Msg -renderEditForm2 cfg settings model = +renderEditForm2 : Texts -> Flags -> ViewConfig -> UiSettings -> Model -> Html Msg +renderEditForm2 texts flags cfg settings model = let fieldVisible field = Data.UiSettings.fieldVisible settings field @@ -670,13 +637,13 @@ renderEditForm2 cfg settings model = tagModeMsg = case model.tagEditMode of AddTags -> - "Tags chosen here are *added* to all selected items." + texts.tagModeAddInfo RemoveTags -> - "Tags chosen here are *removed* from all selected items." + texts.tagModeRemoveInfo ReplaceTags -> - "Tags chosen here *replace* those on selected items." + texts.tagModeReplaceInfo customFieldIcon field = case cfg.customFieldState field.id of @@ -690,22 +657,50 @@ renderEditForm2 cfg settings model = Just "fa fa-sync-alt animate-spin" customFieldSettings = - Comp.CustomFieldMultiInput.ViewSettings - False - "mb-4" - customFieldIcon + { showAddButton = False + , classes = "mb-4" + , fieldIcon = customFieldIcon + , style = dds + , createCustomFieldTitle = "" + } dds = Data.DropdownStyle.sidebarStyle tabStyle = TB.searchMenuStyle + + folderCfg = + { makeOption = Util.Folder.mkFolderOption flags model.allFolders + , placeholder = "" + , labelColor = \_ -> \_ -> "" + , style = dds + } + + idNameCfg = + { makeOption = \e -> { text = e.name, additional = "" } + , labelColor = \_ -> \_ -> "" + , placeholder = texts.selectPlaceholder + , style = dds + } + + directionCfg = + { makeOption = + \entry -> + { text = Data.Direction.toString entry + , additional = "" + } + , placeholder = texts.chooseDirection + , labelColor = \_ -> \_ -> "" + , style = dds + } in div [ class cfg.menuClass, class "mt-2" ] [ TB.akkordion tabStyle (tabState settings model) - [ { title = "Confirm/Unconfirm item metadata" + [ { name = tabName TabConfirmUnconfirm + , title = texts.confirmUnconfirm , titleRight = [] , info = Nothing , body = @@ -717,69 +712,77 @@ renderEditForm2 cfg settings model = , class "flex-grow" , onClick (ConfirmMsg True) ] - [ text "Confirm" + [ text texts.confirm ] , button [ class S.secondaryButton , class "flex-grow" , onClick (ConfirmMsg False) ] - [ text "Unconfirm" + [ text texts.unconfirm ] ] ] } - , { title = "Tags" + , { name = tabName TabTags + , title = texts.basics.tags , titleRight = [] , info = Nothing , body = [ div [ class "field" ] [ label [ class S.inputLabel ] [ Icons.tagsIcon2 "" - , text "Tags" + , text texts.basics.tags , a [ class "float-right" , class S.link , href "#" - , title "Change tag edit mode" + , title texts.changeTagMode , onClick ToggleTagEditMode ] [ tagModeIcon ] ] - , Html.map TagDropdownMsg (Comp.Dropdown.view2 dds settings model.tagModel) + , Html.map TagDropdownMsg + (Comp.Dropdown.view2 (Util.Tag.tagSettings texts.basics.chooseTag dds) + settings + model.tagModel + ) , Markdown.toHtml [ class "opacity-50 text-sm" ] tagModeMsg ] ] } - , { title = "Folder" + , { name = tabName TabFolder + , title = texts.basics.folder , titleRight = [] , info = Nothing , body = - [ Html.map FolderDropdownMsg (Comp.Dropdown.view2 dds settings model.folderModel) + [ Html.map FolderDropdownMsg (Comp.Dropdown.view2 folderCfg settings model.folderModel) , div [ classList [ ( S.message, True ) , ( "hidden", isFolderMember model ) ] ] - [ Markdown.toHtml [] """ -You are **not a member** of this folder. This item will be **hidden** -from any search now. Use a folder where you are a member of to make this -item visible. This message will disappear then. - """ + [ Markdown.toHtml [] texts.folderNotOwnerWarning ] ] } - , { title = "Custom Fields" + , { name = tabName TabCustomFields + , title = texts.basics.customFields , titleRight = [] , info = Nothing , body = [ Html.map CustomFieldMsg - (Comp.CustomFieldMultiInput.view2 dds customFieldSettings model.customFieldModel) + (Comp.CustomFieldMultiInput.view2 + texts.customFieldMultiInput + customFieldSettings + model.customFieldModel + ) ] } - , { title = "Date" + , { name = tabName TabDate + , title = texts.basics.date , titleRight = [] , info = Nothing , body = @@ -801,7 +804,8 @@ item visible. This message will disappear then. ] ] } - , { title = "Due Date" + , { name = tabName TabDueDate + , title = texts.dueDateTab , titleRight = [] , info = Nothing , body = @@ -823,7 +827,8 @@ item visible. This message will disappear then. ] ] } - , { title = "Correspondent" + , { name = tabName TabCorrespondent + , title = texts.basics.correspondent , titleRight = [] , info = Nothing , body = @@ -832,24 +837,35 @@ item visible. This message will disappear then. [ label [ class S.inputLabel ] [ Icons.organizationIcon2 "" , span [ class "ml-2" ] - [ text "Organization" + [ text texts.basics.organization ] ] - , Html.map OrgDropdownMsg (Comp.Dropdown.view2 dds settings model.corrOrgModel) + , Html.map OrgDropdownMsg + (Comp.Dropdown.view2 + idNameCfg + settings + model.corrOrgModel + ) ] , optional [ Data.Fields.CorrPerson ] <| div [ class "mb-4" ] [ label [ class S.inputLabel ] [ Icons.personIcon2 "" , span [ class "ml-2" ] - [ text "Person" + [ text texts.basics.person ] ] - , Html.map CorrPersonMsg (Comp.Dropdown.view2 dds settings model.corrPersonModel) + , Html.map CorrPersonMsg + (Comp.Dropdown.view2 + idNameCfg + settings + model.corrPersonModel + ) ] ] } - , { title = "Concerning" + , { name = tabName TabConcerning + , title = texts.basics.concerning , titleRight = [] , info = Nothing , body = @@ -858,29 +874,35 @@ item visible. This message will disappear then. [ label [ class S.inputLabel ] [ Icons.personIcon2 "" , span [ class "ml-2" ] - [ text "Person" ] + [ text texts.basics.person ] ] - , Html.map ConcPersonMsg (Comp.Dropdown.view2 dds settings model.concPersonModel) + , Html.map ConcPersonMsg (Comp.Dropdown.view2 idNameCfg settings model.concPersonModel) ] , optional [ Data.Fields.ConcEquip ] <| div [ class "mb-4" ] [ label [ class S.inputLabel ] [ Icons.equipmentIcon2 "" , span [ class "ml-2" ] - [ text "Equipment" ] + [ text texts.basics.equipment ] ] - , Html.map ConcEquipMsg (Comp.Dropdown.view2 dds settings model.concEquipModel) + , Html.map ConcEquipMsg + (Comp.Dropdown.view2 idNameCfg + settings + model.concEquipModel + ) ] ] } - , { title = "Direction" + , { name = tabName TabDirection + , title = texts.basics.direction , titleRight = [] , info = Nothing , body = - [ Html.map DirDropdownMsg (Comp.Dropdown.view2 dds settings model.directionModel) + [ Html.map DirDropdownMsg (Comp.Dropdown.view2 directionCfg settings model.directionModel) ] } - , { title = "Name" + , { name = tabName TabName + , title = texts.basics.name , titleRight = [] , info = Nothing , body = @@ -895,9 +917,15 @@ item visible. This message will disappear then. , span [ class S.inputLeftIconOnly ] [ i [ classList - [ ( "text-green-500 fa fa-check", cfg.nameState == SaveSuccess ) - , ( "text-red-500 fa fa-exclamation-triangle", cfg.nameState == SaveFailed ) - , ( "sync fa fa-circle-notch animate-spin", cfg.nameState == Saving ) + [ ( "text-green-500 fa fa-check" + , cfg.nameState == SaveSuccess + ) + , ( "text-red-500 fa fa-exclamation-triangle" + , cfg.nameState == SaveFailed + ) + , ( "sync fa fa-circle-notch animate-spin" + , cfg.nameState == Saving + ) ] ] [] @@ -914,7 +942,7 @@ tabState settings model tab = FTabState.tabState settings model.openTabs (Just model.customFieldModel) - (.title >> ToggleAkkordionTab) + (.name >> ToggleAkkordionTab) tab diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/Notes.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/Notes.elm index 58478bc3..76ad0851 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/Notes.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/Notes.elm @@ -12,19 +12,20 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Markdown +import Messages.Comp.ItemDetail.Notes exposing (Texts) import Page exposing (Page(..)) import Styles as S import Util.String -view : Model -> Html Msg -view model = +view : Texts -> Model -> Html Msg +view texts model = case model.notesField of ViewNotes -> div [ class "flex flex-col ds-item-detail-notes" ] [ div [ class "flex flex-row items-center border-b dark:border-bluegray-600" ] [ div [ class "flex-grow font-bold text-lg" ] - [ text "Notes" + [ text texts.notes ] , div [ class "" ] [ a @@ -33,7 +34,7 @@ view model = , href "#" ] [ i [ class "fa fa-edit mr-2" ] [] - , text "Edit" + , text texts.basics.edit ] ] ] @@ -55,14 +56,14 @@ view model = [ div [ class "flex flex-col" ] [ div [ class "flex flex-row items-center" ] [ div [ class "font-bold text-lg" ] - [ text "Notes" + [ text texts.notes ] , div [ class "flex flex-grow justify-end text-sm" ] [ Html.map NotesEditMsg - (Comp.MarkdownInput.viewEditLink2 classes mm) + (Comp.MarkdownInput.viewEditLink2 texts.basics.edit classes mm) , span [ class "px-3" ] [ text "•" ] , Html.map NotesEditMsg - (Comp.MarkdownInput.viewPreviewLink2 classes mm) + (Comp.MarkdownInput.viewPreviewLink2 texts.preview classes mm) ] ] ] @@ -73,7 +74,9 @@ view model = mm ) , div [ class "text-sm flex justify-end" ] - [ Comp.MarkdownInput.viewCheatLink2 S.link mm + [ Comp.MarkdownInput.viewCheatLink2 texts.supportsMarkdown + S.link + mm ] , div [ class "flex flex-row mt-1" ] [ a @@ -82,7 +85,7 @@ view model = , onClick SaveNotes ] [ i [ class "fa fa-save font-thin mr-2" ] [] - , text "Save" + , text texts.basics.submit ] , a [ classList @@ -94,7 +97,7 @@ view model = , onClick ToggleEditNotes ] [ i [ class "fa fa-times mr-2" ] [] - , text "Cancel" + , text texts.basics.cancel ] ] ] diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm index 7d3cd714..f9ca4e58 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm @@ -18,6 +18,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Html5.DragDrop as DD +import Messages.Comp.ItemDetail.SingleAttachment exposing (Texts) import Page exposing (Page(..)) import Styles as S import Util.Maybe @@ -25,8 +26,8 @@ import Util.Size import Util.String -view : UiSettings -> Model -> Int -> Attachment -> Html Msg -view settings model pos attach = +view : Texts -> UiSettings -> Model -> Int -> Attachment -> Html Msg +view texts settings model pos attach = let fileUrl = Api.fileURL attach.id @@ -42,15 +43,16 @@ view settings model pos attach = [ class "flex flex-row px-2 py-2 text-sm" , class S.border ] - [ attachHeader settings model pos attach + [ attachHeader texts settings model pos attach ] , editAttachmentName model attach - , attachmentSelect model pos attach + , attachmentSelect texts model pos attach , if isAttachMetaOpen model attach.id then case Dict.get attach.id model.attachMeta of Just am -> Html.map (AttachMetaMsg attach.id) (Comp.AttachmentMeta.view2 + texts.attachmentMeta [ class "border-r border-l border-b dark:border-bluegray-600 px-2" ] am ) @@ -94,11 +96,11 @@ view settings model pos attach = - native view -} -attachHeader : UiSettings -> Model -> Int -> Attachment -> Html Msg -attachHeader settings model _ attach = +attachHeader : Texts -> UiSettings -> Model -> Int -> Attachment -> Html Msg +attachHeader texts settings model _ attach = let attachName = - Maybe.withDefault "No name" attach.name + Maybe.withDefault texts.noName attach.name fileUrl = Api.fileURL attach.id @@ -138,7 +140,7 @@ attachHeader settings model _ attach = , a [ href fileUrl , target "_new" - , title "Open file in new tab" + , title texts.openFileInNewTab , class S.secondaryBasicButton , class "ml-2" ] @@ -155,21 +157,21 @@ attachHeader settings model _ attach = , menuOpen = model.attachmentDropdownOpen , items = [ { icon = "fa fa-download" - , label = "Download file" + , label = texts.downloadFile , attrs = [ download attachName , href fileUrl ] } , { icon = "fa fa-file" - , label = "Rename file" + , label = texts.renameFile , attrs = [ href "#" , onClick (EditAttachNameStart attach.id) ] } , { icon = "fa fa-file-archive" - , label = "Download original archive" + , label = texts.downloadOriginalArchiveFile , attrs = [ href (fileUrl ++ "/archive") , target "_new" @@ -177,7 +179,7 @@ attachHeader settings model _ attach = ] } , { icon = "fa fa-external-link-alt" - , label = "Original file" + , label = texts.originalFile , attrs = [ href (fileUrl ++ "/original") , target "_new" @@ -190,7 +192,7 @@ attachHeader settings model _ attach = else "fa fa-toggle-off" - , label = "Render pdf by browser" + , label = texts.renderPdfByBrowser , attrs = [ onClick (TogglePdfNativeView settings.nativePdfPreview) , href "#" @@ -202,21 +204,21 @@ attachHeader settings model _ attach = else "fa fa-toggle-off" - , label = "View extracted data" + , label = texts.viewExtractedData , attrs = [ onClick (AttachMetaClick attach.id) , href "#" ] } , { icon = "fa fa-redo-alt" - , label = "Re-process this file" + , label = texts.reprocessFile , attrs = [ onClick (RequestReprocessFile attach.id) , href "#" ] } , { icon = "fa fa-trash" - , label = "Delete this file" + , label = texts.deleteThisFile , attrs = [ onClick (RequestDeleteAttachment attach.id) , href "#" @@ -279,8 +281,8 @@ editAttachmentName model attach = span [ class "hidden" ] [] -attachmentSelect : Model -> Int -> Attachment -> Html Msg -attachmentSelect model _ _ = +attachmentSelect : Texts -> Model -> Int -> Attachment -> Html Msg +attachmentSelect texts model _ _ = div [ class "flex flex-row border-l border-r px-2 py-2 dark:border-bluegray-600 " , class "overflow-x-auto overflow-y-none" @@ -288,11 +290,11 @@ attachmentSelect model _ _ = [ ( "hidden", not model.attachMenuOpen ) ] ] - (List.indexedMap (menuItem model) model.item.attachments) + (List.indexedMap (menuItem texts model) model.item.attachments) -menuItem : Model -> Int -> Attachment -> Html Msg -menuItem model pos attach = +menuItem : Texts -> Model -> Int -> Attachment -> Html Msg +menuItem texts model pos attach = let highlight = let @@ -342,7 +344,7 @@ menuItem model pos attach = ] , div [ class "mt-1 text-sm break-all w-28 text-center" ] [ Maybe.map (Util.String.ellipsis 36) attach.name - |> Maybe.withDefault "No Name" + |> Maybe.withDefault texts.noName |> text ] ] diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm index 99709b53..c8ebf07a 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm @@ -24,6 +24,7 @@ import Comp.Dropdown exposing (isDropdownChangeMsg) import Comp.Dropzone import Comp.EquipmentForm import Comp.ItemDetail.EditForm +import Comp.ItemDetail.FieldTabState as FTabState import Comp.ItemDetail.Model exposing ( AttachmentRename @@ -62,7 +63,6 @@ import Set exposing (Set) import Throttle import Time import Util.File exposing (makeFileId) -import Util.Folder exposing (mkFolderOption) import Util.Http import Util.List import Util.Maybe @@ -551,6 +551,8 @@ update key flags inav settings msg model = Comp.ConfirmModal.defaultSettings DeleteItemConfirmed ItemModalCancelled + "Ok" + "Cancel" confirmMsg in resultModel { model | itemModal = Just confirm } @@ -576,13 +578,7 @@ update key flags inav settings msg model = GetFolderResp (Ok fs) -> let model_ = - { model - | allFolders = fs.items - , folderModel = - Comp.Dropdown.setMkOption - (mkFolderOption flags fs.items) - model.folderModel - } + { model | allFolders = fs.items } mkIdName fitem = IdName fitem.id fitem.name @@ -645,23 +641,8 @@ update key flags inav settings msg model = List.filter personFilter correspondent |> List.map (\e -> IdName e.id e.name) - mkPersonOption idref = - let - org = - Dict.get idref.id personDict - |> Maybe.andThen .organization - |> Maybe.map .name - |> Maybe.map (Util.String.ellipsis 15) - |> Maybe.withDefault "" - in - Comp.Dropdown.Option idref.id idref.name org - model_ = - { model - | corrPersonModel = Comp.Dropdown.setMkOption mkPersonOption model.corrPersonModel - , concPersonModel = Comp.Dropdown.setMkOption mkPersonOption model.concPersonModel - , allPersons = personDict - } + { model | allPersons = personDict } res1 = update key @@ -945,6 +926,8 @@ update key flags inav settings msg model = Comp.ConfirmModal.defaultSettings (DeleteAttachConfirmed id) AttachModalCancelled + "Ok" + "Cancel" "Really delete this file?" model_ = @@ -1491,22 +1474,21 @@ update key flags inav settings msg model = ToggleAttachmentDropdown -> resultModel { model | attachmentDropdownOpen = not model.attachmentDropdownOpen } - ToggleAkkordionTab title -> + ToggleAkkordionTab name -> let tabs = - if Set.member title model.editMenuTabsOpen then - Set.remove title model.editMenuTabsOpen + if Set.member name model.editMenuTabsOpen then + Set.remove name model.editMenuTabsOpen else - Set.insert title model.editMenuTabsOpen + Set.insert name model.editMenuTabsOpen in resultModel { model | editMenuTabsOpen = tabs } ToggleOpenAllAkkordionTabs -> let allNames = - Comp.ItemDetail.EditForm.formTabs settings model - |> List.map .title + List.map FTabState.tabName FTabState.allTabs |> Set.fromList next = @@ -1533,6 +1515,8 @@ update key flags inav settings msg model = Comp.ConfirmModal.defaultSettings (ReprocessFileConfirmed id) AttachModalCancelled + "Ok" + "Cancel" confirmMsg model_ = @@ -1568,6 +1552,8 @@ update key flags inav settings msg model = Comp.ConfirmModal.defaultSettings ReprocessItemConfirmed ItemModalCancelled + "Ok" + "Cancel" confirmMsg model_ = diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm index 377f0b16..8b1a5e77 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/View2.elm @@ -23,17 +23,18 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Comp.ItemDetail exposing (Texts) import Page exposing (Page(..)) import Styles as S import Util.Time -view : ItemNav -> UiSettings -> Model -> Html Msg -view inav settings model = +view : Texts -> ItemNav -> UiSettings -> Model -> Html Msg +view texts inav settings model = div [ class "flex flex-col h-full" ] - [ header settings model - , menuBar inav settings model - , body inav settings model + [ header texts settings model + , menuBar texts inav settings model + , body texts inav settings model , itemModal model ] @@ -48,18 +49,18 @@ itemModal model = span [ class "hidden" ] [] -header : UiSettings -> Model -> Html Msg -header settings model = +header : Texts -> UiSettings -> Model -> Html Msg +header texts settings model = div [ class "my-3" ] - [ Comp.ItemDetail.ItemInfoHeader.view settings model ] + [ Comp.ItemDetail.ItemInfoHeader.view texts.itemInfoHeader settings model ] -menuBar : ItemNav -> UiSettings -> Model -> Html Msg -menuBar inav settings model = +menuBar : Texts -> ItemNav -> UiSettings -> Model -> Html Msg +menuBar texts inav settings model = let keyDescr name = if settings.itemDetailShortcuts && model.menuOpen then - " Key '" ++ name ++ "'." + " " ++ texts.key ++ "'" ++ name ++ "'." else "" @@ -70,7 +71,7 @@ menuBar inav settings model = a [ class S.secondaryBasicButton , Page.href HomePage - , title "Back to search results" + , title texts.backToSearchResults ] [ i [ class "fa fa-arrow-left" ] [] ] @@ -87,7 +88,7 @@ menuBar inav settings model = |> Maybe.withDefault (href "#") , disabled = inav.prev == Nothing , attrs = - [ title ("Previous item." ++ keyDescr "Ctrl-,") + [ title (texts.previousItem ++ keyDescr "Ctrl-,") ] } , div @@ -116,7 +117,7 @@ menuBar inav settings model = |> Maybe.withDefault (href "#") , disabled = inav.next == Nothing , attrs = - [ title ("Next item." ++ keyDescr "Ctrl-.") + [ title (texts.nextItem ++ keyDescr "Ctrl-.") ] } ] @@ -125,7 +126,7 @@ menuBar inav settings model = [ classList [ ( "bg-gray-200 dark:bg-bluegray-600", model.mailOpen ) ] - , title "Send Mail" + , title texts.sendMail , onClick ToggleMail , class S.secondaryBasicButton , href "#" @@ -141,7 +142,7 @@ menuBar inav settings model = title "Close" else - title "Add more files to this item" + title texts.addMoreFiles , onClick AddFilesToggle , class S.secondaryBasicButton , href "#" @@ -153,11 +154,11 @@ menuBar inav settings model = [ class S.primaryButton , href "#" , onClick ConfirmItem - , title "Confirm item metadata" + , title texts.confirmItemMetadata , classList [ ( "hidden", model.item.state /= "created" ) ] ] [ i [ class "fa fa-check mr-2" ] [] - , text "Confirm" + , text texts.confirm ] ] , end = @@ -166,7 +167,7 @@ menuBar inav settings model = [ class S.secondaryBasicButton , href "#" , onClick UnconfirmItem - , title "Un-confirm item metadata" + , title texts.unconfirmItemMetadata , classList [ ( "hidden", model.item.state == "created" ) ] ] [ i [ class "fa fa-eye-slash font-thin" ] [] @@ -176,7 +177,7 @@ menuBar inav settings model = [ class S.secondaryBasicButton , href "#" , onClick RequestReprocessItem - , title "Reprocess this item" + , title texts.reprocessItem ] [ i [ class "fa fa-redo" ] [] ] @@ -185,7 +186,7 @@ menuBar inav settings model = [ class S.deleteButton , href "#" , onClick RequestDelete - , title "Delete this item" + , title texts.deleteThisItem ] [ i [ class "fa fa-trash" ] [] ] @@ -194,21 +195,21 @@ menuBar inav settings model = } -body : ItemNav -> UiSettings -> Model -> Html Msg -body inav settings model = +body : Texts -> ItemNav -> UiSettings -> Model -> Html Msg +body texts _ settings model = div [ class "grid gap-2 grid-cols-1 md:grid-cols-3 h-full" ] - [ leftArea settings model - , rightArea settings model + [ leftArea texts settings model + , rightArea texts settings model ] -leftArea : UiSettings -> Model -> Html Msg -leftArea settings model = +leftArea : Texts -> UiSettings -> Model -> Html Msg +leftArea texts settings model = div [ class "w-full md:order-first md:mr-2 flex flex-col" ] - [ addDetailForm settings model - , sendMailForm settings model - , Comp.ItemDetail.AddFilesForm.view model - , Comp.ItemDetail.Notes.view model + [ addDetailForm texts settings model + , sendMailForm texts settings model + , Comp.ItemDetail.AddFilesForm.view texts.addFilesForm model + , Comp.ItemDetail.Notes.view texts.notes model , div [ classList [ ( "hidden", Comp.SentMails.isEmpty model.sentMails ) @@ -216,29 +217,29 @@ leftArea settings model = , class "mt-4 " ] [ h3 [ class "flex flex-row items-center border-b dark:border-bluegray-600 font-bold text-lg" ] - [ text "Sent E-Mails" + [ text texts.sentEmails ] - , Html.map SentMailsMsg (Comp.SentMails.view2 model.sentMails) + , Html.map SentMailsMsg (Comp.SentMails.view2 texts.sentMails model.sentMails) ] , div [ class "flex-grow" ] [] - , itemIdInfo model + , itemIdInfo texts model ] -rightArea : UiSettings -> Model -> Html Msg -rightArea settings model = +rightArea : Texts -> UiSettings -> Model -> Html Msg +rightArea texts settings model = div [ class "md:col-span-2 h-full" ] - (attachmentsBody settings model) + (attachmentsBody texts settings model) -attachmentsBody : UiSettings -> Model -> List (Html Msg) -attachmentsBody settings model = - List.indexedMap (Comp.ItemDetail.SingleAttachment.view settings model) +attachmentsBody : Texts -> UiSettings -> Model -> List (Html Msg) +attachmentsBody texts settings model = + List.indexedMap (Comp.ItemDetail.SingleAttachment.view texts.singleAttachment settings model) model.item.attachments -sendMailForm : UiSettings -> Model -> Html Msg -sendMailForm settings model = +sendMailForm : Texts -> UiSettings -> Model -> Html Msg +sendMailForm texts settings model = div [ classList [ ( "hidden", not model.mailOpen ) @@ -247,10 +248,13 @@ sendMailForm settings model = , class "mb-4 px-2 py-2" ] [ div [ class "text-lg font-bold" ] - [ text "Send this item via E-Mail" + [ text texts.sendThisItemViaEmail ] - , B.loadingDimmer model.mailSending - , Html.map ItemMailMsg (Comp.ItemMail.view2 settings model.itemMail) + , B.loadingDimmer + { active = model.mailSending + , label = texts.sendingMailNow + } + , Html.map ItemMailMsg (Comp.ItemMail.view2 texts.itemMail settings model.itemMail) , div [ classList [ ( S.errorMessage @@ -273,26 +277,26 @@ sendMailForm settings model = ] -itemIdInfo : Model -> Html msg -itemIdInfo model = +itemIdInfo : Texts -> Model -> Html msg +itemIdInfo texts model = div [ class "flex flex-col opacity-50 text-xs pb-1 mt-3 border-t dark:border-bluegray-600" ] [ div [ class "inline-flex items-center" - , title "Item ID" + , title texts.itemId ] [ i [ class "fa fa-bullseye mr-2" ] [] , text model.item.id ] , div [ class "inline-flex items-center" - , title "Created on" + , title texts.createdOn ] [ i [ class "fa fa-sun font-thin mr-2" ] [] , Util.Time.formatDateTime model.item.created |> text ] , div [ class "inline-flex items-center" - , title "Last update on" + , title texts.lastUpdateOn ] [ i [ class "fa fa-pencil-alt mr-2" ] [] , Util.Time.formatDateTime model.item.updated |> text @@ -300,8 +304,8 @@ itemIdInfo model = ] -addDetailForm : UiSettings -> Model -> Html Msg -addDetailForm settings model = +addDetailForm : Texts -> UiSettings -> Model -> Html Msg +addDetailForm texts settings model = case model.modalEdit of Just mm -> div @@ -309,7 +313,7 @@ addDetailForm settings model = , class S.box ] [ Comp.DetailEdit.formHeading S.header3 mm - , Html.map ModalEditMsg (Comp.DetailEdit.view2 [] settings mm) + , Html.map ModalEditMsg (Comp.DetailEdit.view2 texts.detailEdit [] settings mm) ] Nothing -> diff --git a/modules/webapp/src/main/elm/Comp/ItemMail.elm b/modules/webapp/src/main/elm/Comp/ItemMail.elm index 718f64a3..01309ec4 100644 --- a/modules/webapp/src/main/elm/Comp/ItemMail.elm +++ b/modules/webapp/src/main/elm/Comp/ItemMail.elm @@ -23,6 +23,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Http +import Messages.Comp.ItemMail exposing (Texts) import Styles as S import Util.Http @@ -69,11 +70,7 @@ type FormAction emptyModel : Model emptyModel = - { connectionModel = - Comp.Dropdown.makeSingle - { makeOption = \a -> { value = a, text = a, additional = "" } - , placeholder = "Select connection..." - } + { connectionModel = Comp.Dropdown.makeSingle , subject = "" , recipients = [] , recipientsModel = Comp.EmailInput.init @@ -160,9 +157,7 @@ update flags msg model = cm = Comp.Dropdown.makeSingleList - { makeOption = \a -> { value = a, text = a, additional = "" } - , placeholder = "Select Connection..." - , options = names + { options = names , selected = List.head names } in @@ -224,21 +219,33 @@ isValid model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = let dds = Data.DropdownStyle.mainStyle + + connectionCfg = + { makeOption = \a -> { text = a, additional = "" } + , placeholder = texts.selectConnection + , labelColor = \_ -> \_ -> "" + , style = dds + } in div [ class "flex flex-col" ] [ div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Send via" + [ text texts.sendVia , B.inputRequired ] - , Html.map ConnMsg (Comp.Dropdown.view2 dds settings model.connectionModel) + , Html.map ConnMsg + (Comp.Dropdown.view2 + connectionCfg + settings + model.connectionModel + ) ] , div [ class S.errorMessage @@ -250,29 +257,38 @@ view2 settings model = [ label [ class S.inputLabel ] - [ text "Recipient(s)" + [ text texts.recipients , B.inputRequired ] , Html.map RecipientMsg - (Comp.EmailInput.view2 dds model.recipients model.recipientsModel) + (Comp.EmailInput.view2 { style = dds, placeholder = appendDots texts.recipients } + model.recipients + model.recipientsModel + ) ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "CC(s)" + [ text texts.ccRecipients ] , Html.map CCRecipientMsg - (Comp.EmailInput.view2 dds model.ccRecipients model.ccRecipientsModel) + (Comp.EmailInput.view2 { style = dds, placeholder = appendDots texts.ccRecipients } + model.ccRecipients + model.ccRecipientsModel + ) ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "BCC(s)" + [ text texts.bccRecipients ] , Html.map BCCRecipientMsg - (Comp.EmailInput.view2 dds model.bccRecipients model.bccRecipientsModel) + (Comp.EmailInput.view2 { style = dds, placeholder = appendDots texts.bccRecipients } + model.bccRecipients + model.bccRecipientsModel + ) ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Subject" + [ text texts.subject , B.inputRequired ] , input @@ -285,7 +301,7 @@ view2 settings model = ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Body" + [ text texts.body , B.inputRequired ] , textarea @@ -298,7 +314,7 @@ view2 settings model = , MB.viewItem <| MB.Checkbox { tagger = \_ -> ToggleAttachAll - , label = "Include all item attachments" + , label = texts.includeAllAttachments , value = model.attachAll , id = "item-send-mail-attach-all" } @@ -311,7 +327,7 @@ view2 settings model = , disabled = not (isValid model) } , B.secondaryButton - { label = "Cancel" + { label = texts.basics.cancel , icon = "fa fa-times" , handler = onClick Cancel , attrs = [ href "#" ] @@ -319,3 +335,8 @@ view2 settings model = } ] ] + + +appendDots : String -> String +appendDots name = + name ++ "…" diff --git a/modules/webapp/src/main/elm/Comp/MarkdownInput.elm b/modules/webapp/src/main/elm/Comp/MarkdownInput.elm index 9209d739..8254d325 100644 --- a/modules/webapp/src/main/elm/Comp/MarkdownInput.elm +++ b/modules/webapp/src/main/elm/Comp/MarkdownInput.elm @@ -68,48 +68,48 @@ viewContent2 txt model = splitDisplay2 txt -viewEditLink2 : (Bool -> Attribute Msg) -> Model -> Html Msg -viewEditLink2 classes model = +viewEditLink2 : String -> (Bool -> Attribute Msg) -> Model -> Html Msg +viewEditLink2 label classes model = a [ onClick (SetDisplay Edit) , classes (model.display == Edit) , href "#" ] - [ text "Edit" + [ text label ] -viewPreviewLink2 : (Bool -> Attribute Msg) -> Model -> Html Msg -viewPreviewLink2 classes model = +viewPreviewLink2 : String -> (Bool -> Attribute Msg) -> Model -> Html Msg +viewPreviewLink2 label classes model = a [ onClick (SetDisplay Preview) , classes (model.display == Preview) , href "#" ] - [ text "Preview" + [ text label ] -viewSplitLink2 : (Bool -> Attribute Msg) -> Model -> Html Msg -viewSplitLink2 classes model = +viewSplitLink2 : String -> (Bool -> Attribute Msg) -> Model -> Html Msg +viewSplitLink2 label classes model = a [ onClick (SetDisplay Split) , classes (model.display == Split) , href "#" ] - [ text "Split" + [ text label ] -viewCheatLink2 : String -> Model -> Html msg -viewCheatLink2 classes model = +viewCheatLink2 : String -> String -> Model -> Html msg +viewCheatLink2 label classes model = a [ class classes , target "_new" , href model.cheatSheetUrl ] [ i [ class "fa fa-question mr-2" ] [] - , text "Supports Markdown" + , text label ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationForm.elm b/modules/webapp/src/main/elm/Comp/NotificationForm.elm index c5c5932d..f73d7eca 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationForm.elm +++ b/modules/webapp/src/main/elm/Comp/NotificationForm.elm @@ -30,6 +30,8 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) import Http +import Markdown +import Messages.Comp.NotificationForm exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -144,17 +146,13 @@ init flags = Comp.CalEventInput.initDefault in ( { settings = Api.Model.NotificationSettings.empty - , connectionModel = - Comp.Dropdown.makeSingle - { makeOption = \a -> { value = a, text = a, additional = "" } - , placeholder = "Select connection..." - } - , tagInclModel = Util.Tag.makeDropdownModel2 - , tagExclModel = Util.Tag.makeDropdownModel2 + , connectionModel = Comp.Dropdown.makeSingle + , tagInclModel = Util.Tag.makeDropdownModel + , tagExclModel = Util.Tag.makeDropdownModel , recipients = [] , recipientsModel = Comp.EmailInput.init , remindDays = Just 1 - , remindDaysModel = Comp.IntField.init (Just 1) Nothing True "Remind Days" + , remindDaysModel = Comp.IntField.init (Just 1) Nothing True , enabled = False , capOverdue = False , schedule = initialSchedule @@ -298,9 +296,7 @@ update flags msg model = cm = Comp.Dropdown.makeSingleList - { makeOption = \a -> { value = a, text = a, additional = "" } - , placeholder = "Select Connection..." - , options = names + { options = names , selected = List.head names } in @@ -480,19 +476,28 @@ isFormSuccess model = |> Maybe.withDefault False -view2 : String -> UiSettings -> Model -> Html Msg -view2 extraClasses settings model = +view2 : Texts -> String -> UiSettings -> Model -> Html Msg +view2 texts extraClasses settings model = let dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this notification task?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteTask + texts.basics.yes + texts.basics.no startOnceBtn = MB.SecondaryButton { tagger = StartOnce - , label = "Start Once" - , title = "Start this task now" + , label = texts.startOnce + , title = texts.startTaskNow , icon = Just "fa fa-play" } + + connectionCfg = + { makeOption = \a -> { text = a, additional = "" } + , placeholder = texts.selectConnection + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } in div [ class "flex flex-col md:relative" @@ -503,19 +508,22 @@ view2 extraClasses settings model = dimmerSettings model.yesNoDelete ) - , B.loadingDimmer (model.loading > 0) + , B.loadingDimmer + { active = model.loading > 0 + , label = texts.basics.loading + } , MB.view { start = [ MB.PrimaryButton { tagger = Submit - , label = "Submit" - , title = "Save" + , label = texts.basics.submit + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" } , MB.SecondaryButton { tagger = Cancel - , label = "Cancel" - , title = "Back to list" + , label = texts.basics.cancel + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" } ] @@ -524,8 +532,8 @@ view2 extraClasses settings model = [ startOnceBtn , MB.DeleteButton { tagger = RequestDelete - , label = "Delete" - , title = "Delete this task" + , label = texts.basics.delete + , title = texts.deleteThisTask , icon = Just "fa fa-trash" } ] @@ -551,14 +559,14 @@ view2 extraClasses settings model = [ MB.viewItem <| MB.Checkbox { tagger = \_ -> ToggleEnabled - , label = "Enable or disable this task." + , label = texts.enableDisable , value = model.enabled , id = "notify-enabled" } ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Summary" + [ text texts.summary ] , input [ type_ "text" @@ -569,72 +577,74 @@ view2 extraClasses settings model = ] [] , span [ class "opacity-50 text-sm" ] - [ text "Some human readable name, only for displaying" + [ text texts.summaryInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Send via" + [ text texts.sendVia , B.inputRequired ] , Html.map ConnMsg (Comp.Dropdown.view2 - DS.mainStyle + connectionCfg settings model.connectionModel ) , span [ class "opacity-50 text-sm" ] - [ text "The SMTP connection to use when sending notification mails." + [ text texts.sendViaInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Recipient(s)" + [ text texts.recipients , B.inputRequired ] , Html.map RecipientMsg (Comp.EmailInput.view2 - DS.mainStyle + { style = DS.mainStyle, placeholder = texts.recipients } model.recipients model.recipientsModel ) , span [ class "opacity-50 text-sm" ] - [ text "One or more mail addresses, confirm each by pressing 'Return'." + [ text texts.recipientsInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Tags Include (and)" ] + [ text texts.tagsInclude ] , Html.map TagIncMsg (Comp.Dropdown.view2 - DS.mainStyle + (Util.Tag.tagSettings texts.basics.chooseTag DS.mainStyle) settings model.tagInclModel ) , span [ class "opacity-50 text-sm" ] - [ text "Items must have all the tags specified here." + [ text texts.tagsIncludeInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Tags Exclude (or)" ] + [ text texts.tagsExclude ] , Html.map TagExcMsg (Comp.Dropdown.view2 - DS.mainStyle + (Util.Tag.tagSettings texts.basics.chooseTag DS.mainStyle) settings model.tagExclModel ) , span [ class "small-info" ] - [ text "Items must not have any tag specified here." + [ text texts.tagsExcludeInfo ] ] , Html.map RemindDaysMsg - (Comp.IntField.viewWithInfo2 - "Select items with a due date *lower than* `today+remindDays`" - model.remindDays - "mb-4" + (Comp.IntField.view + { label = texts.remindDaysLabel + , info = texts.remindDaysInfo + , number = model.remindDays + , classes = "mb-4" + } model.remindDaysModel ) , div [ class "mb-4" ] @@ -643,20 +653,15 @@ view2 extraClasses settings model = { tagger = \_ -> ToggleCapOverdue , id = "notify-toggle-cap-overdue" , value = model.capOverdue - , label = "Cap overdue items" + , label = texts.capOverdue } , div [ class "opacity-50 text-sm" ] - [ text "If checked, only items with a due date" - , em [ class "font-italic" ] - [ text " greater than " ] - , code [ class "font-mono" ] - [ text "today-remindDays" ] - , text " are considered." + [ Markdown.toHtml [] texts.capOverdueInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Schedule" + [ text texts.schedule , a [ class "float-right" , class S.link @@ -665,20 +670,19 @@ view2 extraClasses settings model = ] [ i [ class "fa fa-question" ] [] , span [ class "pl-2" ] - [ text "Click here for help" + [ text texts.scheduleClickForHelp ] ] ] , Html.map CalEventMsg - (Comp.CalEventInput.view2 "" + (Comp.CalEventInput.view2 + texts.calEventInput + "" (Data.Validated.value model.schedule) model.scheduleModel ) , span [ class "opacity-50 text-sm" ] - [ text "Specify how often and when this task should run. " - , text "Use English 3-letter weekdays. Either a single value, " - , text "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) " - , text "is allowed for each part." + [ text texts.scheduleInfo ] ] ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationList.elm b/modules/webapp/src/main/elm/Comp/NotificationList.elm index c87bf16b..48011b6b 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationList.elm +++ b/modules/webapp/src/main/elm/Comp/NotificationList.elm @@ -11,6 +11,7 @@ import Api.Model.NotificationSettings exposing (NotificationSettings) import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.NotificationTable exposing (Texts) import Styles as S import Util.Html @@ -44,8 +45,8 @@ update msg model = --- View2 -view2 : Model -> List NotificationSettings -> Html Msg -view2 _ items = +view2 : Texts -> Model -> List NotificationSettings -> Html Msg +view2 texts _ items = div [] [ table [ class S.tableMain ] [ thead [] @@ -54,13 +55,13 @@ view2 _ items = , th [ class "text-center mr-2" ] [ i [ class "fa fa-check" ] [] ] - , th [ class "text-left " ] [ text "Summary" ] + , th [ class "text-left " ] [ text texts.summary ] , th [ class "text-left hidden sm:table-cell mr-2" ] - [ text "Schedule" ] + [ text texts.schedule ] , th [ class "text-left mr-2" ] - [ text "Connection" ] + [ text texts.connection ] , th [ class "text-left hidden sm:table-cell mr-2" ] - [ text "Recipients" ] + [ text texts.recipients ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/NotificationManage.elm b/modules/webapp/src/main/elm/Comp/NotificationManage.elm index e1b2467a..4d7631ff 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationManage.elm +++ b/modules/webapp/src/main/elm/Comp/NotificationManage.elm @@ -18,6 +18,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Http +import Messages.Comp.NotificationManage exposing (Texts) import Styles as S import Util.Http @@ -212,8 +213,8 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = div [ class "flex flex-col" ] (div [ classList @@ -229,34 +230,38 @@ view2 settings model = ] :: (case model.detailModel of Just msett -> - viewForm2 settings msett + viewForm2 texts settings msett Nothing -> - viewList2 model + viewList2 texts model ) ) -viewForm2 : UiSettings -> Comp.NotificationForm.Model -> List (Html Msg) -viewForm2 settings model = +viewForm2 : Texts -> UiSettings -> Comp.NotificationForm.Model -> List (Html Msg) +viewForm2 texts settings model = [ Html.map DetailMsg - (Comp.NotificationForm.view2 "flex flex-col" settings model) + (Comp.NotificationForm.view2 texts.notificationForm "flex flex-col" settings model) ] -viewList2 : Model -> List (Html Msg) -viewList2 model = +viewList2 : Texts -> Model -> List (Html Msg) +viewList2 texts model = [ MB.view { start = [ MB.PrimaryButton { tagger = NewTask - , label = "New Task" + , label = texts.newTask , icon = Just "fa fa-plus" - , title = "Create a new notification task" + , title = texts.createNewTask } ] , end = [] , rootClasses = "mb-4" } - , Html.map ListMsg (Comp.NotificationList.view2 model.listModel model.items) + , Html.map ListMsg + (Comp.NotificationList.view2 texts.notificationTable + model.listModel + model.items + ) ] diff --git a/modules/webapp/src/main/elm/Comp/OrgForm.elm b/modules/webapp/src/main/elm/Comp/OrgForm.elm index 5f2584fe..63916044 100644 --- a/modules/webapp/src/main/elm/Comp/OrgForm.elm +++ b/modules/webapp/src/main/elm/Comp/OrgForm.elm @@ -13,12 +13,14 @@ import Comp.AddressForm import Comp.Basic as B import Comp.ContactField import Comp.FixedDropdown +import Data.DropdownStyle as DS import Data.Flags exposing (Flags) import Data.OrgUse exposing (OrgUse) import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.OrgForm exposing (Texts) import Styles as S import Util.Maybe @@ -45,9 +47,7 @@ emptyModel = , shortName = Nothing , use = Data.OrgUse.Correspondent , useModel = - Comp.FixedDropdown.initMap - Data.OrgUse.label - Data.OrgUse.all + Comp.FixedDropdown.init Data.OrgUse.all } @@ -147,14 +147,20 @@ update flags msg model = --- View2 -makeUseItem : Model -> Maybe (Comp.FixedDropdown.Item OrgUse) -makeUseItem model = - Just <| - Comp.FixedDropdown.Item model.use (Data.OrgUse.label model.use) +view2 : Texts -> Bool -> UiSettings -> Model -> Html Msg +view2 texts mobile settings model = + let + orgUseCfg = + { display = texts.orgUseLabel + , icon = \_ -> Nothing + , style = DS.mainStyle + } - -view2 : Bool -> UiSettings -> Model -> Html Msg -view2 mobile settings model = + contactTypeCfg = + { mobile = mobile + , contactTypeLabel = texts.contactTypeLabel + } + in div [ class "flex flex-col" ] [ div [ class "mb-4" ] @@ -162,13 +168,13 @@ view2 mobile settings model = [ for "orgname" , class S.inputLabel ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , onInput SetName - , placeholder "Name" + , placeholder texts.basics.name , value model.name , name "orgname" , class S.textInput @@ -184,12 +190,12 @@ view2 mobile settings model = [ for "org-short-name" , class S.inputLabel ] - [ text "Short Name" + [ text texts.shortName ] , input [ type_ "text" , onInput SetShortName - , placeholder "Abbreviation" + , placeholder texts.shortName , Maybe.withDefault "" model.shortName |> value , name "org-short-name" @@ -201,35 +207,40 @@ view2 mobile settings model = [ label [ class S.inputLabel ] - [ text "Use" ] + [ text texts.use + ] , Html.map UseDropdownMsg - (Comp.FixedDropdown.view2 (makeUseItem model) model.useModel) + (Comp.FixedDropdown.viewStyled2 orgUseCfg + False + (Just model.use) + model.useModel + ) , span [ class "opacity-50 text-sm" ] [ case model.use of Data.OrgUse.Correspondent -> - text "Use as correspondent" + text texts.useAsCorrespondent Data.OrgUse.Disabled -> - text "Do not use for suggestions." + text texts.dontUseForSuggestions ] ] , div [ class "mb-4" ] [ h3 [ class S.header3 ] - [ text "Address" + [ text texts.address ] , Html.map AddressMsg - (Comp.AddressForm.view2 settings model.addressModel) + (Comp.AddressForm.view2 texts.addressForm settings model.addressModel) ] , div [ class "mb-4" ] [ h3 [ class S.header3 ] - [ text "Contacts" + [ text texts.contacts ] , Html.map ContactMsg - (Comp.ContactField.view2 mobile settings model.contactModel) + (Comp.ContactField.view2 contactTypeCfg settings model.contactModel) ] , div [ class "mb-4" ] [ h3 [ class S.header3 ] - [ text "Notes" + [ text texts.notes ] , div [ class "" ] [ textarea diff --git a/modules/webapp/src/main/elm/Comp/OrgManage.elm b/modules/webapp/src/main/elm/Comp/OrgManage.elm index 1cdc03fe..44c62299 100644 --- a/modules/webapp/src/main/elm/Comp/OrgManage.elm +++ b/modules/webapp/src/main/elm/Comp/OrgManage.elm @@ -21,6 +21,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onSubmit) import Http +import Messages.Comp.OrgManage exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -205,50 +206,55 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = if model.viewMode == Table then - viewTable2 model + viewTable2 texts model else - viewForm2 settings model + viewForm2 texts settings model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col relative" ] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNewOrg - , title = "Create a new organization" + , title = texts.createNewOrganization , icon = Just "fa fa-plus" - , label = "New Organization" + , label = texts.newOrganization } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.OrgTable.view2 model.tableModel) - , B.loadingDimmer model.loading + , Html.map TableMsg (Comp.OrgTable.view2 texts.orgTable model.tableModel) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] -viewForm2 : UiSettings -> Model -> Html Msg -viewForm2 settings model = +viewForm2 : Texts -> UiSettings -> Model -> Html Msg +viewForm2 texts settings model = let newOrg = model.formModel.org.id == "" dimmerSettings2 = - Comp.YesNoDimmer.defaultSettings2 "Really delete this organization?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteOrg + texts.basics.yes + texts.basics.no in Html.form [ class "md:relative flex flex-col" @@ -262,14 +268,14 @@ viewForm2 settings model = ) , if newOrg then h3 [ class S.header2 ] - [ text "Create new organization" + [ text texts.createNewOrganization ] else h3 [ class S.header2 ] [ text model.formModel.org.name , div [ class "opacity-50 text-sm" ] - [ text "Id: " + [ text (texts.basics.id ++ ": ") , text model.formModel.org.id ] ] @@ -277,24 +283,24 @@ viewForm2 settings model = { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if not newOrg then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this organization" + , title = texts.deleteThisOrg , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -311,6 +317,15 @@ viewForm2 settings model = ] [ Maybe.withDefault "" model.formError |> text ] - , Html.map FormMsg (Comp.OrgForm.view2 False settings model.formModel) - , B.loadingDimmer model.loading + , Html.map FormMsg + (Comp.OrgForm.view2 + texts.orgForm + False + settings + model.formModel + ) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/OrgTable.elm b/modules/webapp/src/main/elm/Comp/OrgTable.elm index 33d64e38..68e377d4 100644 --- a/modules/webapp/src/main/elm/Comp/OrgTable.elm +++ b/modules/webapp/src/main/elm/Comp/OrgTable.elm @@ -12,6 +12,7 @@ import Data.Flags exposing (Flags) import Data.OrgUse import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.OrgTable exposing (Texts) import Styles as S import Util.Address import Util.Contact @@ -53,8 +54,8 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] @@ -62,18 +63,24 @@ view2 model = , th [ class "text-left pr-1 md:px-2" ] [ text "Use" ] - , th [ class "text-left" ] [ text "Name" ] - , th [ class "text-left hidden md:table-cell" ] [ text "Address" ] - , th [ class "text-left hidden sm:table-cell" ] [ text "Contact" ] + , th [ class "text-left" ] + [ text texts.basics.name + ] + , th [ class "text-left hidden md:table-cell" ] + [ text texts.address + ] + , th [ class "text-left hidden sm:table-cell" ] + [ text texts.contact + ] ] ] , tbody [] - (List.map (renderOrgLine2 model) model.orgs) + (List.map (renderOrgLine2 texts model) model.orgs) ] -renderOrgLine2 : Model -> Organization -> Html Msg -renderOrgLine2 model org = +renderOrgLine2 : Texts -> Model -> Organization -> Html Msg +renderOrgLine2 texts model org = tr [ classList [ ( "active", model.selected == Just org ) ] , class S.tableRow @@ -83,7 +90,7 @@ renderOrgLine2 model org = [ div [ class "label inline-flex text-sm" ] [ Data.OrgUse.fromString org.use |> Maybe.withDefault Data.OrgUse.Correspondent - |> Data.OrgUse.label + |> texts.orgUseLabel |> text ] ] diff --git a/modules/webapp/src/main/elm/Comp/PasswordInput.elm b/modules/webapp/src/main/elm/Comp/PasswordInput.elm index 70fc645b..7d245be5 100644 --- a/modules/webapp/src/main/elm/Comp/PasswordInput.elm +++ b/modules/webapp/src/main/elm/Comp/PasswordInput.elm @@ -49,8 +49,13 @@ update msg model = --- View2 -view2 : Maybe String -> Bool -> Model -> Html Msg -view2 pw isError model = +type alias ViewSettings = + { placeholder : String + } + + +view2 : ViewSettings -> Maybe String -> Bool -> Model -> Html Msg +view2 cfg pw isError model = div [ class "relative" ] [ div [ class S.inputIcon ] [ i @@ -81,7 +86,7 @@ view2 pw isError model = else "" - , placeholder "Password" + , placeholder cfg.placeholder ] [] , a diff --git a/modules/webapp/src/main/elm/Comp/PersonForm.elm b/modules/webapp/src/main/elm/Comp/PersonForm.elm index e9b35c79..9ada6a32 100644 --- a/modules/webapp/src/main/elm/Comp/PersonForm.elm +++ b/modules/webapp/src/main/elm/Comp/PersonForm.elm @@ -22,6 +22,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.PersonForm exposing (Texts) import Styles as S @@ -46,10 +47,8 @@ emptyModel = , notes = Nothing , use = Data.PersonUse.Both , useModel = - Comp.FixedDropdown.initMap - Data.PersonUse.label - Data.PersonUse.all - , orgModel = Comp.Dropdown.orgDropdown + Comp.FixedDropdown.init Data.PersonUse.all + , orgModel = Comp.Dropdown.makeSingle } @@ -176,18 +175,24 @@ update flags msg model = ) -makeUseItem : Model -> Maybe (Comp.FixedDropdown.Item PersonUse) -makeUseItem model = - Just <| - Comp.FixedDropdown.Item model.use (Data.PersonUse.label model.use) - - --- View2 -view2 : Bool -> UiSettings -> Model -> Html Msg -view2 mobile settings model = +view2 : Texts -> Bool -> UiSettings -> Model -> Html Msg +view2 texts mobile settings model = + let + personUseCfg = + { display = texts.personUseLabel + , icon = \_ -> Nothing + , style = DS.mainStyle + } + + contactCfg = + { mobile = mobile + , contactTypeLabel = texts.contactTypeLabel + } + in div [ class "flex flex-col" ] [ div [ class "mb-4" @@ -196,13 +201,13 @@ view2 mobile settings model = [ class S.inputLabel , for "personname" ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , onInput SetName - , placeholder "Name" + , placeholder texts.basics.name , value model.name , class S.textInput , classList @@ -216,53 +221,58 @@ view2 mobile settings model = [ label [ class S.inputLabel ] - [ text "Use of this person" ] + [ text texts.useOfPerson + ] , Html.map UseDropdownMsg - (Comp.FixedDropdown.view2 (makeUseItem model) model.useModel) + (Comp.FixedDropdown.viewStyled2 personUseCfg False (Just model.use) model.useModel) , span [ class "opacity-50 text-sm" ] [ case model.use of Data.PersonUse.Concerning -> - text "Use as concerning person only" + text texts.useAsConcerningOnly Data.PersonUse.Correspondent -> - text "Use as correspondent person only" + text texts.useAsCorrespondentOnly Data.PersonUse.Both -> - text "Use as both concerning or correspondent person" + text texts.useAsBoth Data.PersonUse.Disabled -> - text "Do not use for suggestions." + text texts.dontUseForSuggestions ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Organization" + [ text texts.basics.organization ] , Html.map OrgDropdownMsg (Comp.Dropdown.view2 - DS.mainStyle + (Comp.Dropdown.orgFormViewSettings texts.chooseAnOrg DS.mainStyle) settings model.orgModel ) ] , div [ class "mb-4" ] [ h3 [ class "ui dividing header" ] - [ text "Address" + [ text texts.address ] - , Html.map AddressMsg (Comp.AddressForm.view2 settings model.addressModel) + , Html.map AddressMsg + (Comp.AddressForm.view2 texts.addressForm + settings + model.addressModel + ) ] , div [ class "mb-4" ] [ h3 [ class S.header3 ] - [ text "Contacts" + [ text texts.contacts ] , Html.map ContactMsg - (Comp.ContactField.view2 mobile settings model.contactModel) + (Comp.ContactField.view2 contactCfg settings model.contactModel) ] , div [ class "mb-4" ] [ h3 [ class S.header3 ] - [ text "Notes" + [ text texts.notes ] , div [ class "" ] [ textarea diff --git a/modules/webapp/src/main/elm/Comp/PersonManage.elm b/modules/webapp/src/main/elm/Comp/PersonManage.elm index 6e52da6a..c27e7d25 100644 --- a/modules/webapp/src/main/elm/Comp/PersonManage.elm +++ b/modules/webapp/src/main/elm/Comp/PersonManage.elm @@ -22,6 +22,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onSubmit) import Http +import Messages.Comp.PersonManage exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -242,50 +243,55 @@ isLoading model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = if model.viewMode == Table then - viewTable2 model + viewTable2 texts model else - viewForm2 settings model + viewForm2 texts settings model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col" ] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNewPerson - , title = "Create a new person" + , title = texts.createNewPerson , icon = Just "fa fa-plus" - , label = "New Person" + , label = texts.newPerson } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.PersonTable.view2 model.tableModel) - , B.loadingDimmer (isLoading model) + , Html.map TableMsg (Comp.PersonTable.view2 texts.personTable model.tableModel) + , B.loadingDimmer + { active = isLoading model + , label = texts.basics.loading + } ] -viewForm2 : UiSettings -> Model -> Html Msg -viewForm2 settings model = +viewForm2 : Texts -> UiSettings -> Model -> Html Msg +viewForm2 texts settings model = let newPerson = model.formModel.person.id == "" dimmerSettings2 = - Comp.YesNoDimmer.defaultSettings2 "Really delete this person?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeletePerson + texts.basics.yes + texts.basics.no in Html.form [ class "md:relative flex flex-col" @@ -299,14 +305,14 @@ viewForm2 settings model = ) , if newPerson then h3 [ class S.header2 ] - [ text "Create new person" + [ text texts.createNewPerson ] else h3 [ class S.header2 ] [ text model.formModel.person.name , div [ class "opacity-50 text-sm" ] - [ text "Id: " + [ text (texts.basics.id ++ ": ") , text model.formModel.person.id ] ] @@ -314,24 +320,24 @@ viewForm2 settings model = { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if not newPerson then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this person" + , title = texts.deleteThisPerson , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -348,6 +354,14 @@ viewForm2 settings model = ] [ Maybe.withDefault "" model.formError |> text ] - , Html.map FormMsg (Comp.PersonForm.view2 False settings model.formModel) - , B.loadingDimmer (isLoading model) + , Html.map FormMsg + (Comp.PersonForm.view2 texts.personForm + False + settings + model.formModel + ) + , B.loadingDimmer + { active = isLoading model + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/PersonTable.elm b/modules/webapp/src/main/elm/Comp/PersonTable.elm index 8646cc9f..9afb1acb 100644 --- a/modules/webapp/src/main/elm/Comp/PersonTable.elm +++ b/modules/webapp/src/main/elm/Comp/PersonTable.elm @@ -12,6 +12,7 @@ import Data.Flags exposing (Flags) import Data.PersonUse import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.PersonTable exposing (Texts) import Styles as S import Util.Contact @@ -52,27 +53,27 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "w-px whitespace-nowrap" ] [] , th [ class "text-left pr-1 md:px-2" ] - [ text "Use" + [ text texts.use ] - , th [ class "text-left" ] [ text "Name" ] - , th [ class "text-left hidden sm:table-cell" ] [ text "Organization" ] - , th [ class "text-left hidden md:table-cell" ] [ text "Contact" ] + , th [ class "text-left" ] [ text texts.basics.name ] + , th [ class "text-left hidden sm:table-cell" ] [ text texts.basics.organization ] + , th [ class "text-left hidden md:table-cell" ] [ text texts.contact ] ] ] , tbody [] - (List.map (renderPersonLine2 model) model.equips) + (List.map (renderPersonLine2 texts model) model.equips) ] -renderPersonLine2 : Model -> Person -> Html Msg -renderPersonLine2 model person = +renderPersonLine2 : Texts -> Model -> Person -> Html Msg +renderPersonLine2 texts model person = tr [ classList [ ( "active", model.selected == Just person ) ] , class S.tableRow @@ -82,7 +83,7 @@ renderPersonLine2 model person = [ div [ class "label inline-flex text-sm" ] [ Data.PersonUse.fromString person.use |> Maybe.withDefault Data.PersonUse.Both - |> Data.PersonUse.label + |> texts.personUseLabel |> text ] ] diff --git a/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm b/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm index ac1b35f3..6d51b2e0 100644 --- a/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm +++ b/modules/webapp/src/main/elm/Comp/PowerSearchInput.elm @@ -2,6 +2,7 @@ module Comp.PowerSearchInput exposing ( Action(..) , Model , Msg + , ViewSettings , init , update , viewInput @@ -133,12 +134,18 @@ throttleUpdate model = --- View -viewInput : List (Attribute Msg) -> Model -> Html Msg -viewInput attrs model = +type alias ViewSettings = + { placeholder : String + , extraAttrs : List (Attribute Msg) + } + + +viewInput : ViewSettings -> Model -> Html Msg +viewInput cfg model = input - (attrs + (cfg.extraAttrs ++ [ type_ "text" - , placeholder "Search query …" + , placeholder cfg.placeholder , onInput SetSearch , Util.Html.onKeyUpCode KeyUpMsg , Maybe.map value model.input diff --git a/modules/webapp/src/main/elm/Comp/ScanMailboxForm.elm b/modules/webapp/src/main/elm/Comp/ScanMailboxForm.elm index 3e23a981..244cc827 100644 --- a/modules/webapp/src/main/elm/Comp/ScanMailboxForm.elm +++ b/modules/webapp/src/main/elm/Comp/ScanMailboxForm.elm @@ -39,6 +39,8 @@ import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onClick, onInput) import Http import Markdown +import Messages.Comp.ScanMailboxForm exposing (Texts) +import Messages.Data.Language import Set exposing (Set) import Styles as S import Util.Folder exposing (mkFolderOption) @@ -97,6 +99,30 @@ type MenuTab | TabSchedule +{-| Only exits to be able to put tabs in a Set. +-} +tabName : MenuTab -> String +tabName tab = + case tab of + TabGeneral -> + "general" + + TabProcessing -> + "processing" + + TabAdditionalFilter -> + "additional-filter" + + TabPostProcessing -> + "post-processing" + + TabMetadata -> + "metadata" + + TabSchedule -> + "schedule" + + type Msg = Submit | Cancel @@ -166,7 +192,7 @@ initWith flags s = , fileFilter = s.fileFilter , subjectFilter = s.subjectFilter , languageModel = - Comp.FixedDropdown.init (List.map mkLanguageItem Data.Language.all) + Comp.FixedDropdown.init Data.Language.all , language = Maybe.andThen Data.Language.fromString s.language , postHandleAll = Maybe.withDefault False s.postHandleAll , summary = s.summary @@ -191,15 +217,11 @@ init flags = Comp.CalEventInput.initDefault in ( { settings = Api.Model.ScanMailboxSettings.empty - , connectionModel = - Comp.Dropdown.makeSingle - { makeOption = \a -> { value = a, text = a, additional = "" } - , placeholder = "Select connection..." - } + , connectionModel = Comp.Dropdown.makeSingle , enabled = False , deleteMail = False , receivedHours = Nothing - , receivedHoursModel = Comp.IntField.init (Just 1) Nothing True "Received Since Hours" + , receivedHoursModel = Comp.IntField.init (Just 1) Nothing True , foldersModel = Comp.StringListInput.init , folders = [] , targetFolder = Nothing @@ -209,11 +231,7 @@ init flags = , formMsg = Nothing , loading = 3 , yesNoDelete = Comp.YesNoDimmer.emptyModel - , folderModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } + , folderModel = Comp.Dropdown.makeSingle , allFolders = [] , itemFolderId = Nothing , tagModel = Util.Tag.makeDropdownModel @@ -221,11 +239,11 @@ init flags = , fileFilter = Nothing , subjectFilter = Nothing , languageModel = - Comp.FixedDropdown.init (List.map mkLanguageItem Data.Language.all) + Comp.FixedDropdown.init Data.Language.all , language = Nothing , postHandleAll = False , summary = Nothing - , openTabs = Set.insert (tabTitle TabGeneral) Set.empty + , openTabs = Set.singleton (tabName TabGeneral) } , Cmd.batch [ Api.getImapSettings flags "" ConnResp @@ -235,11 +253,6 @@ init flags = ) -mkLanguageItem : Language -> Comp.FixedDropdown.Item Language -mkLanguageItem lang = - Comp.FixedDropdown.Item lang (Data.Language.toName lang) - - --- Update @@ -370,9 +383,7 @@ update flags msg model = cm = Comp.Dropdown.makeSingleList - { makeOption = \a -> { value = a, text = a, additional = "" } - , placeholder = "Select Connection..." - , options = names + { options = names , selected = Util.Maybe.or [ List.head (Comp.Dropdown.getSelected model.connectionModel) @@ -522,10 +533,6 @@ update flags msg model = { model | allFolders = fs.items , loading = model.loading - 1 - , folderModel = - Comp.Dropdown.setMkOption - (mkFolderOption flags fs.items) - model.folderModel } mkIdName fitem = @@ -680,14 +687,14 @@ update flags msg model = , Cmd.none ) - ToggleAkkordionTab title -> + ToggleAkkordionTab name -> let tabs = - if Set.member title model.openTabs then - Set.remove title model.openTabs + if Set.member name model.openTabs then + Set.remove name model.openTabs else - Set.insert title model.openTabs + Set.insert name model.openTabs in ( { model | openTabs = tabs } , NoAction @@ -729,26 +736,26 @@ isFolderMember model = Util.Folder.isFolderMember model.allFolders selected -view2 : String -> UiSettings -> Model -> Html Msg -view2 extraClasses settings model = +view2 : Texts -> Flags -> String -> UiSettings -> Model -> Html Msg +view2 texts flags extraClasses settings model = let dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this scan mailbox task?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteTask texts.basics.yes texts.basics.no startOnceBtn = MB.SecondaryButton { tagger = StartOnce - , label = "Start Once" - , title = "Start this task now" + , label = texts.startOnce + , title = texts.startNow , icon = Just "fa fa-play" } tabActive t = - if Set.member t.title model.openTabs then - ( Comp.Tabs.Open, ToggleAkkordionTab t.title ) + if Set.member t.name model.openTabs then + ( Comp.Tabs.Open, ToggleAkkordionTab t.name ) else - ( Comp.Tabs.Closed, ToggleAkkordionTab t.title ) + ( Comp.Tabs.Closed, ToggleAkkordionTab t.name ) in div [ class extraClasses @@ -758,14 +765,14 @@ view2 extraClasses settings model = { start = [ MB.PrimaryButton { tagger = Submit - , label = "Submit" - , title = "Save" + , label = texts.basics.submit + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" } , MB.SecondaryButton { tagger = Cancel - , label = "Cancel" - , title = "Back to list" + , label = texts.basics.cancel + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" } ] @@ -774,8 +781,8 @@ view2 extraClasses settings model = [ startOnceBtn , MB.DeleteButton { tagger = RequestDelete - , label = "Delete" - , title = "Delete this task" + , label = texts.basics.delete + , title = texts.deleteThisTask , icon = Just "fa fa-trash" } ] @@ -799,91 +806,86 @@ view2 extraClasses settings model = , Comp.Tabs.akkordion Comp.Tabs.defaultStyle tabActive - (formTabs settings model) + (formTabs texts flags settings model) , Html.map YesNoDeleteMsg (Comp.YesNoDimmer.viewN True dimmerSettings model.yesNoDelete ) - , B.loadingDimmer (model.loading > 0) + , B.loadingDimmer + { active = model.loading > 0 + , label = texts.basics.loading + } ] -tabTitle : MenuTab -> String -tabTitle tab = - case tab of - TabGeneral -> - "General" - - TabProcessing -> - "Processing" - - TabAdditionalFilter -> - "Additional Filter" - - TabPostProcessing -> - "Post Processing" - - TabMetadata -> - "Metadata" - - TabSchedule -> - "Schedule" - - -formTabs : UiSettings -> Model -> List (Comp.Tabs.Tab Msg) -formTabs settings model = - [ { title = tabTitle TabGeneral +formTabs : Texts -> Flags -> UiSettings -> Model -> List (Comp.Tabs.Tab Msg) +formTabs texts flags settings model = + [ { name = tabName TabGeneral + , title = texts.generalTab , titleRight = [] , info = Nothing - , body = viewGeneral2 settings model + , body = viewGeneral2 texts settings model } - , { title = tabTitle TabProcessing + , { name = tabName TabProcessing + , title = texts.processingTab , titleRight = [] - , info = Just "These settings define which mails are fetched from the mail server." - , body = viewProcessing2 model + , info = Just texts.processingTabInfo + , body = viewProcessing2 texts model } - , { title = tabTitle TabAdditionalFilter + , { name = tabName TabAdditionalFilter + , title = texts.additionalFilterTab , titleRight = [] - , info = Just "These filters are applied to mails that have been fetched from the mailbox to select those that should be imported." - , body = viewAdditionalFilter2 model + , info = Just texts.additionalFilterTabInfo + , body = viewAdditionalFilter2 texts model } - , { title = tabTitle TabPostProcessing + , { name = tabName TabPostProcessing + , title = texts.postProcessingTab , titleRight = [] - , info = Just "This defines what happens to mails that have been downloaded." - , body = viewPostProcessing2 model + , info = Just texts.postProcessingTabInfo + , body = viewPostProcessing2 texts model } - , { title = tabTitle TabMetadata + , { name = tabName TabMetadata + , title = texts.metadataTab , titleRight = [] - , info = Just "Define metadata that should be attached to all items created by this task." - , body = viewMetadata2 settings model + , info = Just texts.metadataTabInfo + , body = viewMetadata2 texts flags settings model } - , { title = tabTitle TabSchedule + , { name = tabName TabSchedule + , title = texts.scheduleTab , titleRight = [] - , info = Just "Define when mails should be imported." - , body = viewSchedule2 model + , info = Just texts.scheduleTabInfo + , body = viewSchedule2 texts model } ] -viewGeneral2 : UiSettings -> Model -> List (Html Msg) -viewGeneral2 settings model = +viewGeneral2 : Texts -> UiSettings -> Model -> List (Html Msg) +viewGeneral2 texts settings model = + let + connectionCfg = + { makeOption = \a -> { text = a, additional = "" } + , placeholder = texts.selectConnection + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in [ MB.viewItem <| MB.Checkbox { id = "scanmail-enabled" , value = model.enabled , tagger = \_ -> ToggleEnabled - , label = "Enable or disable this task." + , label = texts.enableDisable } , div [ class "mb-4 mt-4" ] [ label [ class S.inputLabel ] - [ text "Mailbox" + [ text texts.mailbox , B.inputRequired ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Summary" + [ text texts.summary ] , input [ type_ "text" @@ -894,27 +896,27 @@ viewGeneral2 settings model = ] [] , span [ class "opacity-50 text-sm" ] - [ text "Some human readable name, only for displaying" + [ text texts.summaryInfo ] ] , Html.map ConnMsg (Comp.Dropdown.view2 - DS.mainStyle + connectionCfg settings model.connectionModel ) , span [ class "opacity-50 text-sm" ] - [ text "The IMAP connection to use when sending notification mails." + [ text texts.connectionInfo ] ] ] -viewProcessing2 : Model -> List (Html Msg) -viewProcessing2 model = +viewProcessing2 : Texts -> Model -> List (Html Msg) +viewProcessing2 texts model = [ div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Folders" + [ text texts.folders , B.inputRequired ] , Html.map FoldersMsg @@ -923,32 +925,34 @@ viewProcessing2 model = model.foldersModel ) , span [ class "opacity-50 text-sm mt-1" ] - [ text "The folders to look for mails." + [ text texts.foldersInfo ] ] , Html.map ReceivedHoursMsg - (Comp.IntField.viewWithInfo2 - "Select mails newer than `now - receivedHours`" - model.receivedHours - "mb-4" + (Comp.IntField.view + { label = texts.receivedHoursLabel + , info = texts.receivedHoursInfo + , number = model.receivedHours + , classes = "mb-4" + } model.receivedHoursModel ) ] -viewAdditionalFilter2 : Model -> List (Html Msg) -viewAdditionalFilter2 model = +viewAdditionalFilter2 : Texts -> Model -> List (Html Msg) +viewAdditionalFilter2 texts model = [ div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "File Filter" ] + [ text texts.fileFilter ] , input [ type_ "text" , onInput SetFileFilter - , placeholder "File Filter" + , placeholder texts.fileFilter , model.fileFilter |> Maybe.withDefault "" |> value @@ -956,34 +960,18 @@ viewAdditionalFilter2 model = ] [] , div [ class "opacity-50 text-sm" ] - [ text "Specify a file glob to filter attachments. For example, to only extract pdf files: " - , code [ class "font-mono" ] - [ text "*.pdf" - ] - , text ". If you want to include the mail body, allow html files or " - , code [ class "font-mono" ] - [ text "mail.html" - ] - , text ". Globs can be combined via OR, like this: " - , code [ class "font-mono" ] - [ text "*.pdf|mail.html" - ] - , text ". No file filter defaults to " - , code [ class "font-mono" ] - [ text "*" - ] - , text " that includes all" + [ Markdown.toHtml [] texts.fileFilterInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Subject Filter" ] + [ text texts.subjectFilter ] , input [ type_ "text" , onInput SetSubjectFilter - , placeholder "Subject Filter" + , placeholder texts.subjectFilter , model.subjectFilter |> Maybe.withDefault "" |> value @@ -991,40 +979,29 @@ viewAdditionalFilter2 model = ] [] , div [ class "opacity-50 text-sm" ] - [ text "Specify a file glob to filter mails by subject. For example: " - , code [ class "font-mono" ] - [ text "*Scanned Document*" - ] - , text ". No file filter defaults to " - , code [ class "font-mono" ] - [ text "*" - ] - , text " that includes all" + [ Markdown.toHtml [] texts.subjectFilterInfo ] ] ] -viewPostProcessing2 : Model -> List (Html Msg) -viewPostProcessing2 model = +viewPostProcessing2 : Texts -> Model -> List (Html Msg) +viewPostProcessing2 texts model = [ div [ class "mb-4" ] [ MB.viewItem <| MB.Checkbox { id = "scanmail-posthandle-all" , value = model.postHandleAll - , label = "Apply post-processing to all fetched mails." + , label = texts.postProcessingLabel , tagger = \_ -> TogglePostHandleAll } , span [ class "opacity-50 text-sm mt-1" ] - [ text "When mails are fetched but not imported due to the 'Additional Filters', this flag can " - , text "control whether they should be moved to a target folder or deleted (whatever is " - , text "defined here) nevertheless. If unchecked only imported mails " - , text "are post-processed, others stay where they are." + [ Markdown.toHtml [] texts.postProcessingInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Target folder" + [ text texts.targetFolder ] , input [ type_ "text" @@ -1034,31 +1011,43 @@ viewPostProcessing2 model = ] [] , span [ class "opacity-50 text-sm" ] - [ text "Move mails into this folder." + [ text texts.targetFolderInfo ] ] , div [ class "mb-4" ] [ MB.viewItem <| MB.Checkbox { id = "scanmail-delete-all" - , label = "Delete imported mails" + , label = texts.deleteMailLabel , tagger = \_ -> ToggleDeleteMail , value = model.deleteMail } , span [ class "opacity-50 text-sm" ] - [ text "Whether to delete all mails fetched by docspell. This only applies if " - , em [] [ text "target folder" ] - , text " is not set." + [ Markdown.toHtml [] texts.deleteMailInfo ] ] ] -viewMetadata2 : UiSettings -> Model -> List (Html Msg) -viewMetadata2 settings model = +viewMetadata2 : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewMetadata2 texts flags settings model = + let + folderCfg = + { makeOption = Util.Folder.mkFolderOption flags model.allFolders + , placeholder = "" + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + + languageCfg = + { display = Messages.Data.Language.gb + , icon = \_ -> Nothing + , style = DS.mainStyleWith "flex-grow mr-2" + } + in [ div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Item direction" + [ text texts.itemDirection , B.inputRequired ] , div [ class "flex flex-col " ] @@ -1070,7 +1059,7 @@ viewMetadata2 settings model = , class S.radioInput ] [] - , span [ class "ml-2" ] [ text "Automatic" ] + , span [ class "ml-2" ] [ text texts.automatic ] ] , label [ class "inline-flex items-center" ] [ input @@ -1080,7 +1069,7 @@ viewMetadata2 settings model = , onCheck (\_ -> DirectionMsg (Just Incoming)) ] [] - , span [ class "ml-2" ] [ text "Incoming" ] + , span [ class "ml-2" ] [ text texts.basics.incoming ] ] , label [ class "inline-flex items-center" ] [ input @@ -1090,27 +1079,25 @@ viewMetadata2 settings model = , class S.radioInput ] [] - , span [ class "ml-2" ] [ text "Outgoing" ] + , span [ class "ml-2" ] [ text texts.basics.outgoing ] ] , span [ class "opacity-50 text-sm" ] - [ text "Sets the direction for an item. If you know all mails are incoming or " - , text "outgoing, you can set it here. Otherwise it will be guessed from looking " - , text "at sender and receiver." + [ Markdown.toHtml [] texts.itemDirectionInfo ] ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Item Folder" + [ text texts.itemFolder ] , Html.map FolderDropdownMsg (Comp.Dropdown.view2 - DS.mainStyle + folderCfg settings model.folderModel ) , span [ class "opacity-50 text-sm" ] - [ text "Put all items from this mailbox into the selected folder" + [ text texts.itemFolderInfo ] , div [ classList @@ -1118,37 +1105,32 @@ viewMetadata2 settings model = ] , class S.message ] - [ Markdown.toHtml [] """ -You are **not a member** of this folder. Items created from mails in -this mailbox will be **hidden** from any search results. Use a folder -where you are a member of to make items visible. This message will -disappear then. - """ + [ Markdown.toHtml [] texts.folderOwnerWarning ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Tags" ] + [ text texts.basics.tags ] , Html.map TagDropdownMsg (Comp.Dropdown.view2 - DS.mainStyle + (Util.Tag.tagSettings texts.basics.chooseTag DS.mainStyle) settings model.tagModel ) , div [ class "opacity-50 text-sm" ] - [ text "Choose tags that should be applied to items." + [ text texts.tagsInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Language" + [ text texts.documentLanguage ] , div [ class "flex flex-row" ] [ Html.map LanguageMsg (Comp.FixedDropdown.viewStyled2 - (DS.mainStyleWith "flex-grow mr-2") + languageCfg False - (Maybe.map mkLanguageItem model.language) + model.language model.languageModel ) , a @@ -1161,18 +1143,17 @@ disappear then. ] ] , div [ class "opacity-50 text-sm" ] - [ text "Used for text extraction and text analysis. The " - , text "collective's default language is used, if not specified here." + [ text texts.documentLanguageInfo ] ] ] -viewSchedule2 : Model -> List (Html Msg) -viewSchedule2 model = +viewSchedule2 : Texts -> Model -> List (Html Msg) +viewSchedule2 texts model = [ div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Schedule" + [ text texts.schedule , B.inputRequired , a [ class "float-right" @@ -1182,20 +1163,19 @@ viewSchedule2 model = ] [ i [ class "fa fa-question" ] [] , span [ class "ml-2" ] - [ text "Click here for help" + [ text texts.scheduleClickForHelp ] ] ] , Html.map CalEventMsg - (Comp.CalEventInput.view2 "" + (Comp.CalEventInput.view2 + texts.calEventInput + "" (Data.Validated.value model.schedule) model.scheduleModel ) , span [ class "opacity-50 text-sm" ] - [ text "Specify how often and when this task should run. " - , text "Use English 3-letter weekdays. Either a single value, " - , text "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) " - , text "is allowed for each part." + [ Markdown.toHtml [] texts.scheduleInfo ] ] ] diff --git a/modules/webapp/src/main/elm/Comp/ScanMailboxList.elm b/modules/webapp/src/main/elm/Comp/ScanMailboxList.elm index e58b33d5..fd6d3d12 100644 --- a/modules/webapp/src/main/elm/Comp/ScanMailboxList.elm +++ b/modules/webapp/src/main/elm/Comp/ScanMailboxList.elm @@ -11,6 +11,7 @@ import Api.Model.ScanMailboxSettings exposing (ScanMailboxSettings) import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.ScanMailboxTable exposing (Texts) import Styles as S import Util.Html @@ -44,8 +45,8 @@ update msg model = --- View2 -view2 : Model -> List ScanMailboxSettings -> Html Msg -view2 _ items = +view2 : Texts -> Model -> List ScanMailboxSettings -> Html Msg +view2 texts _ items = div [] [ table [ class S.tableMain ] [ thead [] @@ -54,11 +55,11 @@ view2 _ items = , th [ class "" ] [ i [ class "fa fa-check" ] [] ] - , th [ class "text-left" ] [ text "Summary" ] + , th [ class "text-left" ] [ text texts.summary ] , th [ class "text-left mr-2" ] [ text "Schedule" ] - , th [ class "text-left mr-2 hidden md:table-cell" ] [ text "Connection" ] - , th [ class "text-left mr-2 hidden md:table-cell" ] [ text "Folders" ] - , th [ class "text-left mr-2 hidden lg:table-cell" ] [ text "Received Since" ] + , th [ class "text-left mr-2 hidden md:table-cell" ] [ text texts.connection ] + , th [ class "text-left mr-2 hidden md:table-cell" ] [ text texts.folders ] + , th [ class "text-left mr-2 hidden lg:table-cell" ] [ text texts.receivedSince ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm b/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm index c199f7fe..ef6d5e0a 100644 --- a/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm +++ b/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm @@ -17,8 +17,8 @@ import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) -import Html.Events exposing (onClick) import Http +import Messages.Comp.ScanMailboxManage exposing (Texts) import Styles as S import Util.Http @@ -213,8 +213,8 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> Flags -> UiSettings -> Model -> Html Msg +view2 texts flags settings model = div [ class "flex flex-col" ] (div [ classList @@ -229,34 +229,38 @@ view2 settings model = ] :: (case model.detailModel of Just msett -> - viewForm2 settings msett + viewForm2 texts flags settings msett Nothing -> - viewList2 model + viewList2 texts model ) ) -viewForm2 : UiSettings -> Comp.ScanMailboxForm.Model -> List (Html Msg) -viewForm2 settings model = +viewForm2 : Texts -> Flags -> UiSettings -> Comp.ScanMailboxForm.Model -> List (Html Msg) +viewForm2 texts flags settings model = [ Html.map DetailMsg - (Comp.ScanMailboxForm.view2 "" settings model) + (Comp.ScanMailboxForm.view2 texts.form flags "" settings model) ] -viewList2 : Model -> List (Html Msg) -viewList2 model = +viewList2 : Texts -> Model -> List (Html Msg) +viewList2 texts model = [ MB.view { start = [ MB.PrimaryButton { tagger = NewTask - , label = "New Task" + , label = texts.newTask , icon = Just "fa fa-plus" - , title = "Create a new scan mailbox task" + , title = texts.createNewTask } ] , end = [] , rootClasses = "mb-4" } - , Html.map ListMsg (Comp.ScanMailboxList.view2 model.listModel model.items) + , Html.map ListMsg + (Comp.ScanMailboxList.view2 texts.table + model.listModel + model.items + ) ] diff --git a/modules/webapp/src/main/elm/Comp/SearchMenu.elm b/modules/webapp/src/main/elm/Comp/SearchMenu.elm index 0c7261a2..b0355286 100644 --- a/modules/webapp/src/main/elm/Comp/SearchMenu.elm +++ b/modules/webapp/src/main/elm/Comp/SearchMenu.elm @@ -44,6 +44,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Http +import Messages.Comp.SearchMenu exposing (Texts) import Set exposing (Set) import Styles as S import Util.Html exposing (KeyCode(..)) @@ -95,36 +96,13 @@ init flags = , tagSelection = Comp.TagSelect.emptySelection , directionModel = Comp.Dropdown.makeSingleList - { makeOption = - \entry -> - { value = Data.Direction.toString entry - , text = Data.Direction.toString entry - , additional = "" - } - , options = Data.Direction.all - , placeholder = "Choose a direction…" + { options = Data.Direction.all , selected = Nothing } - , orgModel = - Comp.Dropdown.orgDropdown - , corrPersonModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "Choose a person" - } - , concPersonModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "Choose a person" - } - , concEquipmentModel = - Comp.Dropdown.makeModel - { multiple = False - , searchable = \n -> n > 0 - , makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , labelColor = \_ -> \_ -> "" - , placeholder = "Choose an equipment" - } + , orgModel = Comp.Dropdown.makeSingle + , corrPersonModel = Comp.Dropdown.makeSingle + , concPersonModel = Comp.Dropdown.makeSingle + , concEquipmentModel = Comp.Dropdown.makeSingle , folderList = Comp.FolderSelect.init Nothing [] , selectedFolder = Nothing , inboxCheckbox = False @@ -925,8 +903,7 @@ updateDrop ddm flags settings msg model = ToggleOpenAllAkkordionTabs -> let allNames = - searchTabs (DD.DragDropData ddm Nothing) flags settings model - |> List.map .title + List.map tabName allTabs |> Set.fromList next = @@ -947,8 +924,8 @@ updateDrop ddm flags settings msg model = --- View2 -viewDrop2 : DD.DragDropData -> Flags -> UiSettings -> Model -> Html Msg -viewDrop2 ddd flags settings model = +viewDrop2 : Texts -> DD.DragDropData -> Flags -> UiSettings -> Model -> Html Msg +viewDrop2 texts ddd flags settings model = let akkordionStyle = Comp.Tabs.searchMenuStyle @@ -956,7 +933,114 @@ viewDrop2 ddd flags settings model = Comp.Tabs.akkordion akkordionStyle (searchTabState settings model) - (searchTabs ddd flags settings model) + (searchTabs texts ddd flags settings model) + + +type SearchTab + = TabInbox + | TabTags + | TabTagCategories + | TabFolder + | TabCorrespondent + | TabConcerning + | TabCustomFields + | TabDate + | TabDueDate + | TabSource + | TabDirection + + +allTabs : List SearchTab +allTabs = + [ TabInbox + , TabTags + , TabTagCategories + , TabFolder + , TabCorrespondent + , TabConcerning + , TabCustomFields + , TabDate + , TabDueDate + , TabSource + , TabDirection + ] + + +tabName : SearchTab -> String +tabName tab = + case tab of + TabInbox -> + "inbox" + + TabTags -> + "tags" + + TabTagCategories -> + "categories" + + TabFolder -> + "folder" + + TabCorrespondent -> + "correspondent" + + TabConcerning -> + "concerning" + + TabCustomFields -> + "custom-fields" + + TabDate -> + "date" + + TabDueDate -> + "due-date" + + TabSource -> + "source" + + TabDirection -> + "direction" + + +findTab : Comp.Tabs.Tab msg -> Maybe SearchTab +findTab tab = + case tab.name of + "inbox" -> + Just TabInbox + + "tags" -> + Just TabTags + + "categories" -> + Just TabTagCategories + + "folder" -> + Just TabFolder + + "correspondent" -> + Just TabCorrespondent + + "concerning" -> + Just TabConcerning + + "custom-fields" -> + Just TabCustomFields + + "date" -> + Just TabDate + + "due-date" -> + Just TabDueDate + + "source" -> + Just TabSource + + "direction" -> + Just TabDirection + + _ -> + Nothing searchTabState : UiSettings -> Model -> Comp.Tabs.Tab Msg -> ( Comp.Tabs.State, Msg ) @@ -966,64 +1050,93 @@ searchTabState settings model tab = Data.UiSettings.fieldHidden settings f hidden = - case tab.title of - "Tags" -> + case findTab tab of + Just TabTags -> isHidden Data.Fields.Tag - "Tag Categories" -> + Just TabTagCategories -> isHidden Data.Fields.Tag - "Folder" -> + Just TabFolder -> isHidden Data.Fields.Folder - "Correspondent" -> + Just TabCorrespondent -> isHidden Data.Fields.CorrOrg && isHidden Data.Fields.CorrPerson - "Concerning" -> + Just TabConcerning -> isHidden Data.Fields.ConcEquip && isHidden Data.Fields.ConcPerson - "Custom Fields" -> + Just TabCustomFields -> isHidden Data.Fields.CustomFields || Comp.CustomFieldMultiInput.isEmpty model.customFieldModel - "Date" -> + Just TabDate -> isHidden Data.Fields.Date - "Due Date" -> + Just TabDueDate -> isHidden Data.Fields.DueDate - "Source" -> + Just TabSource -> isHidden Data.Fields.SourceName - "Direction" -> + Just TabDirection -> isHidden Data.Fields.Direction - _ -> + Just TabInbox -> + False + + Nothing -> False state = if hidden then Comp.Tabs.Hidden - else if Set.member tab.title model.openTabs then + else if Set.member tab.name model.openTabs then Comp.Tabs.Open else Comp.Tabs.Closed in - ( state, ToggleAkkordionTab tab.title ) + ( state, ToggleAkkordionTab tab.name ) -searchTabs : DD.DragDropData -> Flags -> UiSettings -> Model -> List (Comp.Tabs.Tab Msg) -searchTabs ddd flags settings model = +searchTabs : Texts -> DD.DragDropData -> Flags -> UiSettings -> Model -> List (Comp.Tabs.Tab Msg) +searchTabs texts ddd flags settings model = let isHidden f = Data.UiSettings.fieldHidden settings f tagSelectWM = Comp.TagSelect.makeWorkModel model.tagSelection model.tagSelectModel + + directionCfg = + { makeOption = + \entry -> + { text = Data.Direction.toString entry + , additional = "" + } + , placeholder = texts.chooseDirection + , labelColor = \_ -> \_ -> "" + , style = DS.sidebarStyle + } + + personCfg = + { makeOption = \e -> { text = e.name, additional = "" } + , placeholder = texts.choosePerson + , labelColor = \_ -> \_ -> "" + , style = DS.sidebarStyle + } + + concEquipCfg = + { makeOption = \e -> { text = e.name, additional = "" } + , labelColor = \_ -> \_ -> "" + , placeholder = texts.chooseEquipment + , style = DS.sidebarStyle + } in - [ { title = "Inbox" + [ { name = tabName TabInbox + , title = texts.inbox , info = Nothing , titleRight = [] , body = @@ -1031,7 +1144,7 @@ searchTabs ddd flags settings model = MB.Checkbox { id = "search-inbox" , value = model.inboxCheckbox - , label = "Inbox" + , label = texts.inbox , tagger = \_ -> ToggleInbox } , div [ class "mt-2 hidden" ] @@ -1039,10 +1152,10 @@ searchTabs ddd flags settings model = [ text (case model.textSearchModel of Fulltext _ -> - "Fulltext Search" + texts.fulltextSearch Names _ -> - "Search in names" + texts.searchInNames ) , a [ classList @@ -1052,7 +1165,7 @@ searchTabs ddd flags settings model = , class S.link , href "#" , onClick SwapTextSearch - , title "Switch between text search modes" + , title texts.switchSearchModes ] [ i [ class "fa fa-exchange-alt" ] [] ] @@ -1064,37 +1177,40 @@ searchTabs ddd flags settings model = , textSearchString model.textSearchModel |> Maybe.withDefault "" |> value , case model.textSearchModel of Fulltext _ -> - placeholder "Content search…" + placeholder texts.contentSearch Names _ -> - placeholder "Search in various names…" + placeholder texts.searchInNamesPlaceholder , class S.textInputSidebar ] [] , span [ class "opacity-50 text-sm" ] [ case model.textSearchModel of Fulltext _ -> - text "Fulltext search in document contents and notes." + text texts.fulltextSearchInfo Names _ -> - text "Looks in correspondents, concerned entities, item name and notes." + text texts.nameSearchInfo ] ] ] } - , { title = "Tags" + , { name = tabName TabTags + , title = texts.basics.tags , titleRight = [] , info = Nothing , body = List.map (Html.map TagSelectMsg) (Comp.TagSelect.viewTagsDrop2 + texts.tagSelect ddd.model tagSelectWM settings model.tagSelectModel ) } - , { title = "Tag Categories" + , { name = tabName TabTagCategories + , title = texts.tagCategoryTab , titleRight = [] , info = Nothing , body = @@ -1106,7 +1222,8 @@ searchTabs ddd flags settings model = ) ] } - , { title = "Folder" + , { name = tabName TabFolder + , title = texts.basics.folder , titleRight = [] , info = Nothing , body = @@ -1117,7 +1234,8 @@ searchTabs ddd flags settings model = ) ] } - , { title = "Correspondent" + , { name = tabName TabCorrespondent + , title = texts.basics.correspondent , titleRight = [] , info = Nothing , body = @@ -1126,10 +1244,10 @@ searchTabs ddd flags settings model = , classList [ ( "hidden", isHidden Data.Fields.CorrOrg ) ] ] [ label [ class S.inputLabel ] - [ text "Organization" ] + [ text texts.basics.organization ] , Html.map OrgMsg (Comp.Dropdown.view2 - DS.sidebarStyle + (Comp.Dropdown.orgFormViewSettings texts.chooseOrganization DS.sidebarStyle) settings model.orgModel ) @@ -1138,17 +1256,18 @@ searchTabs ddd flags settings model = [ class "mb-4" , classList [ ( "hidden", isHidden Data.Fields.CorrPerson ) ] ] - [ label [ class S.inputLabel ] [ text "Person" ] + [ label [ class S.inputLabel ] [ text texts.basics.person ] , Html.map CorrPersonMsg (Comp.Dropdown.view2 - DS.sidebarStyle + personCfg settings model.corrPersonModel ) ] ] } - , { title = "Concerning" + , { name = tabName TabConcerning + , title = texts.basics.concerning , titleRight = [] , info = Nothing , body = @@ -1156,10 +1275,10 @@ searchTabs ddd flags settings model = [ class "mb-4" , classList [ ( "hidden", isHidden Data.Fields.ConcPerson ) ] ] - [ label [ class S.inputLabel ] [ text "Person" ] + [ label [ class S.inputLabel ] [ text texts.basics.person ] , Html.map ConcPersonMsg (Comp.Dropdown.view2 - DS.sidebarStyle + personCfg settings model.concPersonModel ) @@ -1168,29 +1287,36 @@ searchTabs ddd flags settings model = [ class "mb-4" , classList [ ( "hidden", isHidden Data.Fields.ConcEquip ) ] ] - [ label [ class S.inputLabel ] [ text "Equipment" ] + [ label [ class S.inputLabel ] [ text texts.basics.equipment ] , Html.map ConcEquipmentMsg (Comp.Dropdown.view2 - DS.sidebarStyle + concEquipCfg settings model.concEquipmentModel ) ] ] } - , { title = "Custom Fields" + , { name = tabName TabCustomFields + , title = texts.basics.customFields , titleRight = [] , info = Nothing , body = [ Html.map CustomFieldMsg (Comp.CustomFieldMultiInput.view2 - DS.sidebarStyle - (Comp.CustomFieldMultiInput.ViewSettings False "field" (\_ -> Nothing)) + texts.customFieldMultiInput + { showAddButton = False + , classes = "" + , fieldIcon = \_ -> Nothing + , style = DS.sidebarStyle + , createCustomFieldTitle = texts.createCustomFieldTitle + } model.customFieldModel ) ] } - , { title = "Date" + , { name = tabName TabDate + , title = texts.basics.date , titleRight = [] , info = Nothing , body = @@ -1198,7 +1324,7 @@ searchTabs ddd flags settings model = [ class "flex flex-col" ] [ div [ class "mb-2" ] [ label [ class S.inputLabel ] - [ text "From" + [ text texts.from ] , div [ class "relative" ] [ Html.map FromDateMsg @@ -1215,7 +1341,7 @@ searchTabs ddd flags settings model = ] , div [ class "mb-2" ] [ label [ class S.inputLabel ] - [ text "To" + [ text texts.to ] , div [ class "relative" ] [ Html.map UntilDateMsg @@ -1229,7 +1355,8 @@ searchTabs ddd flags settings model = ] ] } - , { title = "Due Date" + , { name = tabName TabDueDate + , title = texts.dueDateTab , titleRight = [] , info = Nothing , body = @@ -1237,7 +1364,7 @@ searchTabs ddd flags settings model = [ class "flex flex-col" ] [ div [ class "mb-2" ] [ label [ class S.inputLabel ] - [ text "Due From" + [ text texts.dueFrom ] , div [ class "relative" ] [ Html.map FromDueDateMsg @@ -1254,7 +1381,7 @@ searchTabs ddd flags settings model = ] , div [ class "mb-2" ] [ label [ class S.inputLabel ] - [ text "Due To" + [ text texts.dueTo ] , div [ class "relative" ] [ Html.map UntilDueDateMsg @@ -1272,7 +1399,8 @@ searchTabs ddd flags settings model = ] ] } - , { title = "Source" + , { name = tabName TabSource + , title = texts.sourceTab , titleRight = [] , info = Nothing , body = @@ -1282,20 +1410,21 @@ searchTabs ddd flags settings model = , onInput SetSource , Util.Html.onKeyUpCode KeyUpMsg , model.sourceModel |> Maybe.withDefault "" |> value - , placeholder "Search in item source…" + , placeholder texts.searchInItemSource , class S.textInputSidebar ] [] ] ] } - , { title = "Direction" + , { name = tabName TabDirection + , title = texts.basics.direction , titleRight = [] , info = Nothing , body = [ Html.map DirectionMsg (Comp.Dropdown.view2 - DS.sidebarStyle + directionCfg settings model.directionModel ) diff --git a/modules/webapp/src/main/elm/Comp/SearchStatsView.elm b/modules/webapp/src/main/elm/Comp/SearchStatsView.elm index 6e03fd35..4e2d36a8 100644 --- a/modules/webapp/src/main/elm/Comp/SearchStatsView.elm +++ b/modules/webapp/src/main/elm/Comp/SearchStatsView.elm @@ -11,6 +11,7 @@ import Data.Icons as Icons import Data.Money import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.SearchStatsView exposing (Texts) import Styles as S @@ -28,8 +29,8 @@ sortFields fields = --- View2 -view2 : String -> SearchStats -> Html msg -view2 classes stats = +view2 : Texts -> String -> SearchStats -> Html msg +view2 texts classes stats = let isNumField f = f.sum > 0 @@ -75,7 +76,7 @@ view2 classes stats = { rootClass = "" , valueClass = "text-4xl" , value = String.fromInt stats.count - , label = "Items" + , label = texts.items } ] , div [ class "flex-grow" ] @@ -87,15 +88,15 @@ view2 classes stats = [ tr [ class "" ] [ th [ class "py-2 text-left" ] [] , th [ class "py-2 text-center" ] - [ text "Count" ] + [ text texts.count ] , th [ class "py-2 text-center" ] - [ text "Sum" ] + [ text texts.sum ] , th [ class "py-2 text-center hidden md:table-cell" ] - [ text "Avg" ] + [ text texts.avg ] , th [ class "py-2 text-center hidden md:table-cell" ] - [ text "Min" ] + [ text texts.min ] , th [ class "py-2 text-center hidden md:table-cell" ] - [ text "Max" ] + [ text texts.max ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/SentMails.elm b/modules/webapp/src/main/elm/Comp/SentMails.elm index df28d3c3..612223f6 100644 --- a/modules/webapp/src/main/elm/Comp/SentMails.elm +++ b/modules/webapp/src/main/elm/Comp/SentMails.elm @@ -13,6 +13,7 @@ import Comp.Basic as B import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Comp.SentMails exposing (Texts) import Styles as S import Util.Time @@ -59,15 +60,15 @@ update msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = case model.selected of Just mail -> div [ class "flex flex-col" ] [ div [ class "text-sm flex-flex-col" ] [ div [ class "flex flex-row" ] [ span [ class "font-bold" ] - [ text "From:" + [ text (texts.from ++ ":") ] , div [ class "ml-2" ] [ text mail.sender @@ -78,7 +79,7 @@ view2 model = ] , div [ class "flex flex-row" ] [ span [ class "font-bold" ] - [ text "Date:" + [ text (texts.date ++ ":") ] , div [ class "ml-2" ] [ Util.Time.formatDateTime mail.created |> text @@ -86,7 +87,7 @@ view2 model = ] , div [ class "flex flex-row" ] [ span [ class "font-bold" ] - [ text "Recipients:" + [ text (texts.recipients ++ ":") ] , div [ class "ml-2" ] [ String.join ", " mail.recipients |> text @@ -94,7 +95,7 @@ view2 model = ] , div [ class "flex flex-row" ] [ span [ class "font-bold" ] - [ text "Subject:" + [ text (texts.subject ++ ":") ] , div [ class "ml-2" ] [ text mail.subject @@ -122,10 +123,10 @@ view2 model = [ thead [] [ tr [] [ th [] [] - , th [ class "text-left" ] [ text "Recipients" ] - , th [ class "hidden" ] [ text "Subject" ] - , th [ class "hidden text-center xl:table-cell" ] [ text "Sent" ] - , th [ class "hidden" ] [ text "Sender" ] + , th [ class "text-left" ] [ text texts.recipients ] + , th [ class "hidden" ] [ text texts.subject ] + , th [ class "hidden text-center xl:table-cell" ] [ text texts.sent ] + , th [ class "hidden" ] [ text texts.sender ] ] ] , tbody [] <| diff --git a/modules/webapp/src/main/elm/Comp/SourceForm.elm b/modules/webapp/src/main/elm/Comp/SourceForm.elm index bca6a32e..8f402588 100644 --- a/modules/webapp/src/main/elm/Comp/SourceForm.elm +++ b/modules/webapp/src/main/elm/Comp/SourceForm.elm @@ -28,6 +28,7 @@ import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onInput) import Http import Markdown +import Messages.Comp.SourceForm exposing (Texts) import Styles as S import Util.Folder exposing (mkFolderOption) import Util.Maybe @@ -58,30 +59,17 @@ emptyModel = , abbrev = "" , description = Nothing , priorityModel = - Comp.FixedDropdown.initMap - Data.Priority.toName - Data.Priority.all + Comp.FixedDropdown.init Data.Priority.all , priority = Data.Priority.Low , enabled = False - , folderModel = - Comp.Dropdown.makeSingle - { makeOption = \e -> { value = e.id, text = e.name, additional = "" } - , placeholder = "" - } + , folderModel = Comp.Dropdown.makeSingle , allFolders = [] , folderId = Nothing - , tagModel = Util.Tag.makeDropdownModel2 + , tagModel = Util.Tag.makeDropdownModel , fileFilter = Nothing , languageModel = Comp.Dropdown.makeSingleList - { makeOption = - \a -> - { value = Data.Language.toName a - , text = Data.Language.toName a - , additional = "" - } - , placeholder = "Select…" - , options = Data.Language.all + { options = Data.Language.all , selected = Nothing } , language = Nothing @@ -236,13 +224,7 @@ update flags msg model = GetFolderResp (Ok fs) -> let model_ = - { model - | allFolders = fs.items - , folderModel = - Comp.Dropdown.setMkOption - (mkFolderOption flags fs.items) - model.folderModel - } + { model | allFolders = fs.items } mkIdName fitem = IdName fitem.id fitem.name @@ -329,13 +311,35 @@ update flags msg model = --- View2 -view2 : Flags -> UiSettings -> Model -> Html Msg -view2 _ settings model = +view2 : Flags -> Texts -> UiSettings -> Model -> Html Msg +view2 flags texts settings model = let - priorityItem = - Comp.FixedDropdown.Item - model.priority - (Data.Priority.toName model.priority) + folderCfg = + { makeOption = mkFolderOption flags model.allFolders + , placeholder = "" + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + + tagCfg = + Util.Tag.tagSettings texts.basics.chooseTag DS.mainStyle + + languageCfg = + { makeOption = + \a -> + { text = texts.languageLabel a + , additional = "" + } + , placeholder = texts.selectPlaceholder + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + + priorityCfg = + { display = Data.Priority.toName + , icon = \_ -> Nothing + , style = DS.mainStyle + } in div [ class "flex flex-col" ] [ div [ class "mb-4" ] @@ -343,14 +347,14 @@ view2 _ settings model = [ for "source-abbrev" , class S.inputLabel ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , id "source-abbrev" , onInput SetAbbrev - , placeholder "Name" + , placeholder texts.basics.name , value model.abbrev , class S.textInput , classList [ ( S.inputErrorBorder, not (isValid model) ) ] @@ -362,7 +366,7 @@ view2 _ settings model = [ for "source-descr" , class S.inputLabel ] - [ text "Description" + [ text texts.description ] , textarea [ onInput SetDescr @@ -387,49 +391,49 @@ view2 _ settings model = ] [] , span [ class "ml-2" ] - [ text "Enabled" + [ text texts.enabled ] ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Priority" + [ text texts.priority ] , Html.map PrioDropdownMsg - (Comp.FixedDropdown.view2 - (Just priorityItem) + (Comp.FixedDropdown.viewStyled2 + priorityCfg + False + (Just model.priority) model.priorityModel ) , div [ class "opacity-50 text-sm" ] - [ text "The priority used by the scheduler when processing uploaded files." + [ text texts.priorityInfo ] ] , div [ class S.header2 , class "mt-6" ] - [ text "Metadata" + [ text texts.metadata ] , div [ class S.message , class "mb-4" ] - [ text "Metadata specified here is automatically attached to each item uploaded " - , text "through this source, unless it is overriden in the upload request meta data. " - , text "Tags from the request are added to those defined here." + [ text texts.metadataInfoText ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Folder" + [ text texts.basics.folder ] , Html.map FolderDropdownMsg (Comp.Dropdown.view2 - DS.mainStyle + folderCfg settings model.folderModel ) , div [ class "opacity-50 text-sm" ] - [ text "Choose a folder to automatically put items into." + [ text texts.folderInfo ] , div [ classList @@ -437,36 +441,32 @@ view2 _ settings model = ] , class S.message ] - [ Markdown.toHtml [] """ -You are **not a member** of this folder. Items created through this -link will be **hidden** from any search results. Use a folder where -you are a member of to make items visible. This message will -disappear then. - """ + [ Markdown.toHtml [] texts.folderForbiddenText ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Tags" ] + [ text texts.basics.tags + ] , Html.map TagDropdownMsg (Comp.Dropdown.view2 - DS.mainStyle + tagCfg settings model.tagModel ) , div [ class "opacity-50 text-sm" ] - [ text "Choose tags that should be applied to items." + [ text texts.tagsInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "File Filter" ] + [ text texts.fileFilter ] , input [ type_ "text" , onInput SetFileFilter - , placeholder "File Filter" + , placeholder texts.fileFilter , model.fileFilter |> Maybe.withDefault "" |> value @@ -474,30 +474,21 @@ disappear then. ] [] , div [ class "opacity-50 text-sm" ] - [ text "Specify a file glob to filter files when uploading archives " - , text "(e.g. for email and zip). For example, to only extract pdf files: " - , code [ class "font-mono" ] - [ text "*.pdf" - ] - , text ". Globs can be combined via OR, like this: " - , code [ class "font-mono" ] - [ text "*.pdf|mail.html" - ] + [ Markdown.toHtml [] texts.fileFilterInfo ] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Language:" + [ text (texts.language ++ ":") ] , Html.map LanguageMsg (Comp.Dropdown.view2 - DS.mainStyle + languageCfg settings model.languageModel ) - , div [ class "text-gray-400 text-xs" ] - [ text "Used for text extraction and analysis. The collective's " - , text "default language is used if not specified here." + , div [ class "opacity-50 text-sm" ] + [ text texts.languageInfo ] ] ] diff --git a/modules/webapp/src/main/elm/Comp/SourceManage.elm b/modules/webapp/src/main/elm/Comp/SourceManage.elm index 0d8b2954..abd4ed82 100644 --- a/modules/webapp/src/main/elm/Comp/SourceManage.elm +++ b/modules/webapp/src/main/elm/Comp/SourceManage.elm @@ -21,6 +21,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onSubmit) import Http +import Messages.Comp.SourceManage exposing (Texts) import Ports import QRCode import Styles as S @@ -211,49 +212,52 @@ update flags msg model = --- View2 -qrCodeView : String -> Html msg -qrCodeView message = +qrCodeView : Texts -> String -> Html msg +qrCodeView texts message = QRCode.encode message |> Result.map QRCode.toSvg |> Result.withDefault - (Html.text "Error generating QR-Code") + (Html.text texts.errorGeneratingQR) -view2 : Flags -> UiSettings -> Model -> Html Msg -view2 flags settings model = +view2 : Texts -> Flags -> UiSettings -> Model -> Html Msg +view2 texts flags settings model = case model.viewMode of None -> - viewTable2 model + viewTable2 texts model Edit _ -> - div [] (viewForm2 flags settings model) + div [] (viewForm2 texts flags settings model) Display source -> - viewLinks2 flags settings source + viewLinks2 texts flags settings source -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "relative flex flex-col" ] [ MB.view { start = [] , end = [ MB.PrimaryButton { tagger = InitNewSource - , title = "Add a source url" + , title = texts.addSourceUrl , icon = Just "fa fa-plus" - , label = "New source" + , label = texts.newSource } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.SourceTable.view2 model.sources) - , B.loadingDimmer model.loading + , Html.map TableMsg (Comp.SourceTable.view2 texts.sourceTable model.sources) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] -viewLinks2 : Flags -> UiSettings -> SourceAndTags -> Html Msg -viewLinks2 flags _ source = +viewLinks2 : Texts -> Flags -> UiSettings -> SourceAndTags -> Html Msg +viewLinks2 texts flags _ source = let appUrl = flags.config.baseUrl ++ "/app/upload/" ++ source.source.id @@ -270,7 +274,7 @@ viewLinks2 flags _ source = div [] [ h2 [ class S.header2 ] - [ text "Public Uploads: " + [ text (texts.publicUploads ++ ": ") , text source.source.abbrev , div [ class "opacity-50 text-sm" ] [ text source.source.id @@ -279,37 +283,33 @@ viewLinks2 flags _ source = , MB.view { start = [ MB.SecondaryButton - { label = "Back" + { label = texts.basics.back , icon = Just "fa fa-arrow-left" , tagger = SetTableView - , title = "Back to list" + , title = texts.basics.backToList } ] , end = [] , rootClasses = "mb-4" } , p [ class "text-lg pt-2 opacity-75" ] - [ text "This source defines URLs that can be used by anyone to send files to " - , text "you. There is a web page that you can share or the API url can be used " - , text "with other clients." + [ text texts.sourceInfoText ] , p [ class "text-lg py-2 opacity-75" ] - [ text "There have been " - , String.fromInt source.source.counter |> text - , text " items created through this source." + [ text (texts.itemsCreatedInfo source.source.counter) ] , h3 [ class S.header3 , class "mt-2" ] - [ text "Public Upload Page" + [ text texts.publicUploadPage ] , div [ class "" ] [ div [ class "flex flex-row" ] [ a [ class S.secondaryBasicButtonPlain , class "rounded-l border text-sm px-4 py-2" - , title "Copy to clipboard" + , title texts.copyToClipboard , href "#" , Tuple.second appClipboardData |> String.dropLeft 1 @@ -323,7 +323,7 @@ viewLinks2 flags _ source = , class "px-4 py-2 border-0 border-t border-b border-r text-sm" , href appUrl , target "_blank" - , title "Open in new tab/window" + , title texts.openInNewTab ] [ i [ class "fa fa-external-link-alt" ] [] ] @@ -340,21 +340,21 @@ viewLinks2 flags _ source = [ class S.border , class styleQr ] - [ qrCodeView appUrl + [ qrCodeView texts appUrl ] ] , h3 [ class S.header3 , class "mt-4" ] - [ text "Public API Upload URL" + [ text texts.publicUploadUrl ] , div [ class "" ] [ div [ class "flex flex-row" ] [ a [ class S.secondaryBasicButtonPlain , class "px-4 py-2 rounded-l border text-sm" - , title "Copy to clipboard" + , title texts.copyToClipboard , href "#" , Tuple.second apiClipboardData |> String.dropLeft 1 @@ -376,24 +376,26 @@ viewLinks2 flags _ source = [ class S.border , class styleQr ] - [ qrCodeView apiUrl + [ qrCodeView texts apiUrl ] ] ] -viewForm2 : Flags -> UiSettings -> Model -> List (Html Msg) -viewForm2 flags settings model = +viewForm2 : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewForm2 texts flags settings model = let newSource = model.formModel.source.source.id == "" dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this source?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteSource + texts.basics.yes + texts.basics.no in [ if newSource then h3 [ class S.header2 ] - [ text "Create new source" + [ text texts.createNewSource ] else @@ -412,24 +414,24 @@ viewForm2 flags settings model = { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetTableView - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if not newSource then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this settings entry" + , title = texts.deleteThisSource , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -438,7 +440,7 @@ viewForm2 flags settings model = , rootClasses = "mb-4" } , Html.map FormMsg - (Comp.SourceForm.view2 flags settings model.formModel) + (Comp.SourceForm.view2 flags texts.sourceForm settings model.formModel) , div [ classList [ ( S.errorMessage, True ) @@ -452,6 +454,9 @@ viewForm2 flags settings model = dimmerSettings model.deleteConfirm ) - , B.loadingDimmer model.loading + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] ] diff --git a/modules/webapp/src/main/elm/Comp/SourceTable.elm b/modules/webapp/src/main/elm/Comp/SourceTable.elm index bd0a3466..7d6dd6c9 100644 --- a/modules/webapp/src/main/elm/Comp/SourceTable.elm +++ b/modules/webapp/src/main/elm/Comp/SourceTable.elm @@ -12,6 +12,7 @@ import Data.Flags exposing (Flags) import Data.Priority import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.SourceTable exposing (Texts) import Styles as S import Util.Html @@ -54,26 +55,26 @@ update _ msg = --- View2 -view2 : List SourceAndTags -> Html Msg -view2 sources = +view2 : Texts -> List SourceAndTags -> Html Msg +view2 texts sources = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "" ] [] - , th [ class "text-left" ] [ text "Abbrev" ] - , th [ class "px-2 text-center" ] [ text "Enabled" ] - , th [ class "hidden md:table-cell" ] [ text "Counter" ] - , th [ class "hidden md:table-cell" ] [ text "Priority" ] - , th [ class "hidden sm:table-cell" ] [ text "Id" ] + , th [ class "text-left" ] [ text texts.abbrev ] + , th [ class "px-2 text-center" ] [ text texts.enabled ] + , th [ class "hidden md:table-cell" ] [ text texts.counter ] + , th [ class "hidden md:table-cell" ] [ text texts.priority ] + , th [ class "hidden sm:table-cell" ] [ text texts.id ] ] ] , tbody [] - (List.map renderSourceLine2 sources) + (List.map (renderSourceLine2 texts) sources) ] -renderSourceLine2 : SourceAndTags -> Html Msg -renderSourceLine2 source = +renderSourceLine2 : Texts -> SourceAndTags -> Html Msg +renderSourceLine2 texts source = tr [ class S.tableRow ] [ td [ class S.editLinkTableCellStyle ] @@ -82,7 +83,7 @@ renderSourceLine2 source = ] [ B.editLinkLabel (Select source) , B.linkLabel - { label = "Show" + { label = texts.show , icon = "fa fa-eye" , handler = Show source , disabled = not source.source.enabled diff --git a/modules/webapp/src/main/elm/Comp/Tabs.elm b/modules/webapp/src/main/elm/Comp/Tabs.elm index be5e99f0..348d0f46 100644 --- a/modules/webapp/src/main/elm/Comp/Tabs.elm +++ b/modules/webapp/src/main/elm/Comp/Tabs.elm @@ -11,11 +11,11 @@ module Comp.Tabs exposing import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) -import Styles as S type alias Tab msg = - { title : String + { name : String + , title : String , titleRight : List (Html msg) , info : Maybe String , body : List (Html msg) @@ -79,7 +79,7 @@ akkordionTab style state toggle tab = [ class "flex flex-row" , class style.titleClasses ] - ([ a + (a [ class "flex flex-row items-center flex-grow" , href "#" , onClick toggle @@ -100,8 +100,7 @@ akkordionTab style state toggle tab = ] ] ] - ] - ++ tab.titleRight + :: tab.titleRight ) tabContent = diff --git a/modules/webapp/src/main/elm/Comp/TagForm.elm b/modules/webapp/src/main/elm/Comp/TagForm.elm index 45c202d6..c176f862 100644 --- a/modules/webapp/src/main/elm/Comp/TagForm.elm +++ b/modules/webapp/src/main/elm/Comp/TagForm.elm @@ -16,6 +16,7 @@ import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.TagForm exposing (Texts) import Styles as S import Util.Maybe @@ -37,9 +38,7 @@ emptyModel categories = let cm = Comp.Dropdown.makeSingleList - { makeOption = \s -> Comp.Dropdown.mkOption s s - , placeholder = "Select or define category..." - , options = categories + { options = categories , selected = Nothing } in @@ -120,8 +119,16 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = + let + categoryCfg = + { makeOption = \s -> Comp.Dropdown.mkOption s + , placeholder = texts.selectDefineCategory + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in div [ class "flex flex-col" ] [ div [ class "mb-4" ] @@ -129,13 +136,13 @@ view2 model = [ for "tagname" , class S.inputLabel ] - [ text "Name" + [ text texts.basics.name , B.inputRequired ] , input [ type_ "text" , onInput SetName - , placeholder "Name" + , placeholder texts.basics.name , value model.name , id "tagname" , class S.textInput @@ -151,11 +158,11 @@ view2 model = [ label [ class S.inputLabel ] - [ text "Category" + [ text texts.category ] , Html.map CatMsg (Comp.Dropdown.viewSingle2 - DS.mainStyle + categoryCfg model.catDropdown ) ] diff --git a/modules/webapp/src/main/elm/Comp/TagManage.elm b/modules/webapp/src/main/elm/Comp/TagManage.elm index 33664c83..aef1957b 100644 --- a/modules/webapp/src/main/elm/Comp/TagManage.elm +++ b/modules/webapp/src/main/elm/Comp/TagManage.elm @@ -20,6 +20,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onSubmit) import Http +import Messages.Comp.TagManage exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -213,38 +214,38 @@ update flags msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = if model.viewMode == Table then - viewTable2 model + viewTable2 texts model else - viewForm2 model + viewForm2 texts model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col" ] [ MB.view { start = [ MB.TextInput { tagger = SetQuery , value = model.query - , placeholder = "Search…" + , placeholder = texts.basics.searchPlaceholder , icon = Just "fa fa-search" } ] , end = [ MB.PrimaryButton { tagger = InitNewTag - , title = "Create a new tag" + , title = texts.createNewTag , icon = Just "fa fa-plus" - , label = "New Tag" + , label = texts.newTag } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.TagTable.view2 model.tagTableModel) + , Html.map TableMsg (Comp.TagTable.view2 texts.tagTable model.tagTableModel) , div [ classList [ ( "ui dimmer", True ) @@ -256,14 +257,16 @@ viewTable2 model = ] -viewForm2 : Model -> Html Msg -viewForm2 model = +viewForm2 : Texts -> Model -> Html Msg +viewForm2 texts model = let newTag = model.tagFormModel.tag.id == "" dimmerSettings2 = - Comp.YesNoDimmer.defaultSettings2 "Really delete this tag?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteTag + texts.basics.yes + texts.basics.no in Html.form [ class "relative flex flex-col" @@ -277,7 +280,7 @@ viewForm2 model = ) , if newTag then h1 [ class S.header2 ] - [ text "Create new tag" + [ text texts.createNewTag ] else @@ -294,22 +297,22 @@ viewForm2 model = { tagger = Submit , title = "Submit this form" , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if not newTag then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this tag" + , title = texts.deleteThisTag , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -326,6 +329,9 @@ viewForm2 model = ] [ Maybe.withDefault "" model.formError |> text ] - , Html.map FormMsg (Comp.TagForm.view2 model.tagFormModel) - , B.loadingDimmer model.loading + , Html.map FormMsg (Comp.TagForm.view2 texts.tagForm model.tagFormModel) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/TagSelect.elm b/modules/webapp/src/main/elm/Comp/TagSelect.elm index 2d89ae4a..79bd149a 100644 --- a/modules/webapp/src/main/elm/Comp/TagSelect.elm +++ b/modules/webapp/src/main/elm/Comp/TagSelect.elm @@ -26,6 +26,7 @@ import Dict exposing (Dict) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) +import Messages.Comp.TagSelect exposing (Texts) import Set import Simple.Fuzzy import String as S @@ -422,17 +423,17 @@ catState model name = --- View2 -viewAll2 : DD.Model -> UiSettings -> Selection -> Model -> List (Html Msg) -viewAll2 ddm settings sel model = +viewAll2 : Texts -> DD.Model -> UiSettings -> Selection -> Model -> List (Html Msg) +viewAll2 texts ddm settings sel model = let wm = makeWorkModel sel model in - viewTagsDrop2 ddm wm settings model ++ [ viewCats2 settings wm model ] + viewTagsDrop2 texts ddm wm settings model ++ [ viewCats2 settings wm model ] -viewTagsDrop2 : DD.Model -> WorkModel -> UiSettings -> Model -> List (Html Msg) -viewTagsDrop2 ddm wm settings model = +viewTagsDrop2 : Texts -> DD.Model -> WorkModel -> UiSettings -> Model -> List (Html Msg) +viewTagsDrop2 texts ddm wm settings model = [ div [ class "flex flex-col" ] [ div [ class "flex flex-row h-6 items-center text-xs mb-2" ] [ a @@ -442,16 +443,16 @@ viewTagsDrop2 ddm wm settings model = , onClick ToggleShowEmpty ] [ if model.showEmpty then - text " Hide empty" + text (" " ++ texts.hideEmpty) else - text " Show empty" + text (" " ++ texts.showEmpty) ] , div [ class "flex-grow" ] [] , div [ class " relative h-6" ] [ input [ type_ "text" - , placeholder "Filter …" + , placeholder texts.filterPlaceholder , onInput Search , class "bg-blue-50 w-30 h-6 px-0 py-0 text-xs" , class "border-0 border-b border-gray-200 focus:ring-0 focus:border-black" diff --git a/modules/webapp/src/main/elm/Comp/TagTable.elm b/modules/webapp/src/main/elm/Comp/TagTable.elm index 77e36451..3e0ad3ac 100644 --- a/modules/webapp/src/main/elm/Comp/TagTable.elm +++ b/modules/webapp/src/main/elm/Comp/TagTable.elm @@ -11,6 +11,7 @@ import Comp.Basic as B import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.TagTable exposing (Texts) import Styles as S @@ -50,14 +51,14 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "" ] [] - , th [ class "text-left" ] [ text "Name" ] - , th [ class "text-left" ] [ text "Category" ] + , th [ class "text-left" ] [ text texts.basics.name ] + , th [ class "text-left" ] [ text texts.category ] ] ] , tbody [] diff --git a/modules/webapp/src/main/elm/Comp/UiSettingsForm.elm b/modules/webapp/src/main/elm/Comp/UiSettingsForm.elm index c9f0a010..4162917c 100644 --- a/modules/webapp/src/main/elm/Comp/UiSettingsForm.elm +++ b/modules/webapp/src/main/elm/Comp/UiSettingsForm.elm @@ -11,11 +11,13 @@ import Api.Model.TagList exposing (TagList) import Comp.BasicSizeField import Comp.ColorTagger import Comp.FieldListSelect +import Comp.FixedDropdown import Comp.IntField import Comp.MenuBar as MB import Comp.Tabs import Data.BasicSize exposing (BasicSize) import Data.Color exposing (Color) +import Data.DropdownStyle as DS import Data.Fields exposing (Field) import Data.Flags exposing (Flags) import Data.ItemTemplate as IT exposing (ItemTemplate) @@ -26,6 +28,9 @@ import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) import Http import Markdown +import Messages +import Messages.Comp.UiSettingsForm exposing (Texts) +import Messages.UiLanguage exposing (UiLanguage) import Set exposing (Set) import Styles as S import Util.Maybe @@ -48,7 +53,6 @@ type alias Model = , searchMenuTagCatCountModel : Comp.IntField.Model , formFields : List Field , itemDetailShortcuts : Bool - , editMenuVisible : Bool , cardPreviewSize : BasicSize , cardTitlePattern : PatternModel , cardSubtitlePattern : PatternModel @@ -56,6 +60,8 @@ type alias Model = , searchStatsVisible : Bool , sideMenuVisible : Bool , powerSearchEnabled : Bool + , uiLangModel : Comp.FixedDropdown.Model UiLanguage + , uiLang : UiLanguage , openTabs : Set String } @@ -103,7 +109,6 @@ init flags settings = (Just 10) (Just flags.config.maxPageSize) False - "Page size" , tagColors = settings.tagCategoryColors , tagColorModel = Comp.ColorTagger.init @@ -116,31 +121,26 @@ init flags settings = (Just 0) (Just flags.config.maxNoteLength) False - "Max. Note Length" , searchMenuFolderCount = Just settings.searchMenuFolderCount , searchMenuFolderCountModel = Comp.IntField.init (Just 0) (Just 2000) False - "Number of folders in search menu" , searchMenuTagCount = Just settings.searchMenuTagCount , searchMenuTagCountModel = Comp.IntField.init (Just 0) (Just 2000) False - "Number of tags in search menu" , searchMenuTagCatCount = Just settings.searchMenuTagCatCount , searchMenuTagCatCountModel = Comp.IntField.init (Just 0) (Just 2000) False - "Number of categories in search menu" , formFields = settings.formFields , itemDetailShortcuts = settings.itemDetailShortcuts - , editMenuVisible = settings.editMenuVisible , cardPreviewSize = settings.cardPreviewSize , cardTitlePattern = initPatternModel settings.cardTitleTemplate , cardSubtitlePattern = initPatternModel settings.cardSubtitleTemplate @@ -148,6 +148,9 @@ init flags settings = , searchStatsVisible = settings.searchStatsVisible , sideMenuVisible = settings.sideMenuVisible , powerSearchEnabled = settings.powerSearchEnabled + , uiLang = settings.uiLang + , uiLangModel = + Comp.FixedDropdown.init Messages.UiLanguage.all , openTabs = Set.empty } , Api.getTags flags "" GetTagsResp @@ -165,7 +168,6 @@ type Msg | SearchMenuTagCatMsg Comp.IntField.Msg | FieldListMsg Comp.FieldListSelect.Msg | ToggleItemDetailShortcuts - | ToggleEditMenuVisible | CardPreviewSizeMsg Comp.BasicSizeField.Msg | SetCardTitlePattern String | SetCardSubtitlePattern String @@ -174,6 +176,7 @@ type Msg | ToggleAkkordionTab String | ToggleSideMenuVisible | TogglePowerSearch + | UiLangMsg (Comp.FixedDropdown.Msg UiLanguage) @@ -330,15 +333,6 @@ update sett msg model = , Just { sett | itemDetailShortcuts = flag } ) - ToggleEditMenuVisible -> - let - flag = - not model.editMenuVisible - in - ( { model | editMenuVisible = flag } - , Just { sett | editMenuVisible = flag } - ) - CardPreviewSizeMsg lm -> let next = @@ -414,14 +408,14 @@ update sett msg model = , Just { sett | searchStatsVisible = flag } ) - ToggleAkkordionTab title -> + ToggleAkkordionTab name -> let tabs = - if Set.member title model.openTabs then - Set.remove title model.openTabs + if Set.member name model.openTabs then + Set.remove name model.openTabs else - Set.insert title model.openTabs + Set.insert name model.openTabs in ( { model | openTabs = tabs } , Nothing @@ -445,27 +439,44 @@ update sett msg model = , Just { sett | powerSearchEnabled = next } ) + UiLangMsg lm -> + let + ( m, sel ) = + Comp.FixedDropdown.update lm model.uiLangModel + + newLang = + Maybe.withDefault model.uiLang sel + in + ( { model | uiLangModel = m, uiLang = newLang } + , if newLang == model.uiLang then + Nothing + + else + Just { sett | uiLang = newLang } + ) + --- View2 -tagColorViewOpts2 : Comp.ColorTagger.ViewOpts -tagColorViewOpts2 = +tagColorViewOpts2 : Texts -> Comp.ColorTagger.ViewOpts +tagColorViewOpts2 texts = { renderItem = - \( k, v ) -> + \( _, v ) -> span [ class (" label " ++ Data.Color.toString2 v) ] - [ text k ] - , label = "Choose color for tag categories" - , description = Just "Tags can be represented differently based on their category." + [ text (texts.colorLabel v) ] + , colorLabel = texts.colorLabel + , label = texts.chooseTagColorLabel + , description = Just texts.tagColorDescription } -view2 : Flags -> UiSettings -> Model -> Html Msg -view2 flags settings model = +view2 : Texts -> Flags -> UiSettings -> Model -> Html Msg +view2 texts flags settings model = let state tab = - if Set.member tab.title model.openTabs then + if Set.member tab.name model.openTabs then Comp.Tabs.Open else @@ -474,14 +485,22 @@ view2 flags settings model = div [ class "flex flex-col" ] [ Comp.Tabs.akkordion Comp.Tabs.defaultStyle - (\t -> ( state t, ToggleAkkordionTab t.title )) - (settingFormTabs flags settings model) + (\t -> ( state t, ToggleAkkordionTab t.name )) + (settingFormTabs texts flags settings model) ] -settingFormTabs : Flags -> UiSettings -> Model -> List (Comp.Tabs.Tab Msg) -settingFormTabs flags _ model = - [ { title = "General" +settingFormTabs : Texts -> Flags -> UiSettings -> Model -> List (Comp.Tabs.Tab Msg) +settingFormTabs texts flags _ model = + let + langCfg = + { display = \lang -> Messages.get lang |> .label + , icon = \lang -> Just (Messages.get lang |> .flagIcon) + , style = DS.mainStyle + } + in + [ { name = "general" + , title = texts.general , titleRight = [] , info = Nothing , body = @@ -489,25 +508,35 @@ settingFormTabs flags _ model = [ MB.viewItem <| MB.Checkbox { id = "uisetting-sidemenu-visible" - , label = "Show side menu by default" + , label = texts.showSideMenuByDefault , tagger = \_ -> ToggleSideMenuVisible , value = model.sideMenuVisible } ] + , div [ class "mb-4" ] + [ label [ class S.inputLabel ] [ text texts.uiLanguage ] + , Html.map UiLangMsg + (Comp.FixedDropdown.viewStyled2 + langCfg + False + (Just model.uiLang) + model.uiLangModel + ) + ] ] } - , { title = "Item Search" + , { name = "item-search" + , title = texts.itemSearch , titleRight = [] , info = Nothing , body = [ Html.map SearchPageSizeMsg - (Comp.IntField.viewWithInfo2 - ("Maximum results in one page when searching items. At most " - ++ String.fromInt flags.config.maxPageSize - ++ "." - ) - model.itemSearchPageSize - "mb-4" + (Comp.IntField.view + { label = texts.maxResultsPerPage + , info = texts.maxResultsPerPageInfo flags.config.maxPageSize + , number = model.itemSearchPageSize + , classes = "mb-4" + } model.searchPageSizeModel ) , div [ class "mb-4" ] @@ -516,7 +545,7 @@ settingFormTabs flags _ model = { id = "uisetting-searchstats-visible" , value = model.searchStatsVisible , tagger = \_ -> ToggleSearchStatsVisible - , label = "Show basic search statistics by default" + , label = texts.showBasicSearchStatsByDefault } ] , div [ class "mb-4" ] @@ -525,38 +554,38 @@ settingFormTabs flags _ model = { id = "uisetting-powersearch-enabled" , value = model.powerSearchEnabled , tagger = \_ -> TogglePowerSearch - , label = "Enable power-user search bar" + , label = texts.enablePowerSearch } ] ] } - , { title = "Item Cards" + , { name = "item-cards" + , title = texts.itemCards , titleRight = [] , info = Nothing , body = [ Html.map NoteLengthMsg - (Comp.IntField.viewWithInfo2 - ("Maximum size of the item notes to display in card view. Between 0 - " - ++ String.fromInt flags.config.maxNoteLength - ++ "." - ) - model.itemSearchNoteLength - "mb-4" + (Comp.IntField.view + { label = texts.maxNoteSize + , info = texts.maxNoteSizeInfo flags.config.maxNoteLength + , number = model.itemSearchNoteLength + , classes = "mb-4" + } model.searchNoteLengthModel ) , Html.map CardPreviewSizeMsg (Comp.BasicSizeField.view2 "mb-4" - "Size of item preview" + texts.sizeOfItemPreview model.cardPreviewSize ) , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Card Title Pattern" + [ text texts.cardTitlePattern , a [ class "float-right" , class S.link - , title "Toggle pattern help text" + , title texts.togglePatternHelpText , href "#" , onClick TogglePatternHelpMsg ] @@ -573,11 +602,11 @@ settingFormTabs flags _ model = ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Card Subtitle Pattern" + [ text texts.cardSubtitlePattern , a [ class "float-right" , class S.link - , title "Toggle pattern help text" + , title texts.togglePatternHelpText , href "#" , onClick TogglePatternHelpMsg ] @@ -598,37 +627,45 @@ settingFormTabs flags _ model = , ( "hidden", not model.showPatternHelp ) ] ] - IT.helpMessage + texts.templateHelpMessage ] } - , { title = "Search Menu" + , { name = "search-menu" + , title = texts.searchMenu , titleRight = [] , info = Nothing , body = [ Html.map SearchMenuTagMsg - (Comp.IntField.viewWithInfo2 - "How many tags to display in search menu at once. Others can be expanded. Use 0 to always show all." - model.searchMenuTagCount - "mb-4" + (Comp.IntField.view + { label = texts.searchMenuTagCount + , info = texts.searchMenuTagCountInfo + , number = model.searchMenuTagCount + , classes = "mb-4" + } model.searchMenuTagCountModel ) , Html.map SearchMenuTagCatMsg - (Comp.IntField.viewWithInfo2 - "How many categories to display in search menu at once. Others can be expanded. Use 0 to always show all." - model.searchMenuTagCatCount - "mb-4" + (Comp.IntField.view + { label = texts.searchMenuCatCount + , info = texts.searchMenuCatCountInfo + , number = model.searchMenuTagCatCount + , classes = "mb-4" + } model.searchMenuTagCatCountModel ) , Html.map SearchMenuFolderMsg - (Comp.IntField.viewWithInfo2 - "How many folders to display in search menu at once. Other folders can be expanded. Use 0 to always show all." - model.searchMenuFolderCount - "mb-4" + (Comp.IntField.view + { label = texts.searchMenuFolderCount + , info = texts.searchMenuFolderCountInfo + , number = model.searchMenuFolderCount + , classes = "mb-4" + } model.searchMenuFolderCountModel ) ] } - , { title = "Item Detail" + , { name = "item-detail" + , title = texts.itemDetail , titleRight = [] , info = Nothing , body = @@ -636,7 +673,7 @@ settingFormTabs flags _ model = [ MB.viewItem <| MB.Checkbox { tagger = \_ -> TogglePdfPreview - , label = "Browser-native PDF preview" + , label = texts.browserNativePdfView , value = model.nativePdfPreview , id = "uisetting-pdfpreview-toggle" } @@ -645,44 +682,39 @@ settingFormTabs flags _ model = [ MB.viewItem <| MB.Checkbox { tagger = \_ -> ToggleItemDetailShortcuts - , label = "Use keyboard shortcuts for navigation and confirm/unconfirm with open edit menu." + , label = texts.keyboardShortcutLabel , value = model.itemDetailShortcuts , id = "uisetting-itemdetailshortcuts-toggle" } ] - , div [ class "mb-4 hidden" ] - [ MB.viewItem <| - MB.Checkbox - { id = "uisetting-editmenu-visible" - , value = model.editMenuVisible - , tagger = \_ -> ToggleEditMenuVisible - , label = "Show edit side menu by default" - } - ] ] } - , { title = "Tag Category Colors" + , { name = "tag-category-colors" + , title = texts.tagCategoryColors , titleRight = [] , info = Nothing , body = [ Html.map TagColorMsg (Comp.ColorTagger.view2 model.tagColors - tagColorViewOpts2 + (tagColorViewOpts2 texts) model.tagColorModel ) ] } - , { title = "Fields" + , { name = "fields" + , title = texts.fields , titleRight = [] , info = Nothing , body = [ span [ class "opacity-50 text-sm" ] - [ text "Choose which fields to display in search and edit menus." + [ text texts.fieldsInfo ] , Html.map FieldListMsg (Comp.FieldListSelect.view2 - "px-2" + { classes = "px-2" + , fieldLabel = texts.fieldLabel + } model.formFields ) ] diff --git a/modules/webapp/src/main/elm/Comp/UiSettingsManage.elm b/modules/webapp/src/main/elm/Comp/UiSettingsManage.elm index 7cd87d50..c1e60230 100644 --- a/modules/webapp/src/main/elm/Comp/UiSettingsManage.elm +++ b/modules/webapp/src/main/elm/Comp/UiSettingsManage.elm @@ -14,6 +14,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Comp.UiSettingsManage exposing (Texts) import Ports import Styles as S @@ -125,15 +126,15 @@ isSuccess model = Maybe.map .success model.message == Just True -view2 : Flags -> UiSettings -> String -> Model -> Html Msg -view2 flags settings classes model = +view2 : Texts -> Flags -> UiSettings -> String -> Model -> Html Msg +view2 texts flags settings classes model = div [ class classes ] [ MB.view { start = [ MB.PrimaryButton { tagger = Submit - , label = "Submit" - , title = "Save settings" + , label = texts.basics.submit + , title = texts.saveSettings , icon = Just "fa fa-save" } ] @@ -153,6 +154,7 @@ view2 flags settings classes model = ] , Html.map UiSettingsFormMsg (Comp.UiSettingsForm.view2 + texts.uiSettingsForm flags settings model.formModel diff --git a/modules/webapp/src/main/elm/Comp/UserForm.elm b/modules/webapp/src/main/elm/Comp/UserForm.elm index a1b74aad..93351ecd 100644 --- a/modules/webapp/src/main/elm/Comp/UserForm.elm +++ b/modules/webapp/src/main/elm/Comp/UserForm.elm @@ -19,6 +19,7 @@ import Data.UserState exposing (UserState) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput) +import Messages.Comp.UserForm exposing (Texts) import Styles as S import Util.Maybe @@ -40,14 +41,7 @@ emptyModel = , password = Nothing , state = Comp.Dropdown.makeSingleList - { makeOption = - \s -> - { value = Data.UserState.toString s - , text = Data.UserState.toString s - , additional = "" - } - , placeholder = "" - , options = Data.UserState.all + { options = Data.UserState.all , selected = List.head Data.UserState.all } } @@ -102,14 +96,7 @@ update _ msg model = let state = Comp.Dropdown.makeSingleList - { makeOption = - \s -> - { value = Data.UserState.toString s - , text = Data.UserState.toString s - , additional = "" - } - , placeholder = "" - , options = Data.UserState.all + { options = Data.UserState.all , selected = Data.UserState.fromString t.state |> Maybe.map (\u -> List.filter ((==) u) Data.UserState.all) @@ -166,19 +153,31 @@ update _ msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = + let + stateCfg = + { makeOption = + \s -> + { text = Data.UserState.toString s + , additional = "" + } + , placeholder = "" + , style = DS.mainStyle + , labelColor = \_ -> \_ -> "" + } + in div [ class "flex flex-col" ] [ div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "Login" + [ text texts.login , B.inputRequired ] , input [ type_ "text" , onInput SetLogin - , placeholder "Login" + , placeholder texts.login , value model.login , class S.textInput , classList [ ( S.inputErrorBorder, model.login == "" ) ] @@ -187,24 +186,24 @@ view2 settings model = ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "E-Mail" + [ text texts.email ] , input [ onInput SetEmail , type_ "text" , model.email |> Maybe.withDefault "" |> value - , placeholder "E-Mail" + , placeholder texts.email , class S.textInput ] [] ] , div [ class "mb-4" ] [ label [ class S.inputLabel ] - [ text "State" + [ text texts.state ] , Html.map StateMsg (Comp.Dropdown.view2 - DS.mainStyle + stateCfg settings model.state ) @@ -214,13 +213,13 @@ view2 settings model = , classList [ ( "hidden", model.user.login /= "" ) ] ] [ label [ class S.inputLabel ] - [ text "Password" + [ text texts.password , B.inputRequired ] , input [ type_ "text" , onInput SetPassword - , placeholder "Password" + , placeholder texts.password , Maybe.withDefault "" model.password |> value , class S.textInput , classList [ ( S.inputErrorBorder, Util.Maybe.isEmpty model.password ) ] diff --git a/modules/webapp/src/main/elm/Comp/UserManage.elm b/modules/webapp/src/main/elm/Comp/UserManage.elm index f1f7ff1d..553111e1 100644 --- a/modules/webapp/src/main/elm/Comp/UserManage.elm +++ b/modules/webapp/src/main/elm/Comp/UserManage.elm @@ -21,6 +21,7 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onSubmit) import Http +import Messages.Comp.UserManage exposing (Texts) import Styles as S import Util.Http import Util.Maybe @@ -30,7 +31,7 @@ type alias Model = { tableModel : Comp.UserTable.Model , formModel : Comp.UserForm.Model , viewMode : ViewMode - , formError : Maybe String + , formError : FormError , loading : Bool , deleteConfirm : Comp.YesNoDimmer.Model } @@ -41,12 +42,18 @@ type ViewMode | Form +type FormError + = FormErrorNone + | FormErrorSubmit String + | FormErrorInvalid + + emptyModel : Model emptyModel = { tableModel = Comp.UserTable.emptyModel , formModel = Comp.UserForm.emptyModel , viewMode = Table - , formError = Nothing + , formError = FormErrorNone , loading = False , deleteConfirm = Comp.YesNoDimmer.emptyModel } @@ -79,7 +86,7 @@ update flags msg model = , viewMode = Maybe.map (\_ -> Form) tm.selected |> Maybe.withDefault Table , formError = if Util.Maybe.nonEmpty tm.selected then - Nothing + FormErrorNone else model.formError @@ -132,7 +139,7 @@ update flags msg model = InitNewUser -> let nm = - { model | viewMode = Form, formError = Nothing } + { model | viewMode = Form, formError = FormErrorNone } user = Api.Model.User.empty @@ -158,7 +165,7 @@ update flags msg model = ( { model | loading = True }, cmd ) else - ( { model | formError = Just "Please correct the errors in the form." }, Cmd.none ) + ( { model | formError = FormErrorInvalid }, Cmd.none ) SubmitResp (Ok res) -> if res.success then @@ -172,10 +179,15 @@ update flags msg model = ( { m3 | loading = False }, Cmd.batch [ c2, c3 ] ) else - ( { model | formError = Just res.message, loading = False }, Cmd.none ) + ( { model | formError = FormErrorSubmit res.message, loading = False }, Cmd.none ) SubmitResp (Err err) -> - ( { model | formError = Just (Util.Http.errorToString err), loading = False }, Cmd.none ) + ( { model + | formError = FormErrorSubmit (Util.Http.errorToString err) + , loading = False + } + , Cmd.none + ) RequestDelete -> update flags (YesNoMsg Comp.YesNoDimmer.activate) model @@ -202,44 +214,49 @@ update flags msg model = --- View2 -view2 : UiSettings -> Model -> Html Msg -view2 settings model = +view2 : Texts -> UiSettings -> Model -> Html Msg +view2 texts settings model = if model.viewMode == Table then - viewTable2 model + viewTable2 texts model else - viewForm2 settings model + viewForm2 texts settings model -viewTable2 : Model -> Html Msg -viewTable2 model = +viewTable2 : Texts -> Model -> Html Msg +viewTable2 texts model = div [ class "flex flex-col" ] [ MB.view { start = [] , end = [ MB.PrimaryButton { tagger = InitNewUser - , title = "Add a new user" + , title = texts.addNewUser , icon = Just "fa fa-plus" - , label = "New user" + , label = texts.newUser } ] , rootClasses = "mb-4" } - , Html.map TableMsg (Comp.UserTable.view2 model.tableModel) - , B.loadingDimmer model.loading + , Html.map TableMsg (Comp.UserTable.view2 texts.userTable model.tableModel) + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] -viewForm2 : UiSettings -> Model -> Html Msg -viewForm2 settings model = +viewForm2 : Texts -> UiSettings -> Model -> Html Msg +viewForm2 texts settings model = let newUser = Comp.UserForm.isNewUser model.formModel dimmerSettings : Comp.YesNoDimmer.Settings dimmerSettings = - Comp.YesNoDimmer.defaultSettings2 "Really delete this user?" + Comp.YesNoDimmer.defaultSettings texts.reallyDeleteUser + texts.basics.yes + texts.basics.no in Html.form [ class "flex flex-col md:relative" @@ -252,7 +269,7 @@ viewForm2 settings model = ) , if newUser then h3 [ class S.header2 ] - [ text "Create new user" + [ text texts.createNewUser ] else @@ -263,24 +280,24 @@ viewForm2 settings model = { start = [ MB.PrimaryButton { tagger = Submit - , title = "Submit this form" + , title = texts.basics.submitThisForm , icon = Just "fa fa-save" - , label = "Submit" + , label = texts.basics.submit } , MB.SecondaryButton { tagger = SetViewMode Table - , title = "Back to list" + , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" - , label = "Cancel" + , label = texts.basics.cancel } ] , end = if not newUser then [ MB.DeleteButton { tagger = RequestDelete - , title = "Delete this user" + , title = texts.deleteThisUser , icon = Just "fa fa-trash" - , label = "Delete" + , label = texts.basics.delete } ] @@ -288,14 +305,25 @@ viewForm2 settings model = [] , rootClasses = "mb-4" } - , Html.map FormMsg (Comp.UserForm.view2 settings model.formModel) + , Html.map FormMsg (Comp.UserForm.view2 texts.userForm settings model.formModel) , div [ classList - [ ( "hidden", Util.Maybe.isEmpty model.formError ) + [ ( "hidden", model.formError == FormErrorNone ) ] , class S.errorMessage ] - [ Maybe.withDefault "" model.formError |> text + [ case model.formError of + FormErrorNone -> + text "" + + FormErrorSubmit err -> + text err + + FormErrorInvalid -> + text texts.pleaseCorrectErrors ] - , B.loadingDimmer model.loading + , B.loadingDimmer + { active = model.loading + , label = texts.basics.loading + } ] diff --git a/modules/webapp/src/main/elm/Comp/UserTable.elm b/modules/webapp/src/main/elm/Comp/UserTable.elm index 8a021de3..b30ee285 100644 --- a/modules/webapp/src/main/elm/Comp/UserTable.elm +++ b/modules/webapp/src/main/elm/Comp/UserTable.elm @@ -11,6 +11,7 @@ import Comp.Basic as B import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) +import Messages.Comp.UserTable exposing (Texts) import Styles as S import Util.Time exposing (formatDateTime) @@ -51,32 +52,34 @@ update _ msg model = --- View2 -view2 : Model -> Html Msg -view2 model = +view2 : Texts -> Model -> Html Msg +view2 texts model = table [ class S.tableMain ] [ thead [] [ tr [] [ th [ class "w-px whitespace-nowrap" ] [] - , th [ class "text-left" ] [ text "Login" ] - , th [ class "text-center" ] [ text "State" ] - , th [ class "hidden md:table-cell text-left" ] [ text "Email" ] - , th [ class "hidden md:table-cell text-center" ] [ text "Logins" ] - , th [ class "hidden sm:table-cell text-center" ] [ text "Last Login" ] - , th [ class "hidden md:table-cell text-center" ] [ text "Created" ] + , th [ class "text-left" ] [ text texts.login ] + , th [ class "text-center" ] [ text texts.state ] + , th [ class "hidden md:table-cell text-left" ] [ text texts.email ] + , th [ class "hidden md:table-cell text-center" ] [ text texts.login ] + , th [ class "hidden sm:table-cell text-center" ] [ text texts.lastLogin ] + , th [ class "hidden md:table-cell text-center" ] + [ text texts.basics.created + ] ] ] , tbody [] - (List.map (renderUserLine2 model) model.users) + (List.map (renderUserLine2 texts model) model.users) ] -renderUserLine2 : Model -> User -> Html Msg -renderUserLine2 model user = +renderUserLine2 : Texts -> Model -> User -> Html Msg +renderUserLine2 texts model user = tr [ classList [ ( "active", model.selected == Just user ) ] , class S.tableRow ] - [ B.editLinkTableCell (Select user) + [ B.editLinkTableCell2 texts.basics (Select user) , td [ class "text-left" ] [ text user.login ] diff --git a/modules/webapp/src/main/elm/Comp/YesNoDimmer.elm b/modules/webapp/src/main/elm/Comp/YesNoDimmer.elm index e4006c49..d32ed1c3 100644 --- a/modules/webapp/src/main/elm/Comp/YesNoDimmer.elm +++ b/modules/webapp/src/main/elm/Comp/YesNoDimmer.elm @@ -4,7 +4,6 @@ module Comp.YesNoDimmer exposing , Settings , activate , defaultSettings - , defaultSettings2 , disable , emptyModel , initActive @@ -58,24 +57,13 @@ type alias Settings = } -defaultSettings : Settings -defaultSettings = - { message = "Delete this item permanently?" - , headerIcon = "exclamation icon" - , headerClass = "ui inverted icon header" - , confirmButton = "Yes, do it!" - , cancelButton = "No" - , extraClass = "" - } - - -defaultSettings2 : String -> Settings -defaultSettings2 msg = +defaultSettings : String -> String -> String -> Settings +defaultSettings msg yesLabel noLabel = { message = msg , headerIcon = "fa fa-exclamation-circle mr-3" , headerClass = "text-2xl font-bold text-center w-full" - , confirmButton = "Yes, do it!" - , cancelButton = "No" + , confirmButton = yesLabel + , cancelButton = noLabel , extraClass = "" } diff --git a/modules/webapp/src/main/elm/Data/CustomFieldType.elm b/modules/webapp/src/main/elm/Data/CustomFieldType.elm index a9b89719..5bca7135 100644 --- a/modules/webapp/src/main/elm/Data/CustomFieldType.elm +++ b/modules/webapp/src/main/elm/Data/CustomFieldType.elm @@ -3,7 +3,6 @@ module Data.CustomFieldType exposing , all , asString , fromString - , label ) @@ -39,25 +38,6 @@ asString ft = "money" -label : CustomFieldType -> String -label ft = - case ft of - Text -> - "Text" - - Numeric -> - "Numeric" - - Date -> - "Date" - - Boolean -> - "Boolean" - - Money -> - "Money" - - fromString : String -> Maybe CustomFieldType fromString str = case String.toLower str of diff --git a/modules/webapp/src/main/elm/Data/Direction.elm b/modules/webapp/src/main/elm/Data/Direction.elm index 648f183f..b7230f6f 100644 --- a/modules/webapp/src/main/elm/Data/Direction.elm +++ b/modules/webapp/src/main/elm/Data/Direction.elm @@ -8,7 +8,6 @@ module Data.Direction exposing , iconFromMaybe2 , iconFromString , iconFromString2 - , labelFromMaybe , toString ) @@ -102,10 +101,3 @@ iconFromMaybe2 : Maybe String -> String iconFromMaybe2 ms = Maybe.map iconFromString2 ms |> Maybe.withDefault unknownIcon2 - - -labelFromMaybe : Maybe String -> String -labelFromMaybe ms = - Maybe.andThen fromString ms - |> Maybe.map toString - |> Maybe.withDefault "Direction" diff --git a/modules/webapp/src/main/elm/Data/EquipmentUse.elm b/modules/webapp/src/main/elm/Data/EquipmentUse.elm index 7341a2fd..be9f24de 100644 --- a/modules/webapp/src/main/elm/Data/EquipmentUse.elm +++ b/modules/webapp/src/main/elm/Data/EquipmentUse.elm @@ -3,7 +3,6 @@ module Data.EquipmentUse exposing , all , asString , fromString - , label ) import Api.Model.Equipment exposing (Equipment) @@ -37,16 +36,6 @@ asString pu = "disabled" -label : EquipmentUse -> String -label pu = - case pu of - Concerning -> - "Concerning" - - Disabled -> - "Disabled" - - all : List EquipmentUse all = [ Concerning, Disabled ] diff --git a/modules/webapp/src/main/elm/Data/Fields.elm b/modules/webapp/src/main/elm/Data/Fields.elm index ef977d38..d0cf4f3c 100644 --- a/modules/webapp/src/main/elm/Data/Fields.elm +++ b/modules/webapp/src/main/elm/Data/Fields.elm @@ -3,7 +3,6 @@ module Data.Fields exposing , all , fromList , fromString - , label , sort , toString ) @@ -130,46 +129,6 @@ toString field = "sourcename" -label : Field -> String -label field = - case field of - Tag -> - "Tag" - - Folder -> - "Folder" - - CorrOrg -> - "Correspondent Organization" - - CorrPerson -> - "Correspondent Person" - - ConcPerson -> - "Concerning Person" - - ConcEquip -> - "Concerned Equipment" - - Date -> - "Date" - - DueDate -> - "Due Date" - - Direction -> - "Direction" - - PreviewImage -> - "Preview Image" - - CustomFields -> - "Custom Fields" - - SourceName -> - "Item Source" - - fromList : List String -> List Field fromList strings = List.filterMap fromString strings diff --git a/modules/webapp/src/main/elm/Data/ItemTemplate.elm b/modules/webapp/src/main/elm/Data/ItemTemplate.elm index 30fbf43d..8924ad8e 100644 --- a/modules/webapp/src/main/elm/Data/ItemTemplate.elm +++ b/modules/webapp/src/main/elm/Data/ItemTemplate.elm @@ -17,7 +17,6 @@ module Data.ItemTemplate exposing , folder , from , fromMaybe - , helpMessage , isEmpty , literal , map @@ -240,37 +239,6 @@ getName = --- Parse pattern -helpMessage : String -helpMessage = - """ -A pattern allows to customize the title and subtitle of each card. -Variables expressions are enclosed in `{{` and `}}`, other text is -used as-is. The following variables are available: - -- `{{name}}` the item name -- `{{source}}` the source the item was created from -- `{{folder}}` the items folder -- `{{corrOrg}}` the correspondent organization -- `{{corrPerson}}` the correspondent person -- `{{correspondent}}` both organization and person separated by a comma -- `{{concPerson}}` the concerning person -- `{{concEquip}}` the concerning equipment -- `{{concerning}}` both person and equipment separated by a comma -- `{{fileCount}}` the number of attachments of this item -- `{{dateLong}}` the item date as full formatted date -- `{{dateShort}}` the item date as short formatted date (yyyy/mm/dd) -- `{{dueDateLong}}` the item due date as full formatted date -- `{{dueDateShort}}` the item due date as short formatted date (yyyy/mm/dd) -- `{{direction}}` the items direction values as string - -If some variable is not present, an empty string is rendered. You can -combine multiple variables with `|` to use the first non-empty one, -for example `{{corrOrg|corrPerson|-}}` would render the organization -and if that is not present the person. If both are absent a dash `-` -is rendered. -""" - - knownPattern : String -> Maybe ItemTemplate knownPattern str = case str of diff --git a/modules/webapp/src/main/elm/Data/Language.elm b/modules/webapp/src/main/elm/Data/Language.elm index f0cdac3d..3ea22908 100644 --- a/modules/webapp/src/main/elm/Data/Language.elm +++ b/modules/webapp/src/main/elm/Data/Language.elm @@ -3,7 +3,6 @@ module Data.Language exposing , all , fromString , toIso3 - , toName ) @@ -125,55 +124,6 @@ toIso3 lang = "lav" -toName : Language -> String -toName lang = - case lang of - German -> - "German" - - English -> - "English" - - French -> - "French" - - Italian -> - "Italian" - - Spanish -> - "Spanish" - - Portuguese -> - "Portuguese" - - Czech -> - "Czech" - - Danish -> - "Danish" - - Finnish -> - "Finnish" - - Norwegian -> - "Norwegian" - - Swedish -> - "Swedish" - - Russian -> - "Russian" - - Romanian -> - "Romanian" - - Dutch -> - "Dutch" - - Latvian -> - "Latvian" - - all : List Language all = [ German diff --git a/modules/webapp/src/main/elm/Data/Money.elm b/modules/webapp/src/main/elm/Data/Money.elm index 7856f517..cffe7dfc 100644 --- a/modules/webapp/src/main/elm/Data/Money.elm +++ b/modules/webapp/src/main/elm/Data/Money.elm @@ -1,5 +1,6 @@ module Data.Money exposing ( Money + , MoneyParseError(..) , format , fromString , normalizeInput @@ -11,7 +12,12 @@ type alias Money = Float -fromString : String -> Result String Money +type MoneyParseError + = RequireTwoDigitsAfterDot String + | NoOrTooManyPoints String + + +fromString : String -> Result MoneyParseError Money fromString str = let input = @@ -28,13 +34,13 @@ fromString str = if index == (len - 3) then String.toFloat input |> Maybe.map Ok - |> Maybe.withDefault (Err "Two digits required after the dot.") + |> Maybe.withDefault (Err (RequireTwoDigitsAfterDot str)) else - Err ("Two digits required after the dot: " ++ str) + Err (RequireTwoDigitsAfterDot str) _ -> - Err "One single dot + digits required for money." + Err (NoOrTooManyPoints str) format : Float -> String diff --git a/modules/webapp/src/main/elm/Data/OrgUse.elm b/modules/webapp/src/main/elm/Data/OrgUse.elm index ca0f6fec..5f536bd9 100644 --- a/modules/webapp/src/main/elm/Data/OrgUse.elm +++ b/modules/webapp/src/main/elm/Data/OrgUse.elm @@ -3,7 +3,6 @@ module Data.OrgUse exposing , all , asString , fromString - , label ) @@ -35,16 +34,6 @@ asString pu = "disabled" -label : OrgUse -> String -label pu = - case pu of - Correspondent -> - "Correspondent" - - Disabled -> - "Disabled" - - all : List OrgUse all = [ Correspondent, Disabled ] diff --git a/modules/webapp/src/main/elm/Data/PersonUse.elm b/modules/webapp/src/main/elm/Data/PersonUse.elm index fc5d2060..204d5b92 100644 --- a/modules/webapp/src/main/elm/Data/PersonUse.elm +++ b/modules/webapp/src/main/elm/Data/PersonUse.elm @@ -3,7 +3,6 @@ module Data.PersonUse exposing , all , asString , fromString - , label , spanPersonList ) @@ -52,22 +51,6 @@ asString pu = "disabled" -label : PersonUse -> String -label pu = - case pu of - Correspondent -> - "Correspondent" - - Concerning -> - "Concerning" - - Both -> - "Both" - - Disabled -> - "Disabled" - - all : List PersonUse all = [ Correspondent, Concerning, Both, Disabled ] diff --git a/modules/webapp/src/main/elm/Data/SSLType.elm b/modules/webapp/src/main/elm/Data/SSLType.elm index 35327f56..44f9b836 100644 --- a/modules/webapp/src/main/elm/Data/SSLType.elm +++ b/modules/webapp/src/main/elm/Data/SSLType.elm @@ -2,7 +2,6 @@ module Data.SSLType exposing ( SSLType(..) , all , fromString - , label , toString ) @@ -45,16 +44,3 @@ fromString str = _ -> Nothing - - -label : SSLType -> String -label st = - case st of - None -> - "None" - - SSL -> - "SSL/TLS" - - StartTLS -> - "StartTLS" diff --git a/modules/webapp/src/main/elm/Data/UiSettings.elm b/modules/webapp/src/main/elm/Data/UiSettings.elm index 988eb2d4..8e1e3cd0 100644 --- a/modules/webapp/src/main/elm/Data/UiSettings.elm +++ b/modules/webapp/src/main/elm/Data/UiSettings.elm @@ -7,7 +7,6 @@ module Data.UiSettings exposing , cardPreviewSize2 , catColor , catColorFg2 - , catColorString , catColorString2 , defaults , fieldHidden @@ -18,7 +17,6 @@ module Data.UiSettings exposing , posToString , tagColor , tagColorFg2 - , tagColorString , tagColorString2 , toStoredUiSettings ) @@ -32,6 +30,8 @@ import Data.UiTheme exposing (UiTheme) import Dict exposing (Dict) import Html exposing (Attribute) import Html.Attributes as HA +import Messages +import Messages.UiLanguage exposing (UiLanguage) {-| Settings for the web ui. All fields should be optional, since it @@ -63,6 +63,7 @@ type alias StoredUiSettings = , uiTheme : Maybe String , sideMenuVisible : Bool , powerSearchEnabled : Bool + , uiLang : Maybe String } @@ -94,6 +95,7 @@ type alias UiSettings = , uiTheme : UiTheme , sideMenuVisible : Bool , powerSearchEnabled : Bool + , uiLang : UiLanguage } @@ -165,6 +167,7 @@ defaults = , uiTheme = Data.UiTheme.Light , sideMenuVisible = True , powerSearchEnabled = False + , uiLang = Messages.UiLanguage.English } @@ -217,6 +220,9 @@ merge given fallback = |> Maybe.withDefault fallback.uiTheme , sideMenuVisible = given.sideMenuVisible , powerSearchEnabled = given.powerSearchEnabled + , uiLang = + Maybe.map Messages.fromIso2 given.uiLang + |> Maybe.withDefault Messages.UiLanguage.English } @@ -254,6 +260,7 @@ toStoredUiSettings settings = , uiTheme = Just (Data.UiTheme.toString settings.uiTheme) , sideMenuVisible = settings.sideMenuVisible , powerSearchEnabled = settings.powerSearchEnabled + , uiLang = Just <| Messages.toIso2 settings.uiLang } @@ -267,13 +274,6 @@ tagColor tag settings = Maybe.andThen (catColor settings) tag.category -catColorString : UiSettings -> String -> String -catColorString settings name = - catColor settings name - |> Maybe.map Data.Color.toString - |> Maybe.withDefault "" - - catColorString2 : UiSettings -> String -> String catColorString2 settings name = catColor settings name @@ -288,13 +288,6 @@ catColorFg2 settings name = |> Maybe.withDefault "" -tagColorString : Tag -> UiSettings -> String -tagColorString tag settings = - tagColor tag settings - |> Maybe.map Data.Color.toString - |> Maybe.withDefault "" - - tagColorString2 : Tag -> UiSettings -> String tagColorString2 tag settings = tagColor tag settings diff --git a/modules/webapp/src/main/elm/Messages.elm b/modules/webapp/src/main/elm/Messages.elm new file mode 100644 index 00000000..06857527 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages.elm @@ -0,0 +1,125 @@ +module Messages exposing + ( Messages + , fromIso2 + , get + , toIso2 + ) + +import Messages.App +import Messages.Page.CollectiveSettings +import Messages.Page.Home +import Messages.Page.ItemDetail +import Messages.Page.Login +import Messages.Page.ManageData +import Messages.Page.NewInvite +import Messages.Page.Queue +import Messages.Page.Register +import Messages.Page.Upload +import Messages.Page.UserSettings +import Messages.UiLanguage exposing (UiLanguage(..)) + + +{-| The messages record contains all strings used in the application. +-} +type alias Messages = + { lang : UiLanguage + , iso2 : String + , label : String + , flagIcon : String + , app : Messages.App.Texts + , collectiveSettings : Messages.Page.CollectiveSettings.Texts + , login : Messages.Page.Login.Texts + , register : Messages.Page.Register.Texts + , newInvite : Messages.Page.NewInvite.Texts + , upload : Messages.Page.Upload.Texts + , itemDetail : Messages.Page.ItemDetail.Texts + , queue : Messages.Page.Queue.Texts + , userSettings : Messages.Page.UserSettings.Texts + , manageData : Messages.Page.ManageData.Texts + , home : Messages.Page.Home.Texts + } + + +get : UiLanguage -> Messages +get lang = + case lang of + English -> + gb + + German -> + de + + +{-| Get a ISO-3166-1 code of the given lanugage. +-} +toIso2 : UiLanguage -> String +toIso2 lang = + get lang |> .iso2 + + +{-| Return the UiLanguage from given iso2 code. If the iso2 code is not +known, return Nothing. +-} +readIso2 : String -> Maybe UiLanguage +readIso2 iso = + let + isIso lang = + iso == toIso2 lang + in + List.filter isIso Messages.UiLanguage.all + |> List.head + + +{-| return the language from the given iso2 code. if the iso2 code is +not known, return English as a default. +-} +fromIso2 : String -> UiLanguage +fromIso2 iso = + readIso2 iso + |> Maybe.withDefault English + + + +--- Messages Definitions +-- for flag icons, see https://github.com/lipis/flag-icon-css +-- use two classes: flag-icon flag-icon-xx where xx is the two-letter country code + + +gb : Messages +gb = + { lang = English + , iso2 = "gb" + , label = "English" + , flagIcon = "flag-icon flag-icon-gb" + , app = Messages.App.gb + , collectiveSettings = Messages.Page.CollectiveSettings.gb + , login = Messages.Page.Login.gb + , register = Messages.Page.Register.gb + , newInvite = Messages.Page.NewInvite.gb + , upload = Messages.Page.Upload.gb + , itemDetail = Messages.Page.ItemDetail.gb + , queue = Messages.Page.Queue.gb + , userSettings = Messages.Page.UserSettings.gb + , manageData = Messages.Page.ManageData.gb + , home = Messages.Page.Home.gb + } + + +de : Messages +de = + { lang = German + , iso2 = "de" + , label = "Deutsch" + , flagIcon = "flag-icon flag-icon-de" + , app = Messages.App.de + , collectiveSettings = Messages.Page.CollectiveSettings.de + , login = Messages.Page.Login.de + , register = Messages.Page.Register.de + , newInvite = Messages.Page.NewInvite.de + , upload = Messages.Page.Upload.de + , itemDetail = Messages.Page.ItemDetail.de + , queue = Messages.Page.Queue.de + , userSettings = Messages.Page.UserSettings.de + , manageData = Messages.Page.ManageData.de + , home = Messages.Page.Home.de + } diff --git a/modules/webapp/src/main/elm/Messages/App.elm b/modules/webapp/src/main/elm/Messages/App.elm new file mode 100644 index 00000000..fc9e5011 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/App.elm @@ -0,0 +1,49 @@ +module Messages.App exposing + ( Texts + , de + , gb + ) + + +type alias Texts = + { collectiveProfile : String + , userProfile : String + , lightDark : String + , logout : String + , items : String + , manageData : String + , uploadFiles : String + , processingQueue : String + , newInvites : String + , help : String + } + + +gb : Texts +gb = + { collectiveProfile = "Collective Profile" + , userProfile = "User Profile" + , lightDark = "Light/Dark" + , logout = "Logout" + , items = "Items" + , manageData = "Manage Data" + , uploadFiles = "Upload Files" + , processingQueue = "Processing Queue" + , newInvites = "New Invites" + , help = "Help" + } + + +de : Texts +de = + { collectiveProfile = "Kollektiv-Profil" + , userProfile = "Benutzer-Profil" + , lightDark = "Hell/Dunkel" + , logout = "Abmelden" + , items = "Dokumente" + , manageData = "Daten verwalten" + , uploadFiles = "Dateien hochladen" + , processingQueue = "Verarbeitung" + , newInvites = "Neue Einladung" + , help = "Hilfe (English)" + } diff --git a/modules/webapp/src/main/elm/Messages/Basics.elm b/modules/webapp/src/main/elm/Messages/Basics.elm new file mode 100644 index 00000000..9c9616fb --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Basics.elm @@ -0,0 +1,73 @@ +module Messages.Basics exposing (..) + + +type alias Texts = + { incoming : String + , outgoing : String + , tags : String + , items : String + , submit : String + , submitThisForm : String + , cancel : String + , delete : String + , created : String + , edit : String + , back : String + , backToList : String + , searchPlaceholder : String + , id : String + , ok : String + , yes : String + , no : String + , chooseTag : String + , loading : String + , name : String + , organization : String + , person : String + , equipment : String + , folder : String + , date : String + , correspondent : String + , concerning : String + , customFields : String + , direction : String + } + + +gb : Texts +gb = + { incoming = "Incoming" + , outgoing = "Outgoing" + , tags = "Tags" + , items = "Items" + , submit = "Submit" + , submitThisForm = "Submit this form" + , cancel = "Cancel" + , delete = "Delete" + , created = "Created" + , edit = "Edit" + , back = "Back" + , backToList = "Back to list" + , searchPlaceholder = "Search…" + , id = "Id" + , ok = "Ok" + , yes = "Yes" + , no = "No" + , chooseTag = "Choose a tag…" + , loading = "Loading…" + , name = "Name" + , organization = "Organization" + , person = "Person" + , equipment = "Equipment" + , folder = "Folder" + , date = "Date" + , correspondent = "Correspondent" + , concerning = "Concerning" + , customFields = "Custom Fields" + , direction = "Direction" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Comp/AddressForm.elm b/modules/webapp/src/main/elm/Messages/Comp/AddressForm.elm new file mode 100644 index 00000000..42c0bf5d --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/AddressForm.elm @@ -0,0 +1,20 @@ +module Messages.Comp.AddressForm exposing (..) + + +type alias Texts = + { selectCountry : String + , street : String + , zipCode : String + , city : String + , country : String + } + + +gb : Texts +gb = + { selectCountry = "Select Country" + , street = "Street" + , zipCode = "Zip Code" + , city = "City" + , country = "Country" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/AttachmentMeta.elm b/modules/webapp/src/main/elm/Messages/Comp/AttachmentMeta.elm new file mode 100644 index 00000000..463dab6b --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/AttachmentMeta.elm @@ -0,0 +1,34 @@ +module Messages.Comp.AttachmentMeta exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , extractedMetadata : String + , content : String + , labels : String + , proposals : String + , correspondentOrg : String + , correspondentPerson : String + , concerningPerson : String + , concerningEquipment : String + , itemDate : String + , itemDueDate : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , extractedMetadata = "Extracted Meta Data" + , content = "Content" + , labels = "Labels" + , proposals = "Proposals" + , correspondentOrg = "Correspondent Organization" + , correspondentPerson = "Correspondent Person" + , concerningPerson = "Concerning Person" + , concerningEquipment = "Concerning Equipment" + , itemDate = "Item Date" + , itemDueDate = "Item Due Date" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CalEventInput.elm b/modules/webapp/src/main/elm/Messages/Comp/CalEventInput.elm new file mode 100644 index 00000000..f648dcc2 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CalEventInput.elm @@ -0,0 +1,28 @@ +module Messages.Comp.CalEventInput exposing (..) + + +type alias Texts = + { weekday : String + , year : String + , month : String + , day : String + , hour : String + , minute : String + , error : String + , schedule : String + , next : String + } + + +gb : Texts +gb = + { weekday = "Weekday" + , year = "Year" + , month = "Month" + , day = "Day" + , hour = "Hour" + , minute = "Minute" + , error = "Error" + , schedule = "Schedule" + , next = "Next" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ChangePasswordForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ChangePasswordForm.elm new file mode 100644 index 00000000..acbe8004 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ChangePasswordForm.elm @@ -0,0 +1,26 @@ +module Messages.Comp.ChangePasswordForm exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , currentPassword : String + , newPassword : String + , repeatPassword : String + , currentPasswordPlaceholder : String + , newPasswordPlaceholder : String + , repeatPasswordPlaceholder : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , currentPassword = "Current Password" + , newPassword = "New Password" + , repeatPassword = "New Password (repeat)" + , currentPasswordPlaceholder = "Password" + , newPasswordPlaceholder = "Password" + , repeatPasswordPlaceholder = "Password" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ClassifierSettingsForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ClassifierSettingsForm.elm new file mode 100644 index 00000000..dd649bbb --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ClassifierSettingsForm.elm @@ -0,0 +1,39 @@ +module Messages.Comp.ClassifierSettingsForm exposing (..) + +import Messages.Comp.CalEventInput + + +type alias Texts = + { calEventInput : Messages.Comp.CalEventInput.Texts + , autoTaggingText : String + , blacklistOrWhitelist : String + , whitelistLabel : String + , blacklistLabel : String + , itemCount : String + , schedule : String + , itemCountHelp : String + } + + +gb : Texts +gb = + { calEventInput = Messages.Comp.CalEventInput.gb + , autoTaggingText = + """ + +Auto-tagging works by learning from existing documents. The more +documents you have correctly tagged, the better. Learning is done +periodically based on a schedule. You can specify tag-groups that +should either be used (whitelist) or not used (blacklist) for +learning. + +Use an empty whitelist to disable auto tagging. + + """ + , blacklistOrWhitelist = "Is the following a blacklist or whitelist?" + , whitelistLabel = "Include tag categories for learning" + , blacklistLabel = "Exclude tag categories from learning" + , itemCount = "Item Count" + , schedule = "Schedule" + , itemCountHelp = "The maximum number of items to learn from, order by date newest first. Use 0 to mean all." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CollectiveSettingsForm.elm b/modules/webapp/src/main/elm/Messages/Comp/CollectiveSettingsForm.elm new file mode 100644 index 00000000..c4e0d741 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CollectiveSettingsForm.elm @@ -0,0 +1,46 @@ +module Messages.Comp.CollectiveSettingsForm exposing (..) + +import Data.Language exposing (Language) +import Messages.Comp.ClassifierSettingsForm +import Messages.Data.Language + + +type alias Texts = + { classifierSettingsForm : Messages.Comp.ClassifierSettingsForm.Texts + , save : String + , saveSettings : String + , documentLanguage : String + , documentLanguageHelp : String + , integrationEndpoint : String + , integrationEndpointLabel : String + , integrationEndpointHelp : String + , fulltextSearch : String + , reindexAllData : String + , reindexAllDataHelp : String + , autoTagging : String + , startNow : String + , languageLabel : Language -> String + } + + +gb : Texts +gb = + { classifierSettingsForm = Messages.Comp.ClassifierSettingsForm.gb + , save = "Save" + , saveSettings = "Save Settings" + , documentLanguage = "Document Language" + , documentLanguageHelp = "The language of your documents. This helps text recognition (OCR) and text analysis." + , integrationEndpoint = "Integration Endpoint" + , integrationEndpointLabel = "Enable integration endpoint" + , integrationEndpointHelp = + "The integration endpoint allows (local) applications to submit files. " + ++ "You can choose to disable it for your collective." + , fulltextSearch = "Full-Text Search" + , reindexAllData = "Re-Index All Data" + , reindexAllDataHelp = + "This starts a task that clears the full-text index and re-indexes all your data again." + ++ "You must type OK before clicking the button to avoid accidental re-indexing." + , autoTagging = "Auto-Tagging" + , startNow = "Start now" + , languageLabel = Messages.Data.Language.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CustomFieldForm.elm b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldForm.elm new file mode 100644 index 00000000..69abed71 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldForm.elm @@ -0,0 +1,44 @@ +module Messages.Comp.CustomFieldForm exposing (..) + +import Data.CustomFieldType exposing (CustomFieldType) +import Messages.Basics +import Messages.Data.CustomFieldType + + +type alias Texts = + { basics : Messages.Basics.Texts + , reallyDeleteField : String + , fieldTypeLabel : CustomFieldType -> String + , createCustomField : String + , modifyTypeWarning : String + , nameInfo : String + , fieldFormat : String + , fieldFormatInfo : String + , label : String + , labelInfo : String + , deleteThisField : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , reallyDeleteField = "Really delete this custom field?" + , fieldTypeLabel = Messages.Data.CustomFieldType.gb + , createCustomField = "Create a new custom field." + , modifyTypeWarning = + "Note that changing the format may " + ++ "result in invisible values in the ui, if they don't comply to the new format!" + , nameInfo = + "The name uniquely identifies this field. It must be a valid " + ++ "identifier, not contain spaces or weird characters." + , fieldFormat = "Field Format" + , fieldFormatInfo = + "A field must have a format. Values are validated " + ++ "according to this format." + , label = "Label" + , labelInfo = + "The user defined label for this field. This is used to represent " + ++ "this field in the ui. If not present, the name is used." + , deleteThisField = "Delete this field" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CustomFieldInput.elm b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldInput.elm new file mode 100644 index 00000000..905c0dff --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldInput.elm @@ -0,0 +1,18 @@ +module Messages.Comp.CustomFieldInput exposing (..) + + +type alias Texts = + { errorNoValue : String + , errorNoNumber : String + , errorNoAmount : String + , errorNotANumber : String -> String + } + + +gb : Texts +gb = + { errorNoValue = "Please fill in some value" + , errorNoNumber = "No number given" + , errorNoAmount = "No amount given" + , errorNotANumber = \str -> "Not a number: " ++ str + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CustomFieldManage.elm b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldManage.elm new file mode 100644 index 00000000..123b6a05 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldManage.elm @@ -0,0 +1,24 @@ +module Messages.Comp.CustomFieldManage exposing (..) + +import Messages.Basics +import Messages.Comp.CustomFieldForm +import Messages.Comp.CustomFieldTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , fieldForm : Messages.Comp.CustomFieldForm.Texts + , fieldTable : Messages.Comp.CustomFieldTable.Texts + , addCustomField : String + , newCustomField : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , fieldForm = Messages.Comp.CustomFieldForm.gb + , fieldTable = Messages.Comp.CustomFieldTable.gb + , addCustomField = "Add a new custom field" + , newCustomField = "New custom field" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CustomFieldMultiInput.elm b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldMultiInput.elm new file mode 100644 index 00000000..59e5bc25 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldMultiInput.elm @@ -0,0 +1,14 @@ +module Messages.Comp.CustomFieldMultiInput exposing (..) + +import Messages.Comp.CustomFieldInput + + +type alias Texts = + { customFieldInput : Messages.Comp.CustomFieldInput.Texts + } + + +gb : Texts +gb = + { customFieldInput = Messages.Comp.CustomFieldInput.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/CustomFieldTable.elm b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldTable.elm new file mode 100644 index 00000000..30745c89 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/CustomFieldTable.elm @@ -0,0 +1,20 @@ +module Messages.Comp.CustomFieldTable exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , nameLabel : String + , format : String + , usageCount : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , nameLabel = "Name/Label" + , format = "Format" + , usageCount = "#Usage" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/DetailEdit.elm b/modules/webapp/src/main/elm/Messages/Comp/DetailEdit.elm new file mode 100644 index 00000000..e73bd47f --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/DetailEdit.elm @@ -0,0 +1,29 @@ +module Messages.Comp.DetailEdit exposing (..) + +import Messages.Basics +import Messages.Comp.CustomFieldForm +import Messages.Comp.EquipmentForm +import Messages.Comp.OrgForm +import Messages.Comp.PersonForm +import Messages.Comp.TagForm + + +type alias Texts = + { basics : Messages.Basics.Texts + , tagForm : Messages.Comp.TagForm.Texts + , personForm : Messages.Comp.PersonForm.Texts + , orgForm : Messages.Comp.OrgForm.Texts + , equipmentForm : Messages.Comp.EquipmentForm.Texts + , customFieldForm : Messages.Comp.CustomFieldForm.Texts + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , tagForm = Messages.Comp.TagForm.gb + , personForm = Messages.Comp.PersonForm.gb + , orgForm = Messages.Comp.OrgForm.gb + , equipmentForm = Messages.Comp.EquipmentForm.gb + , customFieldForm = Messages.Comp.CustomFieldForm.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/Dropzone.elm b/modules/webapp/src/main/elm/Messages/Comp/Dropzone.elm new file mode 100644 index 00000000..d1f17580 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/Dropzone.elm @@ -0,0 +1,20 @@ +module Messages.Comp.Dropzone exposing (..) + + +type alias Texts = + { dropFilesHere : String + , or : String + , select : String + , selectInfo : String + } + + +gb : Texts +gb = + { dropFilesHere = "Drop files here" + , or = "Or" + , select = "Select ..." + , selectInfo = + "Choose document files (pdf, docx, txt, html, …). " + ++ "Archives (zip and eml) are extracted." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsForm.elm b/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsForm.elm new file mode 100644 index 00000000..917d9986 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsForm.elm @@ -0,0 +1,48 @@ +module Messages.Comp.EmailSettingsForm exposing (..) + +import Data.SSLType exposing (SSLType) +import Messages.Basics +import Messages.Data.SSLType + + +type alias Texts = + { basics : Messages.Basics.Texts + , sslTypeLabel : SSLType -> String + , connectionPlaceholder : String + , connectionNameInfo : String + , smtpHost : String + , smtpHostPlaceholder : String + , smtpPort : String + , smtpUser : String + , smtpUserPlaceholder : String + , smtpPassword : String + , smtpPasswordPlaceholder : String + , fromAddress : String + , fromAddressPlaceholder : String + , replyTo : String + , replyToPlaceholder : String + , ssl : String + , ignoreCertCheck : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , sslTypeLabel = Messages.Data.SSLType.gb + , connectionPlaceholder = "Connection name, e.g. 'gmail.com'" + , connectionNameInfo = "The connection name must not contain whitespace or special characters." + , smtpHost = "SMTP Host" + , smtpHostPlaceholder = "SMTP host name, e.g. 'mail.gmail.com'" + , smtpPort = "SMTP Port" + , smtpUser = "SMTP User" + , smtpUserPlaceholder = "SMTP Username, e.g. 'your.name@gmail.com'" + , smtpPassword = "SMTP Password" + , smtpPasswordPlaceholder = "Password" + , fromAddress = "From Address" + , fromAddressPlaceholder = "Sender E-Mail address" + , replyTo = "Reply-To" + , replyToPlaceholder = "Optional reply-to E-Mail address" + , ssl = "SSL" + , ignoreCertCheck = "Ignore certificate check" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsManage.elm b/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsManage.elm new file mode 100644 index 00000000..a72c0531 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsManage.elm @@ -0,0 +1,28 @@ +module Messages.Comp.EmailSettingsManage exposing (..) + +import Messages.Basics +import Messages.Comp.EmailSettingsForm +import Messages.Comp.EmailSettingsTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , settingsForm : Messages.Comp.EmailSettingsForm.Texts + , settingsTable : Messages.Comp.EmailSettingsTable.Texts + , newSettings : String + , addNewSmtpSettings : String + , reallyDeleteConnection : String + , deleteThisEntry : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , settingsForm = Messages.Comp.EmailSettingsForm.gb + , settingsTable = Messages.Comp.EmailSettingsTable.gb + , newSettings = "New Settings" + , addNewSmtpSettings = "Add new SMTP settings" + , reallyDeleteConnection = "Really delete these connection?" + , deleteThisEntry = "Delete this connection" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsTable.elm b/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsTable.elm new file mode 100644 index 00000000..a39c11ff --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EmailSettingsTable.elm @@ -0,0 +1,18 @@ +module Messages.Comp.EmailSettingsTable exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , hostPort : String + , from : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , hostPort = "Host/Port" + , from = "From" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/EquipmentForm.elm b/modules/webapp/src/main/elm/Messages/Comp/EquipmentForm.elm new file mode 100644 index 00000000..779f2fff --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EquipmentForm.elm @@ -0,0 +1,26 @@ +module Messages.Comp.EquipmentForm exposing (..) + +import Data.EquipmentUse exposing (EquipmentUse) +import Messages.Basics +import Messages.Data.EquipmentUse + + +type alias Texts = + { basics : Messages.Basics.Texts + , use : String + , useAsConcerning : String + , useNotSuggestions : String + , equipmentUseLabel : EquipmentUse -> String + , notes : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , use = "Use" + , useAsConcerning = "Use as concerning equipment" + , useNotSuggestions = "Do not use for suggestions." + , equipmentUseLabel = Messages.Data.EquipmentUse.gb + , notes = "Notes" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/EquipmentManage.elm b/modules/webapp/src/main/elm/Messages/Comp/EquipmentManage.elm new file mode 100644 index 00000000..c6aab13b --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EquipmentManage.elm @@ -0,0 +1,28 @@ +module Messages.Comp.EquipmentManage exposing (..) + +import Messages.Basics +import Messages.Comp.EquipmentForm +import Messages.Comp.EquipmentTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , equipmentTable : Messages.Comp.EquipmentTable.Texts + , equipmentForm : Messages.Comp.EquipmentForm.Texts + , createNewEquipment : String + , newEquipment : String + , reallyDeleteEquipment : String + , deleteThisEquipment : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , equipmentTable = Messages.Comp.EquipmentTable.gb + , equipmentForm = Messages.Comp.EquipmentForm.gb + , createNewEquipment = "Create a new equipment" + , newEquipment = "New Equipment" + , reallyDeleteEquipment = "Really delete this equipment?" + , deleteThisEquipment = "Delete this equipment" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/EquipmentTable.elm b/modules/webapp/src/main/elm/Messages/Comp/EquipmentTable.elm new file mode 100644 index 00000000..5039e589 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EquipmentTable.elm @@ -0,0 +1,20 @@ +module Messages.Comp.EquipmentTable exposing (..) + +import Data.EquipmentUse exposing (EquipmentUse) +import Messages.Basics +import Messages.Data.EquipmentUse + + +type alias Texts = + { basics : Messages.Basics.Texts + , use : String + , equipmentUseLabel : EquipmentUse -> String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , use = "Use" + , equipmentUseLabel = Messages.Data.EquipmentUse.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/FolderDetail.elm b/modules/webapp/src/main/elm/Messages/Comp/FolderDetail.elm new file mode 100644 index 00000000..3c45cb34 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/FolderDetail.elm @@ -0,0 +1,32 @@ +module Messages.Comp.FolderDetail exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , reallyDeleteThisFolder : String + , autoOwnerInfo : String + , modifyInfo : String + , notOwnerInfo : String + , members : String + , addMember : String + , add : String + , removeMember : String + , deleteThisFolder : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , reallyDeleteThisFolder = "Really delete this folder?" + , autoOwnerInfo = "You are automatically set as owner of this new folder." + , modifyInfo = "Modify this folder by changing the name or add/remove members." + , notOwnerInfo = "You are not the owner of this folder and therefore are not allowed to edit it." + , members = "Members" + , addMember = "Add a new member" + , add = "Add" + , removeMember = "Remove this member" + , deleteThisFolder = "Delete this folder" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/FolderManage.elm b/modules/webapp/src/main/elm/Messages/Comp/FolderManage.elm new file mode 100644 index 00000000..c1912da4 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/FolderManage.elm @@ -0,0 +1,26 @@ +module Messages.Comp.FolderManage exposing (..) + +import Messages.Basics +import Messages.Comp.FolderDetail +import Messages.Comp.FolderTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , folderDetail : Messages.Comp.FolderDetail.Texts + , folderTable : Messages.Comp.FolderTable.Texts + , showOwningFoldersOnly : String + , createNewFolder : String + , newFolder : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , folderDetail = Messages.Comp.FolderDetail.gb + , folderTable = Messages.Comp.FolderTable.gb + , showOwningFoldersOnly = "Show owning folders only" + , createNewFolder = "Create a new folder" + , newFolder = "New Folder" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/FolderTable.elm b/modules/webapp/src/main/elm/Messages/Comp/FolderTable.elm new file mode 100644 index 00000000..18f404fc --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/FolderTable.elm @@ -0,0 +1,16 @@ +module Messages.Comp.FolderTable exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , memberCount : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , memberCount = "#Member" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsForm.elm new file mode 100644 index 00000000..c5c1f204 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsForm.elm @@ -0,0 +1,44 @@ +module Messages.Comp.ImapSettingsForm exposing (..) + +import Data.SSLType exposing (SSLType) +import Messages.Basics +import Messages.Data.SSLType + + +type alias Texts = + { basics : Messages.Basics.Texts + , sslTypeLabel : SSLType -> String + , connectionNamePlaceholder : String + , connectionNameInfo : String + , imapHost : String + , imapHostPlaceholder : String + , imapPort : String + , imapUser : String + , imapUserPlaceholder : String + , imapPassword : String + , imapPasswordPlaceholder : String + , ssl : String + , ignoreCertCheck : String + , enableOAuth2 : String + , oauth2Info : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , sslTypeLabel = Messages.Data.SSLType.gb + , connectionNamePlaceholder = "Connection name, e.g. 'gmail.com'" + , connectionNameInfo = "The connection name must not contain whitespace or special characters." + , imapHost = "IMAP Host" + , imapHostPlaceholder = "IMAP host name, e.g. 'mail.gmail.com'" + , imapPort = "IMAP Port" + , imapUser = "IMAP User" + , imapUserPlaceholder = "IMAP Username, e.g. 'your.name@gmail.com'" + , imapPassword = "IMAP Password" + , imapPasswordPlaceholder = "Password" + , ssl = "SSL" + , ignoreCertCheck = "Ignore certificate check" + , enableOAuth2 = "Enable OAuth2 authentication" + , oauth2Info = "Enabling this, allows to connect via XOAuth using the password as access token." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsManage.elm b/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsManage.elm new file mode 100644 index 00000000..296228e0 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsManage.elm @@ -0,0 +1,28 @@ +module Messages.Comp.ImapSettingsManage exposing (..) + +import Messages.Basics +import Messages.Comp.ImapSettingsForm +import Messages.Comp.ImapSettingsTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , imapForm : Messages.Comp.ImapSettingsForm.Texts + , imapTable : Messages.Comp.ImapSettingsTable.Texts + , addNewImapSettings : String + , newSettings : String + , reallyDeleteSettings : String + , deleteThisEntry : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , imapForm = Messages.Comp.ImapSettingsForm.gb + , imapTable = Messages.Comp.ImapSettingsTable.gb + , addNewImapSettings = "Add new IMAP settings" + , newSettings = "New Settings" + , reallyDeleteSettings = "Really delete this mail-box connection?" + , deleteThisEntry = "Delete this settings entry" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsTable.elm b/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsTable.elm new file mode 100644 index 00000000..2fdef3e0 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ImapSettingsTable.elm @@ -0,0 +1,16 @@ +module Messages.Comp.ImapSettingsTable exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , hostPort : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , hostPort = "Host/Port" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemCard.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemCard.elm new file mode 100644 index 00000000..56941360 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemCard.elm @@ -0,0 +1,24 @@ +module Messages.Comp.ItemCard exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , dueOn : String + , new : String + , openAttachmentFile : String + , gotoDetail : String + , cycleAttachments : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , dueOn = "Due on" + , new = "New" + , openAttachmentFile = "Open attachment file" + , gotoDetail = "Go to detail view" + , cycleAttachments = "Cycle attachments" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemCardList.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemCardList.elm new file mode 100644 index 00000000..9cb13cb0 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemCardList.elm @@ -0,0 +1,14 @@ +module Messages.Comp.ItemCardList exposing (..) + +import Messages.Comp.ItemCard + + +type alias Texts = + { itemCard : Messages.Comp.ItemCard.Texts + } + + +gb : Texts +gb = + { itemCard = Messages.Comp.ItemCard.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm new file mode 100644 index 00000000..dbd62f5d --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail.elm @@ -0,0 +1,66 @@ +module Messages.Comp.ItemDetail exposing (..) + +import Messages.Comp.DetailEdit +import Messages.Comp.ItemDetail.AddFilesForm +import Messages.Comp.ItemDetail.ItemInfoHeader +import Messages.Comp.ItemDetail.Notes +import Messages.Comp.ItemDetail.SingleAttachment +import Messages.Comp.ItemMail +import Messages.Comp.SentMails + + +type alias Texts = + { addFilesForm : Messages.Comp.ItemDetail.AddFilesForm.Texts + , itemInfoHeader : Messages.Comp.ItemDetail.ItemInfoHeader.Texts + , singleAttachment : Messages.Comp.ItemDetail.SingleAttachment.Texts + , sentMails : Messages.Comp.SentMails.Texts + , notes : Messages.Comp.ItemDetail.Notes.Texts + , itemMail : Messages.Comp.ItemMail.Texts + , detailEdit : Messages.Comp.DetailEdit.Texts + , key : String + , backToSearchResults : String + , previousItem : String + , nextItem : String + , sendMail : String + , addMoreFiles : String + , confirmItemMetadata : String + , confirm : String + , unconfirmItemMetadata : String + , reprocessItem : String + , deleteThisItem : String + , sentEmails : String + , sendThisItemViaEmail : String + , itemId : String + , createdOn : String + , lastUpdateOn : String + , sendingMailNow : String + } + + +gb : Texts +gb = + { addFilesForm = Messages.Comp.ItemDetail.AddFilesForm.gb + , itemInfoHeader = Messages.Comp.ItemDetail.ItemInfoHeader.gb + , singleAttachment = Messages.Comp.ItemDetail.SingleAttachment.gb + , sentMails = Messages.Comp.SentMails.gb + , notes = Messages.Comp.ItemDetail.Notes.gb + , itemMail = Messages.Comp.ItemMail.gb + , detailEdit = Messages.Comp.DetailEdit.gb + , key = "Key" + , backToSearchResults = "Back to search results" + , previousItem = "Previous item." + , nextItem = "Next item." + , sendMail = "Send Mail" + , addMoreFiles = "Add more files to this item" + , confirmItemMetadata = "Confirm item metadata" + , confirm = "Confirm" + , unconfirmItemMetadata = "Un-confirm item metadata" + , reprocessItem = "Reprocess this item" + , deleteThisItem = "Delete this item" + , sentEmails = "Sent E-Mails" + , sendThisItemViaEmail = "Send this item via E-Mail" + , itemId = "Item ID" + , createdOn = "Created on" + , lastUpdateOn = "Last update on" + , sendingMailNow = "Sending e-mail…" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/AddFilesForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/AddFilesForm.elm new file mode 100644 index 00000000..a1908411 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/AddFilesForm.elm @@ -0,0 +1,27 @@ +module Messages.Comp.ItemDetail.AddFilesForm exposing (..) + +import Messages.Basics +import Messages.Comp.Dropzone + + +type alias Texts = + { dropzone : Messages.Comp.Dropzone.Texts + , basics : Messages.Basics.Texts + , addMoreFilesToItem : String + , reset : String + , filesSubmittedInfo : String + , refreshNow : String + } + + +gb : Texts +gb = + { dropzone = Messages.Comp.Dropzone.gb + , basics = Messages.Basics.gb + , addMoreFilesToItem = "Add more files to this item" + , reset = "Reset" + , filesSubmittedInfo = + "All files have been uploaded. They are being processed, some data " + ++ "may not be available immediately. " + , refreshNow = "Refresh now" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/EditForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/EditForm.elm new file mode 100644 index 00000000..eefe9be8 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/EditForm.elm @@ -0,0 +1,52 @@ +module Messages.Comp.ItemDetail.EditForm exposing (..) + +import Messages.Basics +import Messages.Comp.CustomFieldMultiInput + + +type alias Texts = + { basics : Messages.Basics.Texts + , customFieldInput : Messages.Comp.CustomFieldMultiInput.Texts + , createNewCustomField : String + , chooseDirection : String + , selectPlaceholder : String + , folderNotOwnerWarning : String + , dueDateTab : String + , addNewOrg : String + , editOrg : String + , chooseOrg : String + , addNewCorrespondentPerson : String + , editPerson : String + , personOrgInfo : String + , addNewConcerningPerson : String + , addNewEquipment : String + , editEquipment : String + , suggestions : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , customFieldInput = Messages.Comp.CustomFieldMultiInput.gb + , createNewCustomField = "Create new custom field" + , chooseDirection = "Choose a direction…" + , selectPlaceholder = "Select…" + , folderNotOwnerWarning = + """ +You are **not a member** of this folder. This item will be **hidden** +from any search now. Use a folder where you are a member of to make this +item visible. This message will disappear then. +""" + , dueDateTab = "Due Date" + , addNewOrg = "Add new organization" + , editOrg = "Edit organization" + , chooseOrg = "Choose an organization" + , addNewCorrespondentPerson = "Add new correspondent person" + , editPerson = "Edit person" + , personOrgInfo = "The selected person doesn't belong to the selected organization." + , addNewConcerningPerson = "Add new concerning person" + , addNewEquipment = "Add new equipment" + , editEquipment = "Edit equipment" + , suggestions = "Suggestions" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/ItemInfoHeader.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/ItemInfoHeader.elm new file mode 100644 index 00000000..aef26dae --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/ItemInfoHeader.elm @@ -0,0 +1,22 @@ +module Messages.Comp.ItemDetail.ItemInfoHeader exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , itemDate : String + , dueDate : String + , source : String + , new : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , itemDate = "Item Date" + , dueDate = "Due Date" + , source = "Source" + , new = "New" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/MultiEditMenu.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/MultiEditMenu.elm new file mode 100644 index 00000000..1ed6d2c2 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/MultiEditMenu.elm @@ -0,0 +1,44 @@ +module Messages.Comp.ItemDetail.MultiEditMenu exposing (..) + +import Messages.Basics +import Messages.Comp.CustomFieldMultiInput + + +type alias Texts = + { basics : Messages.Basics.Texts + , customFieldMultiInput : Messages.Comp.CustomFieldMultiInput.Texts + , tagModeAddInfo : String + , tagModeRemoveInfo : String + , tagModeReplaceInfo : String + , selectPlaceholder : String + , chooseDirection : String + , confirmUnconfirm : String + , confirm : String + , unconfirm : String + , changeTagMode : String + , folderNotOwnerWarning : String + , dueDateTab : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , customFieldMultiInput = Messages.Comp.CustomFieldMultiInput.gb + , tagModeAddInfo = "Tags chosen here are *added* to all selected items." + , tagModeRemoveInfo = "Tags chosen here are *removed* from all selected items." + , tagModeReplaceInfo = "Tags chosen here *replace* those on selected items." + , selectPlaceholder = "Select…" + , chooseDirection = "Choose a direction…" + , confirmUnconfirm = "Confirm/Unconfirm item metadata" + , confirm = "Confirm" + , unconfirm = "Unconfirm" + , changeTagMode = "Change tag edit mode" + , folderNotOwnerWarning = + """ +You are **not a member** of this folder. This item will be **hidden** +from any search now. Use a folder where you are a member of to make this +item visible. This message will disappear then. + """ + , dueDateTab = "Due Date" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/Notes.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/Notes.elm new file mode 100644 index 00000000..de92e57e --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/Notes.elm @@ -0,0 +1,20 @@ +module Messages.Comp.ItemDetail.Notes exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , notes : String + , preview : String + , supportsMarkdown : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , notes = "Notes" + , preview = "Preview" + , supportsMarkdown = "Supports Markdown" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm new file mode 100644 index 00000000..f785b748 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemDetail/SingleAttachment.elm @@ -0,0 +1,34 @@ +module Messages.Comp.ItemDetail.SingleAttachment exposing (..) + +import Messages.Comp.AttachmentMeta + + +type alias Texts = + { attachmentMeta : Messages.Comp.AttachmentMeta.Texts + , noName : String + , openFileInNewTab : String + , downloadFile : String + , renameFile : String + , downloadOriginalArchiveFile : String + , originalFile : String + , renderPdfByBrowser : String + , viewExtractedData : String + , reprocessFile : String + , deleteThisFile : String + } + + +gb : Texts +gb = + { attachmentMeta = Messages.Comp.AttachmentMeta.gb + , noName = "No name" + , openFileInNewTab = "Open file in new tab" + , downloadFile = "Download file" + , renameFile = "Rename file" + , downloadOriginalArchiveFile = "Download original archive" + , originalFile = "Original file" + , renderPdfByBrowser = "Render pdf by browser" + , viewExtractedData = "View extracted data" + , reprocessFile = "Re-process this file" + , deleteThisFile = "Delete this file" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ItemMail.elm b/modules/webapp/src/main/elm/Messages/Comp/ItemMail.elm new file mode 100644 index 00000000..f154aa1a --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ItemMail.elm @@ -0,0 +1,30 @@ +module Messages.Comp.ItemMail exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , selectConnection : String + , sendVia : String + , recipients : String + , ccRecipients : String + , bccRecipients : String + , subject : String + , body : String + , includeAllAttachments : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , selectConnection = "Select connection..." + , sendVia = "Send via" + , recipients = "Recipient(s)" + , ccRecipients = "CC recipient(s)" + , bccRecipients = "BCC recipient(s)..." + , subject = "Subject" + , body = "Body" + , includeAllAttachments = "Include all item attachments" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationForm.elm new file mode 100644 index 00000000..74894b16 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationForm.elm @@ -0,0 +1,67 @@ +module Messages.Comp.NotificationForm exposing (..) + +import Messages.Basics +import Messages.Comp.CalEventInput + + +type alias Texts = + { basics : Messages.Basics.Texts + , calEventInput : Messages.Comp.CalEventInput.Texts + , reallyDeleteTask : String + , startOnce : String + , startTaskNow : String + , selectConnection : String + , deleteThisTask : String + , enableDisable : String + , summary : String + , summaryInfo : String + , sendVia : String + , sendViaInfo : String + , recipients : String + , recipientsInfo : String + , tagsInclude : String + , tagsIncludeInfo : String + , tagsExclude : String + , tagsExcludeInfo : String + , remindDaysInfo : String + , remindDaysLabel : String + , capOverdue : String + , capOverdueInfo : String + , schedule : String + , scheduleClickForHelp : String + , scheduleInfo : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , calEventInput = Messages.Comp.CalEventInput.gb + , reallyDeleteTask = "Really delete this notification task?" + , startOnce = "Start Once" + , startTaskNow = "Start this task now" + , selectConnection = "Select connection..." + , deleteThisTask = "Delete this task" + , enableDisable = "Enable or disable this task." + , summary = "Summary" + , summaryInfo = "Some human readable name, only for displaying" + , sendVia = "Send via" + , sendViaInfo = "The SMTP connection to use when sending notification mails." + , recipients = "Recipient(s)" + , recipientsInfo = "One or more mail addresses, confirm each by pressing 'Return'." + , tagsInclude = "Tags Include (and)" + , tagsIncludeInfo = "Items must have all the tags specified here." + , tagsExclude = "Tags Exclude (or)" + , tagsExcludeInfo = "Items must not have any tag specified here." + , remindDaysLabel = "Remind Days" + , remindDaysInfo = "Select items with a due date *lower than* `today+remindDays`" + , capOverdue = "Cap overdue items" + , capOverdueInfo = "If checked, only items with a due date *greater than* `today - remindDays` are considered." + , schedule = "Schedule" + , scheduleClickForHelp = "Click here for help" + , scheduleInfo = + "Specify how often and when this task should run. " + ++ "Use English 3-letter weekdays. Either a single value, " + ++ "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) " + ++ "is allowed for each part." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationManage.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationManage.elm new file mode 100644 index 00000000..b766598d --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationManage.elm @@ -0,0 +1,24 @@ +module Messages.Comp.NotificationManage exposing (..) + +import Messages.Basics +import Messages.Comp.NotificationForm +import Messages.Comp.NotificationTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , notificationForm : Messages.Comp.NotificationForm.Texts + , notificationTable : Messages.Comp.NotificationTable.Texts + , newTask : String + , createNewTask : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , notificationForm = Messages.Comp.NotificationForm.gb + , notificationTable = Messages.Comp.NotificationTable.gb + , newTask = "New Task" + , createNewTask = "Create a new notification task" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationTable.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationTable.elm new file mode 100644 index 00000000..acea92ed --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationTable.elm @@ -0,0 +1,18 @@ +module Messages.Comp.NotificationTable exposing (..) + + +type alias Texts = + { summary : String + , schedule : String + , connection : String + , recipients : String + } + + +gb : Texts +gb = + { summary = "Summary" + , schedule = "Schedule" + , connection = "Connection" + , recipients = "Recipients" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/OrgForm.elm b/modules/webapp/src/main/elm/Messages/Comp/OrgForm.elm new file mode 100644 index 00000000..b22139d2 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/OrgForm.elm @@ -0,0 +1,39 @@ +module Messages.Comp.OrgForm exposing (..) + +import Data.ContactType exposing (ContactType) +import Data.OrgUse exposing (OrgUse) +import Messages.Basics +import Messages.Comp.AddressForm +import Messages.Data.ContactType +import Messages.Data.OrgUse + + +type alias Texts = + { basics : Messages.Basics.Texts + , addressForm : Messages.Comp.AddressForm.Texts + , orgUseLabel : OrgUse -> String + , shortName : String + , use : String + , useAsCorrespondent : String + , dontUseForSuggestions : String + , address : String + , contacts : String + , contactTypeLabel : ContactType -> String + , notes : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , addressForm = Messages.Comp.AddressForm.gb + , orgUseLabel = Messages.Data.OrgUse.gb + , shortName = "Short Name" + , use = "Use" + , useAsCorrespondent = "Use as correspondent" + , dontUseForSuggestions = "Do not use for suggestions." + , address = "Address" + , contacts = "Contacts" + , contactTypeLabel = Messages.Data.ContactType.gb + , notes = "Notes" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/OrgManage.elm b/modules/webapp/src/main/elm/Messages/Comp/OrgManage.elm new file mode 100644 index 00000000..a0474c8b --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/OrgManage.elm @@ -0,0 +1,28 @@ +module Messages.Comp.OrgManage exposing (..) + +import Messages.Basics +import Messages.Comp.OrgForm +import Messages.Comp.OrgTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , orgForm : Messages.Comp.OrgForm.Texts + , orgTable : Messages.Comp.OrgTable.Texts + , newOrganization : String + , createNewOrganization : String + , reallyDeleteOrg : String + , deleteThisOrg : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , orgForm = Messages.Comp.OrgForm.gb + , orgTable = Messages.Comp.OrgTable.gb + , newOrganization = "New Organization" + , createNewOrganization = "Create a new organization" + , reallyDeleteOrg = "Really delete this organization?" + , deleteThisOrg = "Delete this organization" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/OrgTable.elm b/modules/webapp/src/main/elm/Messages/Comp/OrgTable.elm new file mode 100644 index 00000000..867ff913 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/OrgTable.elm @@ -0,0 +1,22 @@ +module Messages.Comp.OrgTable exposing (..) + +import Data.OrgUse exposing (OrgUse) +import Messages.Basics +import Messages.Data.OrgUse + + +type alias Texts = + { basics : Messages.Basics.Texts + , address : String + , contact : String + , orgUseLabel : OrgUse -> String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , address = "Address" + , contact = "Contact" + , orgUseLabel = Messages.Data.OrgUse.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/PersonForm.elm b/modules/webapp/src/main/elm/Messages/Comp/PersonForm.elm new file mode 100644 index 00000000..fcb9bae3 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/PersonForm.elm @@ -0,0 +1,43 @@ +module Messages.Comp.PersonForm exposing (..) + +import Data.ContactType exposing (ContactType) +import Data.PersonUse exposing (PersonUse) +import Messages.Basics +import Messages.Comp.AddressForm +import Messages.Data.ContactType +import Messages.Data.PersonUse + + +type alias Texts = + { basics : Messages.Basics.Texts + , addressForm : Messages.Comp.AddressForm.Texts + , personUseLabel : PersonUse -> String + , useOfPerson : String + , useAsConcerningOnly : String + , useAsCorrespondentOnly : String + , useAsBoth : String + , dontUseForSuggestions : String + , chooseAnOrg : String + , address : String + , contacts : String + , contactTypeLabel : ContactType -> String + , notes : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , addressForm = Messages.Comp.AddressForm.gb + , personUseLabel = Messages.Data.PersonUse.gb + , useOfPerson = "Use of this person" + , useAsConcerningOnly = "Use as concerning person only" + , useAsCorrespondentOnly = "Use as correspondent person only" + , useAsBoth = "Use as both concerning or correspondent person" + , dontUseForSuggestions = "Do not use for suggestions." + , chooseAnOrg = "Choose an organization" + , address = "Address" + , contacts = "Contacts" + , contactTypeLabel = Messages.Data.ContactType.gb + , notes = "Notes" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/PersonManage.elm b/modules/webapp/src/main/elm/Messages/Comp/PersonManage.elm new file mode 100644 index 00000000..f32a4540 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/PersonManage.elm @@ -0,0 +1,28 @@ +module Messages.Comp.PersonManage exposing (..) + +import Messages.Basics +import Messages.Comp.PersonForm +import Messages.Comp.PersonTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , personForm : Messages.Comp.PersonForm.Texts + , personTable : Messages.Comp.PersonTable.Texts + , newPerson : String + , createNewPerson : String + , reallyDeletePerson : String + , deleteThisPerson : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , personForm = Messages.Comp.PersonForm.gb + , personTable = Messages.Comp.PersonTable.gb + , newPerson = "New Person" + , createNewPerson = "Create a new person" + , reallyDeletePerson = "Really delete this person?" + , deleteThisPerson = "Delete this person" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/PersonTable.elm b/modules/webapp/src/main/elm/Messages/Comp/PersonTable.elm new file mode 100644 index 00000000..2e81db34 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/PersonTable.elm @@ -0,0 +1,24 @@ +module Messages.Comp.PersonTable exposing (..) + +import Data.PersonUse exposing (PersonUse) +import Messages.Basics +import Messages.Data.PersonUse + + +type alias Texts = + { basics : Messages.Basics.Texts + , address : String + , contact : String + , use : String + , personUseLabel : PersonUse -> String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , address = "Address" + , contact = "Contact" + , use = "Use" + , personUseLabel = Messages.Data.PersonUse.gb + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxForm.elm new file mode 100644 index 00000000..c5c298b1 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxForm.elm @@ -0,0 +1,138 @@ +module Messages.Comp.ScanMailboxForm exposing (..) + +import Messages.Basics +import Messages.Comp.CalEventInput + + +type alias Texts = + { basics : Messages.Basics.Texts + , calEventInput : Messages.Comp.CalEventInput.Texts + , reallyDeleteTask : String + , startOnce : String + , startNow : String + , deleteThisTask : String + , generalTab : String + , processingTab : String + , additionalFilterTab : String + , postProcessingTab : String + , metadataTab : String + , scheduleTab : String + , processingTabInfo : String + , additionalFilterTabInfo : String + , postProcessingTabInfo : String + , metadataTabInfo : String + , scheduleTabInfo : String + , selectConnection : String + , enableDisable : String + , mailbox : String + , summary : String + , summaryInfo : String + , connectionInfo : String + , folders : String + , foldersInfo : String + , receivedHoursInfo : String + , receivedHoursLabel : String + , fileFilter : String + , fileFilterInfo : String + , subjectFilter : String + , subjectFilterInfo : String + , postProcessingLabel : String + , postProcessingInfo : String + , targetFolder : String + , targetFolderInfo : String + , deleteMailLabel : String + , deleteMailInfo : String + , itemDirection : String + , automatic : String + , itemDirectionInfo : String + , itemFolder : String + , itemFolderInfo : String + , folderOwnerWarning : String + , tagsInfo : String + , documentLanguage : String + , documentLanguageInfo : String + , schedule : String + , scheduleClickForHelp : String + , scheduleInfo : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , calEventInput = Messages.Comp.CalEventInput.gb + , reallyDeleteTask = "Really delete this scan mailbox task?" + , startOnce = "Start Once" + , startNow = "Start this task now" + , deleteThisTask = "Delete this task" + , generalTab = "General" + , processingTab = "Processing" + , additionalFilterTab = "Additional Filter" + , postProcessingTab = "Post Processing" + , metadataTab = "Metadata" + , scheduleTab = "Schedule" + , processingTabInfo = "These settings define which mails are fetched from the mail server." + , additionalFilterTabInfo = "These filters are applied to mails that have been fetched from the mailbox to select those that should be imported." + , postProcessingTabInfo = "This defines what happens to mails that have been downloaded." + , metadataTabInfo = "Define metadata that should be attached to all items created by this task." + , scheduleTabInfo = "Define when mails should be imported." + , selectConnection = "Select connection..." + , enableDisable = "Enable or disable this task." + , mailbox = "Mailbox" + , summary = "Summary" + , summaryInfo = "Some human readable name, only for displaying" + , connectionInfo = "The IMAP connection to use when sending notification mails." + , folders = "Folders" + , foldersInfo = "The folders to look for mails." + , receivedHoursInfo = "Select mails newer than `now - receivedHours`" + , receivedHoursLabel = "Received Since Hours" + , fileFilter = "File Filter" + , fileFilterInfo = + "Specify a file glob to filter attachments. For example, to only extract pdf files: " + ++ "`*.pdf`. If you want to include the mail body, allow html files or " + ++ "`mail.html`. Globs can be combined via OR, like this: " + ++ "`*.pdf|mail.html`. No file filter defaults to " + ++ "`*` that includes all" + , subjectFilter = "Subject Filter" + , subjectFilterInfo = + "Specify a file glob to filter mails by subject. For example: " + ++ "`*Scanned Document*`. No file filter defaults to `*` that includes all." + , postProcessingLabel = "Apply post-processing to all fetched mails." + , postProcessingInfo = + "When mails are fetched but not imported due to the 'Additional Filters', this flag can " + ++ "control whether they should be moved to a target folder or deleted (whatever is " + ++ "defined here) nevertheless. If unchecked only imported mails " + ++ "are post-processed, others stay where they are." + , targetFolder = "Target folder" + , targetFolderInfo = "Move mails into this folder." + , deleteMailLabel = "Delete imported mails" + , deleteMailInfo = + "Whether to delete all mails fetched by docspell. This only applies if " + ++ "*target folder* is not set." + , itemDirection = "Item direction" + , automatic = "Automatic" + , itemDirectionInfo = + "Sets the direction for an item. If you know all mails are incoming or " + ++ "outgoing, you can set it here. Otherwise it will be guessed from looking " + ++ "at sender and receiver." + , itemFolder = "Item Folder" + , itemFolderInfo = "Put all items from this mailbox into the selected folder" + , folderOwnerWarning = """ +You are **not a member** of this folder. Items created from mails in +this mailbox will be **hidden** from any search results. Use a folder +where you are a member of to make items visible. This message will +disappear then. + """ + , tagsInfo = "Choose tags that should be applied to items." + , documentLanguage = "Language" + , documentLanguageInfo = + "Used for text extraction and text analysis. The " + ++ "collective's default language is used, if not specified here." + , schedule = "Schedule" + , scheduleClickForHelp = "Click here for help" + , scheduleInfo = + "Specify how often and when this task should run. " + ++ "Use English 3-letter weekdays. Either a single value, " + ++ "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) " + ++ "is allowed for each part." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxManage.elm b/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxManage.elm new file mode 100644 index 00000000..8803cc22 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxManage.elm @@ -0,0 +1,24 @@ +module Messages.Comp.ScanMailboxManage exposing (..) + +import Messages.Basics +import Messages.Comp.ScanMailboxForm +import Messages.Comp.ScanMailboxTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , form : Messages.Comp.ScanMailboxForm.Texts + , table : Messages.Comp.ScanMailboxTable.Texts + , newTask : String + , createNewTask : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , form = Messages.Comp.ScanMailboxForm.gb + , table = Messages.Comp.ScanMailboxTable.gb + , newTask = "New Task" + , createNewTask = "Create a new scan mailbox task" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxTable.elm b/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxTable.elm new file mode 100644 index 00000000..48dd9cc2 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ScanMailboxTable.elm @@ -0,0 +1,18 @@ +module Messages.Comp.ScanMailboxTable exposing (..) + + +type alias Texts = + { summary : String + , connection : String + , folders : String + , receivedSince : String + } + + +gb : Texts +gb = + { summary = "Summary" + , connection = "Connection" + , folders = "Folders" + , receivedSince = "Received Since" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/SearchMenu.elm b/modules/webapp/src/main/elm/Messages/Comp/SearchMenu.elm new file mode 100644 index 00000000..9e693e63 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/SearchMenu.elm @@ -0,0 +1,62 @@ +module Messages.Comp.SearchMenu exposing (..) + +import Messages.Basics +import Messages.Comp.CustomFieldMultiInput +import Messages.Comp.TagSelect + + +type alias Texts = + { basics : Messages.Basics.Texts + , customFieldMultiInput : Messages.Comp.CustomFieldMultiInput.Texts + , tagSelect : Messages.Comp.TagSelect.Texts + , chooseDirection : String + , choosePerson : String + , chooseEquipment : String + , inbox : String + , fulltextSearch : String + , searchInNames : String + , switchSearchModes : String + , contentSearch : String + , searchInNamesPlaceholder : String + , fulltextSearchInfo : String + , nameSearchInfo : String + , tagCategoryTab : String + , chooseOrganization : String + , createCustomFieldTitle : String + , from : String + , to : String + , dueDateTab : String + , dueFrom : String + , dueTo : String + , sourceTab : String + , searchInItemSource : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , customFieldMultiInput = Messages.Comp.CustomFieldMultiInput.gb + , tagSelect = Messages.Comp.TagSelect.gb + , chooseDirection = "Choose a direction…" + , choosePerson = "Choose a person" + , chooseEquipment = "Choose an equipment" + , inbox = "Inbox" + , fulltextSearch = "Fulltext Search" + , searchInNames = "Search in names" + , switchSearchModes = "Switch between text search modes" + , contentSearch = "Content search…" + , searchInNamesPlaceholder = "Search in various names…" + , fulltextSearchInfo = "Fulltext search in document contents and notes." + , nameSearchInfo = "Looks in correspondents, concerned entities, item name and notes." + , tagCategoryTab = "Tag Categories" + , chooseOrganization = "Choose an organization" + , createCustomFieldTitle = "Create a new custom field" + , from = "From" + , to = "To" + , dueDateTab = "Due Date" + , dueFrom = "Due From" + , dueTo = "Due To" + , sourceTab = "Source" + , searchInItemSource = "Search in item source…" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/SearchStatsView.elm b/modules/webapp/src/main/elm/Messages/Comp/SearchStatsView.elm new file mode 100644 index 00000000..5810c588 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/SearchStatsView.elm @@ -0,0 +1,22 @@ +module Messages.Comp.SearchStatsView exposing (..) + + +type alias Texts = + { items : String + , count : String + , sum : String + , avg : String + , min : String + , max : String + } + + +gb : Texts +gb = + { items = "Items" + , count = "Count" + , sum = "Sum" + , avg = "Avg" + , min = "Min" + , max = "Max" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/SentMails.elm b/modules/webapp/src/main/elm/Messages/Comp/SentMails.elm new file mode 100644 index 00000000..1dd241fc --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/SentMails.elm @@ -0,0 +1,22 @@ +module Messages.Comp.SentMails exposing (..) + + +type alias Texts = + { from : String + , date : String + , recipients : String + , subject : String + , sent : String + , sender : String + } + + +gb : Texts +gb = + { from = "From" + , date = "Date" + , recipients = "Recipients" + , subject = "Subject" + , sent = "Sent" + , sender = "Sender" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/SourceForm.elm b/modules/webapp/src/main/elm/Messages/Comp/SourceForm.elm new file mode 100644 index 00000000..93e83f98 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/SourceForm.elm @@ -0,0 +1,63 @@ +module Messages.Comp.SourceForm exposing (..) + +import Data.Language exposing (Language) +import Messages.Basics +import Messages.Data.Language + + +type alias Texts = + { basics : Messages.Basics.Texts + , description : String + , enabled : String + , priority : String + , priorityInfo : String + , metadata : String + , metadataInfoText : String + , folderInfo : String + , folderForbiddenText : String + , tagsInfo : String + , fileFilter : String + , fileFilterInfo : String + , language : String + , languageInfo : String + , languageLabel : Language -> String + , selectPlaceholder : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , description = "Description" + , enabled = "Enabled" + , priority = "Priority" + , priorityInfo = "The priority used by the scheduler when processing uploaded files." + , metadata = "Metadata" + , metadataInfoText = + "Metadata specified here is automatically attached to each item uploaded " + ++ "through this source, unless it is overriden in the upload request meta data. " + ++ "Tags from the request are added to those defined here." + , folderInfo = "Choose a folder to automatically put items into." + , folderForbiddenText = + """ +You are **not a member** of this folder. Items created through this +link will be **hidden** from any search results. Use a folder where +you are a member of to make items visible. This message will +disappear then. + """ + , tagsInfo = "Choose tags that should be applied to items." + , fileFilter = "File Filter" + , fileFilterInfo = """ + +Specify a file glob to filter files when uploading archives +(e.g. for email and zip). For example, to only extract pdf files: +`*.pdf`. Globs can be combined via OR, like this: `*.pdf|mail.html`. + +""" + , language = "Language" + , languageInfo = + "Used for text extraction and analysis. The collective's " + ++ "default language is used if not specified here." + , languageLabel = Messages.Data.Language.gb + , selectPlaceholder = "Select…" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/SourceManage.elm b/modules/webapp/src/main/elm/Messages/Comp/SourceManage.elm new file mode 100644 index 00000000..8b466539 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/SourceManage.elm @@ -0,0 +1,53 @@ +module Messages.Comp.SourceManage exposing (..) + +import Messages.Basics +import Messages.Comp.SourceForm +import Messages.Comp.SourceTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , sourceTable : Messages.Comp.SourceTable.Texts + , sourceForm : Messages.Comp.SourceForm.Texts + , addSourceUrl : String + , newSource : String + , publicUploads : String + , sourceInfoText : String + , itemsCreatedInfo : Int -> String + , publicUploadPage : String + , copyToClipboard : String + , openInNewTab : String + , publicUploadUrl : String + , reallyDeleteSource : String + , createNewSource : String + , deleteThisSource : String + , errorGeneratingQR : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , sourceTable = Messages.Comp.SourceTable.gb + , sourceForm = Messages.Comp.SourceForm.gb + , addSourceUrl = "Add a source url" + , newSource = "New source" + , publicUploads = "Public Uploads" + , sourceInfoText = + "This source defines URLs that can be used by anyone to send files to " + ++ "you. There is a web page that you can share or the API url can be used " + ++ "with other clients." + , itemsCreatedInfo = + \n -> + "There have been " + ++ String.fromInt n + ++ " items created through this source." + , publicUploadPage = "Public Upload Page" + , copyToClipboard = "Copy to clipboard" + , openInNewTab = "Open in new tab/window" + , publicUploadUrl = "Public API Upload URL" + , reallyDeleteSource = "Really delete this source?" + , createNewSource = "Create new source" + , deleteThisSource = "Delete this source" + , errorGeneratingQR = "Error generating QR Code" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/SourceTable.elm b/modules/webapp/src/main/elm/Messages/Comp/SourceTable.elm new file mode 100644 index 00000000..90d6ea29 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/SourceTable.elm @@ -0,0 +1,22 @@ +module Messages.Comp.SourceTable exposing (..) + + +type alias Texts = + { abbrev : String + , enabled : String + , counter : String + , priority : String + , id : String + , show : String + } + + +gb : Texts +gb = + { abbrev = "Abbrev" + , enabled = "Enabled" + , counter = "Counter" + , priority = "Priority" + , id = "Id" + , show = "Show" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/TagForm.elm b/modules/webapp/src/main/elm/Messages/Comp/TagForm.elm new file mode 100644 index 00000000..9e80ed64 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/TagForm.elm @@ -0,0 +1,18 @@ +module Messages.Comp.TagForm exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , selectDefineCategory : String + , category : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , selectDefineCategory = "Select or define category..." + , category = "Category" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/TagManage.elm b/modules/webapp/src/main/elm/Messages/Comp/TagManage.elm new file mode 100644 index 00000000..1a05c160 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/TagManage.elm @@ -0,0 +1,28 @@ +module Messages.Comp.TagManage exposing (..) + +import Messages.Basics +import Messages.Comp.TagForm +import Messages.Comp.TagTable + + +type alias Texts = + { basics : Messages.Basics.Texts + , tagTable : Messages.Comp.TagTable.Texts + , tagForm : Messages.Comp.TagForm.Texts + , createNewTag : String + , newTag : String + , reallyDeleteTag : String + , deleteThisTag : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , tagTable = Messages.Comp.TagTable.gb + , tagForm = Messages.Comp.TagForm.gb + , createNewTag = "Create a new tag" + , newTag = "New Tag" + , reallyDeleteTag = "Really delete this tag?" + , deleteThisTag = "Delete this tag" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/TagSelect.elm b/modules/webapp/src/main/elm/Messages/Comp/TagSelect.elm new file mode 100644 index 00000000..ac790146 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/TagSelect.elm @@ -0,0 +1,16 @@ +module Messages.Comp.TagSelect exposing (..) + + +type alias Texts = + { hideEmpty : String + , showEmpty : String + , filterPlaceholder : String + } + + +gb : Texts +gb = + { hideEmpty = "Hide empty" + , showEmpty = "Show empty" + , filterPlaceholder = "Filter …" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/TagTable.elm b/modules/webapp/src/main/elm/Messages/Comp/TagTable.elm new file mode 100644 index 00000000..f60dbca3 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/TagTable.elm @@ -0,0 +1,16 @@ +module Messages.Comp.TagTable exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , category : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , category = "Category" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/UiSettingsForm.elm b/modules/webapp/src/main/elm/Messages/Comp/UiSettingsForm.elm new file mode 100644 index 00000000..50991728 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/UiSettingsForm.elm @@ -0,0 +1,116 @@ +module Messages.Comp.UiSettingsForm exposing (..) + +import Data.Color exposing (Color) +import Data.Fields exposing (Field) +import Messages.Data.Color +import Messages.Data.Fields + + +type alias Texts = + { general : String + , showSideMenuByDefault : String + , uiLanguage : String + , itemSearch : String + , maxResultsPerPageInfo : Int -> String + , maxResultsPerPage : String + , showBasicSearchStatsByDefault : String + , enablePowerSearch : String + , itemCards : String + , maxNoteSize : String + , maxNoteSizeInfo : Int -> String + , sizeOfItemPreview : String + , cardTitlePattern : String + , togglePatternHelpText : String + , cardSubtitlePattern : String + , searchMenu : String + , searchMenuTagCount : String + , searchMenuTagCountInfo : String + , searchMenuCatCount : String + , searchMenuCatCountInfo : String + , searchMenuFolderCount : String + , searchMenuFolderCountInfo : String + , itemDetail : String + , browserNativePdfView : String + , keyboardShortcutLabel : String + , tagCategoryColors : String + , colorLabel : Color -> String + , chooseTagColorLabel : String + , tagColorDescription : String + , fields : String + , fieldsInfo : String + , fieldLabel : Field -> String + , templateHelpMessage : String + } + + +gb : Texts +gb = + { general = "General" + , showSideMenuByDefault = "Show side menu by default" + , uiLanguage = "UI Language" + , itemSearch = "Item Search" + , maxResultsPerPageInfo = + \max -> + "Maximum results in one page when searching items. At most " + ++ String.fromInt max + ++ "." + , maxResultsPerPage = "Page size" + , showBasicSearchStatsByDefault = "Show basic search statistics by default" + , enablePowerSearch = "Enable power-user search bar" + , itemCards = "Item Cards" + , maxNoteSize = "Max. Note Length" + , maxNoteSizeInfo = + \max -> + "Maximum size of the item notes to display in card view. Between 0 - " + ++ String.fromInt max + ++ "." + , sizeOfItemPreview = "Size of item preview" + , cardTitlePattern = "Card Title Pattern" + , togglePatternHelpText = "Toggle pattern help text" + , cardSubtitlePattern = "Card Subtitle Pattern" + , searchMenu = "Search Menu" + , searchMenuTagCount = "Number of tags in search menu" + , searchMenuTagCountInfo = "How many tags to display in search menu at once. Others can be expanded. Use 0 to always show all." + , searchMenuCatCount = "Number of categories in search menu" + , searchMenuCatCountInfo = "How many categories to display in search menu at once. Others can be expanded. Use 0 to always show all." + , searchMenuFolderCount = "Number of folders in search menu" + , searchMenuFolderCountInfo = "How many folders to display in search menu at once. Other folders can be expanded. Use 0 to always show all." + , itemDetail = "Item Detail" + , browserNativePdfView = "Browser-native PDF preview" + , keyboardShortcutLabel = "Use keyboard shortcuts for navigation and confirm/unconfirm with open edit menu." + , tagCategoryColors = "Tag Category Colors" + , colorLabel = Messages.Data.Color.gb + , chooseTagColorLabel = "Choose color for tag categories" + , tagColorDescription = "Tags can be represented differently based on their category." + , fields = "Fields" + , fieldsInfo = "Choose which fields to display in search and edit menus." + , fieldLabel = Messages.Data.Fields.gb + , templateHelpMessage = + """ +A pattern allows to customize the title and subtitle of each card. +Variables expressions are enclosed in `{{` and `}}`, other text is +used as-is. The following variables are available: + +- `{{name}}` the item name +- `{{source}}` the source the item was created from +- `{{folder}}` the items folder +- `{{corrOrg}}` the correspondent organization +- `{{corrPerson}}` the correspondent person +- `{{correspondent}}` both organization and person separated by a comma +- `{{concPerson}}` the concerning person +- `{{concEquip}}` the concerning equipment +- `{{concerning}}` both person and equipment separated by a comma +- `{{fileCount}}` the number of attachments of this item +- `{{dateLong}}` the item date as full formatted date +- `{{dateShort}}` the item date as short formatted date (yyyy/mm/dd) +- `{{dueDateLong}}` the item due date as full formatted date +- `{{dueDateShort}}` the item due date as short formatted date (yyyy/mm/dd) +- `{{direction}}` the items direction values as string + +If some variable is not present, an empty string is rendered. You can +combine multiple variables with `|` to use the first non-empty one, +for example `{{corrOrg|corrPerson|-}}` would render the organization +and if that is not present the person. If both are absent a dash `-` +is rendered. +""" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/UiSettingsManage.elm b/modules/webapp/src/main/elm/Messages/Comp/UiSettingsManage.elm new file mode 100644 index 00000000..3b38bcbd --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/UiSettingsManage.elm @@ -0,0 +1,19 @@ +module Messages.Comp.UiSettingsManage exposing (..) + +import Messages.Basics +import Messages.Comp.UiSettingsForm + + +type alias Texts = + { basics : Messages.Basics.Texts + , uiSettingsForm : Messages.Comp.UiSettingsForm.Texts + , saveSettings : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , uiSettingsForm = Messages.Comp.UiSettingsForm.gb + , saveSettings = "Save settings" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/UserForm.elm b/modules/webapp/src/main/elm/Messages/Comp/UserForm.elm new file mode 100644 index 00000000..f533bcd8 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/UserForm.elm @@ -0,0 +1,18 @@ +module Messages.Comp.UserForm exposing (..) + + +type alias Texts = + { login : String + , state : String + , email : String + , password : String + } + + +gb : Texts +gb = + { login = "Login" + , state = "State" + , email = "E-Mail" + , password = "Password" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/UserManage.elm b/modules/webapp/src/main/elm/Messages/Comp/UserManage.elm new file mode 100644 index 00000000..19b927f5 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/UserManage.elm @@ -0,0 +1,39 @@ +module Messages.Comp.UserManage exposing (..) + +import Messages.Basics +import Messages.Comp.UserForm +import Messages.Comp.UserTable + + +type alias Texts = + { userTable : Messages.Comp.UserTable.Texts + , userForm : Messages.Comp.UserForm.Texts + , users : String + , newUser : String + , addNewUser : String + , reallyDeleteUser : String + , createNewUser : String + , basics : Messages.Basics.Texts + , deleteThisUser : String + , pleaseCorrectErrors : String + } + + +gb : Texts +gb = + { userTable = Messages.Comp.UserTable.gb + , userForm = Messages.Comp.UserForm.gb + , basics = Messages.Basics.gb + , users = "Users" + , newUser = "New user" + , addNewUser = "Add new user" + , reallyDeleteUser = "Really delete this user?" + , createNewUser = "Create new user" + , deleteThisUser = "Delete this user" + , pleaseCorrectErrors = "Please correct the errors in the form." + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Comp/UserTable.elm b/modules/webapp/src/main/elm/Messages/Comp/UserTable.elm new file mode 100644 index 00000000..c5729b50 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/UserTable.elm @@ -0,0 +1,24 @@ +module Messages.Comp.UserTable exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , login : String + , state : String + , email : String + , logins : String + , lastLogin : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , login = "Login" + , state = "State" + , email = "E-Mail" + , logins = "Logins" + , lastLogin = "Last Login" + } diff --git a/modules/webapp/src/main/elm/Messages/Data/Color.elm b/modules/webapp/src/main/elm/Messages/Data/Color.elm new file mode 100644 index 00000000..560e45fe --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/Color.elm @@ -0,0 +1,46 @@ +module Messages.Data.Color exposing (..) + +import Data.Color exposing (Color(..)) + + +gb : Color -> String +gb color = + case color of + Red -> + "Red" + + Orange -> + "Orange" + + Yellow -> + "Yellow" + + Olive -> + "Olive" + + Green -> + "Green" + + Teal -> + "Teal" + + Blue -> + "Blue" + + Violet -> + "Violet" + + Purple -> + "Purple" + + Pink -> + "Pink" + + Brown -> + "Brown" + + Grey -> + "Grey" + + Black -> + "Black" diff --git a/modules/webapp/src/main/elm/Messages/Data/ContactType.elm b/modules/webapp/src/main/elm/Messages/Data/ContactType.elm new file mode 100644 index 00000000..06056387 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/ContactType.elm @@ -0,0 +1,25 @@ +module Messages.Data.ContactType exposing (..) + +import Data.ContactType exposing (ContactType(..)) + + +gb : ContactType -> String +gb ct = + case ct of + Phone -> + "Phone" + + Mobile -> + "Mobile" + + Fax -> + "Fax" + + Email -> + "Email" + + Docspell -> + "Docspell" + + Website -> + "Website" diff --git a/modules/webapp/src/main/elm/Messages/Data/CustomFieldType.elm b/modules/webapp/src/main/elm/Messages/Data/CustomFieldType.elm new file mode 100644 index 00000000..39fba224 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/CustomFieldType.elm @@ -0,0 +1,22 @@ +module Messages.Data.CustomFieldType exposing (..) + +import Data.CustomFieldType exposing (CustomFieldType(..)) + + +gb : CustomFieldType -> String +gb ft = + case ft of + Text -> + "Text" + + Numeric -> + "Numeric" + + Date -> + "Date" + + Boolean -> + "Boolean" + + Money -> + "Money" diff --git a/modules/webapp/src/main/elm/Messages/Data/EquipmentUse.elm b/modules/webapp/src/main/elm/Messages/Data/EquipmentUse.elm new file mode 100644 index 00000000..bc3cbdca --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/EquipmentUse.elm @@ -0,0 +1,13 @@ +module Messages.Data.EquipmentUse exposing (..) + +import Data.EquipmentUse exposing (EquipmentUse(..)) + + +gb : EquipmentUse -> String +gb pu = + case pu of + Concerning -> + "Concerning" + + Disabled -> + "Disabled" diff --git a/modules/webapp/src/main/elm/Messages/Data/Fields.elm b/modules/webapp/src/main/elm/Messages/Data/Fields.elm new file mode 100644 index 00000000..f9b65e23 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/Fields.elm @@ -0,0 +1,43 @@ +module Messages.Data.Fields exposing (..) + +import Data.Fields exposing (Field(..)) + + +gb : Field -> String +gb field = + case field of + Tag -> + "Tag" + + Folder -> + "Folder" + + CorrOrg -> + "Correspondent Organization" + + CorrPerson -> + "Correspondent Person" + + ConcPerson -> + "Concerning Person" + + ConcEquip -> + "Concerned Equipment" + + Date -> + "Date" + + DueDate -> + "Due Date" + + Direction -> + "Direction" + + PreviewImage -> + "Preview Image" + + CustomFields -> + "Custom Fields" + + SourceName -> + "Item Source" diff --git a/modules/webapp/src/main/elm/Messages/Data/Language.elm b/modules/webapp/src/main/elm/Messages/Data/Language.elm new file mode 100644 index 00000000..3c21f593 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/Language.elm @@ -0,0 +1,52 @@ +module Messages.Data.Language exposing (..) + +import Data.Language exposing (Language(..)) + + +gb : Language -> String +gb lang = + case lang of + German -> + "German" + + English -> + "English" + + French -> + "French" + + Italian -> + "Italian" + + Spanish -> + "Spanish" + + Portuguese -> + "Portuguese" + + Czech -> + "Czech" + + Danish -> + "Danish" + + Finnish -> + "Finnish" + + Norwegian -> + "Norwegian" + + Swedish -> + "Swedish" + + Russian -> + "Russian" + + Romanian -> + "Romanian" + + Dutch -> + "Dutch" + + Latvian -> + "Latvian" diff --git a/modules/webapp/src/main/elm/Messages/Data/OrgUse.elm b/modules/webapp/src/main/elm/Messages/Data/OrgUse.elm new file mode 100644 index 00000000..b765b153 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/OrgUse.elm @@ -0,0 +1,13 @@ +module Messages.Data.OrgUse exposing (..) + +import Data.OrgUse exposing (OrgUse(..)) + + +gb : OrgUse -> String +gb pu = + case pu of + Correspondent -> + "Correspondent" + + Disabled -> + "Disabled" diff --git a/modules/webapp/src/main/elm/Messages/Data/PersonUse.elm b/modules/webapp/src/main/elm/Messages/Data/PersonUse.elm new file mode 100644 index 00000000..f1c46bf6 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/PersonUse.elm @@ -0,0 +1,19 @@ +module Messages.Data.PersonUse exposing (..) + +import Data.PersonUse exposing (PersonUse(..)) + + +gb : PersonUse -> String +gb pu = + case pu of + Correspondent -> + "Correspondent" + + Concerning -> + "Concerning" + + Both -> + "Both" + + Disabled -> + "Disabled" diff --git a/modules/webapp/src/main/elm/Messages/Data/SSLType.elm b/modules/webapp/src/main/elm/Messages/Data/SSLType.elm new file mode 100644 index 00000000..6e051ae0 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/SSLType.elm @@ -0,0 +1,16 @@ +module Messages.Data.SSLType exposing (..) + +import Data.SSLType exposing (SSLType(..)) + + +gb : SSLType -> String +gb st = + case st of + None -> + "None" + + SSL -> + "SSL/TLS" + + StartTLS -> + "StartTLS" diff --git a/modules/webapp/src/main/elm/Messages/Page/CollectiveSettings.elm b/modules/webapp/src/main/elm/Messages/Page/CollectiveSettings.elm new file mode 100644 index 00000000..0e254a9f --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/CollectiveSettings.elm @@ -0,0 +1,44 @@ +module Messages.Page.CollectiveSettings exposing (..) + +import Messages.Basics +import Messages.Comp.CollectiveSettingsForm +import Messages.Comp.SourceManage +import Messages.Comp.UserManage + + +type alias Texts = + { basics : Messages.Basics.Texts + , userManage : Messages.Comp.UserManage.Texts + , collectiveSettingsForm : Messages.Comp.CollectiveSettingsForm.Texts + , sourceManage : Messages.Comp.SourceManage.Texts + , collectiveSettings : String + , insights : String + , sources : String + , settings : String + , users : String + , user : String + , collective : String + , size : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , userManage = Messages.Comp.UserManage.gb + , collectiveSettingsForm = Messages.Comp.CollectiveSettingsForm.gb + , sourceManage = Messages.Comp.SourceManage.gb + , collectiveSettings = "Collective Settings" + , insights = "Insights" + , sources = "Sources" + , settings = "Settings" + , users = "Users" + , user = "User" + , collective = "Collective" + , size = "Size" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/Home.elm b/modules/webapp/src/main/elm/Messages/Page/Home.elm new file mode 100644 index 00000000..1299926d --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/Home.elm @@ -0,0 +1,58 @@ +module Messages.Page.Home exposing (..) + +import Messages.Basics +import Messages.Comp.ItemCardList +import Messages.Comp.SearchStatsView +import Messages.Page.HomeSideMenu + + +type alias Texts = + { basics : Messages.Basics.Texts + , itemCardList : Messages.Comp.ItemCardList.Texts + , searchStatsView : Messages.Comp.SearchStatsView.Texts + , sideMenu : Messages.Page.HomeSideMenu.Texts + , contentSearch : String + , searchInNames : String + , selectModeTitle : String + , fullHeightPreviewTitle : String + , fullWidthPreviewTitle : String + , powerSearchPlaceholder : String + , reallyReprocessQuestion : String + , reallyDeleteQuestion : String + , editSelectedItems : Int -> String + , reprocessSelectedItems : Int -> String + , deleteSelectedItems : Int -> String + , selectAllVisible : String + , selectNone : String + , resetSearchForm : String + , exitSelectMode : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , itemCardList = Messages.Comp.ItemCardList.gb + , searchStatsView = Messages.Comp.SearchStatsView.gb + , sideMenu = Messages.Page.HomeSideMenu.gb + , contentSearch = "Content search…" + , searchInNames = "Search in names…" + , selectModeTitle = "Select Mode" + , fullHeightPreviewTitle = "Full height preview" + , fullWidthPreviewTitle = "Full width preview" + , powerSearchPlaceholder = "Search query …" + , reallyReprocessQuestion = "Really reprocess all selected items? Metadata of unconfirmed items may change." + , reallyDeleteQuestion = "Really delete all selected items?" + , editSelectedItems = \n -> "Edit " ++ String.fromInt n ++ " selected items" + , reprocessSelectedItems = \n -> "Reprocess " ++ String.fromInt n ++ " selected items" + , deleteSelectedItems = \n -> "Delete " ++ String.fromInt n ++ " selected items" + , selectAllVisible = "Select all visible" + , selectNone = "Select none" + , resetSearchForm = "Reset search form" + , exitSelectMode = "Exit Select Mode" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/HomeSideMenu.elm b/modules/webapp/src/main/elm/Messages/Page/HomeSideMenu.elm new file mode 100644 index 00000000..6701a8cd --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/HomeSideMenu.elm @@ -0,0 +1,27 @@ +module Messages.Page.HomeSideMenu exposing (..) + +import Messages.Comp.ItemDetail.MultiEditMenu +import Messages.Comp.SearchMenu + + +type alias Texts = + { searchMenu : Messages.Comp.SearchMenu.Texts + , multiEdit : Messages.Comp.ItemDetail.MultiEditMenu.Texts + , editMode : String + , resetSearchForm : String + , multiEditHeader : String + , multiEditInfo : String + , close : String + } + + +gb : Texts +gb = + { searchMenu = Messages.Comp.SearchMenu.gb + , multiEdit = Messages.Comp.ItemDetail.MultiEditMenu.gb + , editMode = "Edit Mode" + , resetSearchForm = "Reset search form" + , multiEditHeader = "Multi-Edit" + , multiEditInfo = "Note that a change here immediatly affects all selected items on the right!" + , close = "Close" + } diff --git a/modules/webapp/src/main/elm/Messages/Page/ItemDetail.elm b/modules/webapp/src/main/elm/Messages/Page/ItemDetail.elm new file mode 100644 index 00000000..5bd48731 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/ItemDetail.elm @@ -0,0 +1,26 @@ +module Messages.Page.ItemDetail exposing (..) + +import Messages.Comp.ItemDetail +import Messages.Comp.ItemDetail.EditForm + + +type alias Texts = + { itemDetail : Messages.Comp.ItemDetail.Texts + , editForm : Messages.Comp.ItemDetail.EditForm.Texts + , editMetadata : String + , collapseExpand : String + } + + +gb : Texts +gb = + { itemDetail = Messages.Comp.ItemDetail.gb + , editForm = Messages.Comp.ItemDetail.EditForm.gb + , editMetadata = "Edit Metadata" + , collapseExpand = "Collapse/Expand" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/Login.elm b/modules/webapp/src/main/elm/Messages/Page/Login.elm new file mode 100644 index 00000000..00322cd9 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/Login.elm @@ -0,0 +1,52 @@ +module Messages.Page.Login exposing + ( Texts + , de + , gb + ) + + +type alias Texts = + { loginToDocspell : String + , username : String + , collectiveSlashLogin : String + , password : String + , rememberMe : String + , loginPlaceholder : String + , passwordPlaceholder : String + , loginButton : String + , loginSuccessful : String + , noAccount : String + , signupLink : String + } + + +gb : Texts +gb = + { loginToDocspell = "Login to Docspell" + , username = "Username" + , collectiveSlashLogin = "Collective / Login" + , password = "Password" + , rememberMe = "Remember Me" + , loginPlaceholder = "Login" + , passwordPlaceholder = "Password" + , loginButton = "Login" + , loginSuccessful = "Login successful" + , noAccount = "No account?" + , signupLink = "Sign up!" + } + + +de : Texts +de = + { loginToDocspell = "Docspell Anmeldung" + , username = "Benutzer" + , collectiveSlashLogin = "Kollektiv / Benutzer" + , password = "Passwort" + , rememberMe = "Anmeldung speichern" + , loginPlaceholder = "Benutzer" + , passwordPlaceholder = "Passwort" + , loginButton = "Anmelden" + , loginSuccessful = "Anmeldung erfolgreich" + , noAccount = "Kein Konto?" + , signupLink = "Hier registrieren!" + } diff --git a/modules/webapp/src/main/elm/Messages/Page/ManageData.elm b/modules/webapp/src/main/elm/Messages/Page/ManageData.elm new file mode 100644 index 00000000..93713e1f --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/ManageData.elm @@ -0,0 +1,39 @@ +module Messages.Page.ManageData exposing (..) + +import Messages.Basics +import Messages.Comp.CustomFieldManage +import Messages.Comp.EquipmentManage +import Messages.Comp.FolderManage +import Messages.Comp.OrgManage +import Messages.Comp.PersonManage +import Messages.Comp.TagManage + + +type alias Texts = + { basics : Messages.Basics.Texts + , tagManage : Messages.Comp.TagManage.Texts + , equipmentManage : Messages.Comp.EquipmentManage.Texts + , orgManage : Messages.Comp.OrgManage.Texts + , personManage : Messages.Comp.PersonManage.Texts + , folderManage : Messages.Comp.FolderManage.Texts + , customFieldManage : Messages.Comp.CustomFieldManage.Texts + , manageData : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , tagManage = Messages.Comp.TagManage.gb + , equipmentManage = Messages.Comp.EquipmentManage.gb + , orgManage = Messages.Comp.OrgManage.gb + , personManage = Messages.Comp.PersonManage.gb + , folderManage = Messages.Comp.FolderManage.gb + , customFieldManage = Messages.Comp.CustomFieldManage.gb + , manageData = "Manage Data" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/NewInvite.elm b/modules/webapp/src/main/elm/Messages/Page/NewInvite.elm new file mode 100644 index 00000000..0654c75b --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/NewInvite.elm @@ -0,0 +1,38 @@ +module Messages.Page.NewInvite exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , createNewInvitations : String + , invitationKey : String + , password : String + , reset : String + , inviteInfo : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , createNewInvitations = "Create new invitations" + , invitationKey = "Invitation Key" + , password = "Password" + , reset = "Reset" + , inviteInfo = + """Docspell requires an invite when signing up. You can + create these invites here and send them to friends so + they can signup with docspell. + + Each invite can only be used once. You'll need to + create one key for each person you want to invite. + + Creating an invite requires providing the password + from the configuration.""" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/Queue.elm b/modules/webapp/src/main/elm/Messages/Page/Queue.elm new file mode 100644 index 00000000..689eb045 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/Queue.elm @@ -0,0 +1,51 @@ +module Messages.Page.Queue exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , currentlyRunning : String + , queue : String + , waiting : String + , errored : String + , success : String + , noJobsRunning : String + , noJobsDisplay : String + , noJobsWaiting : String + , noJobsFailed : String + , noJobsSuccess : String + , deleteThisJob : String + , showLog : String + , remove : String + , retries : String + , changePriority : String + , prio : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , currentlyRunning = "Currently Running" + , queue = "Queue" + , waiting = "Waiting" + , errored = "Errored" + , success = "Success" + , noJobsRunning = "No jobs currently running." + , noJobsDisplay = "No jobs to display." + , noJobsWaiting = "No waiting jobs." + , noJobsFailed = "No failed jobs to display." + , noJobsSuccess = "No succesfull jobs to display." + , deleteThisJob = "Cancel/Delete this job?" + , showLog = "Show log" + , remove = "Remove" + , retries = "Retries" + , changePriority = "Change priority of this job" + , prio = "Prio" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/Register.elm b/modules/webapp/src/main/elm/Messages/Page/Register.elm new file mode 100644 index 00000000..ac6f3543 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/Register.elm @@ -0,0 +1,41 @@ +module Messages.Page.Register exposing (..) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , signupToDocspell : String + , collectiveId : String + , collective : String + , userLogin : String + , username : String + , password : String + , passwordRepeat : String + , invitationKey : String + , alreadySignedUp : String + , signIn : String + , registrationSuccessful : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , signupToDocspell = "Signup to Docspell" + , collectiveId = "Collective ID" + , collective = "Collective" + , userLogin = "User Login" + , username = "Username" + , password = "Password" + , passwordRepeat = "Password (repeat)" + , invitationKey = "Invitation Key" + , alreadySignedUp = "Already signed up?" + , signIn = "Sign in" + , registrationSuccessful = "Registration successful." + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/Upload.elm b/modules/webapp/src/main/elm/Messages/Page/Upload.elm new file mode 100644 index 00000000..8effba94 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/Upload.elm @@ -0,0 +1,66 @@ +module Messages.Page.Upload exposing (..) + +import Data.Language exposing (Language) +import Messages.Basics +import Messages.Comp.Dropzone +import Messages.Data.Language + + +type alias Texts = + { basics : Messages.Basics.Texts + , dropzone : Messages.Comp.Dropzone.Texts + , reset : String + , allFilesOneItem : String + , skipExistingFiles : String + , language : String + , languageInfo : String + , uploadErrorMessage : String + , successBox : + { allFilesUploaded : String + , line1 : String + , itemsPage : String + , line2 : String + , processingPage : String + , line3 : String + , resetLine1 : String + , reset : String + , resetLine2 : String + } + , selectedFiles : String + , languageLabel : Language -> String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , dropzone = Messages.Comp.Dropzone.gb + , reset = "Reset" + , allFilesOneItem = "All files are one single item" + , skipExistingFiles = "Skip files already present in docspell" + , language = "Language" + , languageInfo = + "Used for text extraction and analysis. The collective's " + ++ "default language is used if not specified here." + , uploadErrorMessage = "There were errors uploading some files." + , successBox = + { allFilesUploaded = "All files uploaded" + , line1 = + "Your files have been successfully uploaded. " + ++ "They are now being processed. Check the " + , itemsPage = "Items Page" + , line2 = " later where the files will arrive eventually. Or go to the " + , processingPage = "Processing Page" + , line3 = " to view the current processing state." + , resetLine1 = " Click " + , reset = "Reset" + , resetLine2 = " to upload more files." + } + , selectedFiles = "Selected Files" + , languageLabel = Messages.Data.Language.gb + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm b/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm new file mode 100644 index 00000000..4b44fc5a --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm @@ -0,0 +1,77 @@ +module Messages.Page.UserSettings exposing (..) + +import Messages.Comp.ChangePasswordForm +import Messages.Comp.EmailSettingsManage +import Messages.Comp.ImapSettingsManage +import Messages.Comp.NotificationManage +import Messages.Comp.ScanMailboxManage +import Messages.Comp.UiSettingsManage + + +type alias Texts = + { changePasswordForm : Messages.Comp.ChangePasswordForm.Texts + , uiSettingsManage : Messages.Comp.UiSettingsManage.Texts + , emailSettingsManage : Messages.Comp.EmailSettingsManage.Texts + , imapSettingsManage : Messages.Comp.ImapSettingsManage.Texts + , notificationManage : Messages.Comp.NotificationManage.Texts + , scanMailboxManage : Messages.Comp.ScanMailboxManage.Texts + , userSettings : String + , uiSettings : String + , notifications : String + , scanMailbox : String + , emailSettingSmtp : String + , emailSettingImap : String + , changePassword : String + , uiSettingsInfo : String + , notificationInfoText : String + , notificationRemindDaysInfo : String + , scanMailboxInfo1 : String + , scanMailboxInfo2 : String + } + + +gb : Texts +gb = + { changePasswordForm = Messages.Comp.ChangePasswordForm.gb + , uiSettingsManage = Messages.Comp.UiSettingsManage.gb + , emailSettingsManage = Messages.Comp.EmailSettingsManage.gb + , imapSettingsManage = Messages.Comp.ImapSettingsManage.gb + , notificationManage = Messages.Comp.NotificationManage.gb + , scanMailboxManage = Messages.Comp.ScanMailboxManage.gb + , userSettings = "User Settings" + , uiSettings = "UI Settings" + , notifications = "Notifications" + , scanMailbox = "Scan Mailbox" + , emailSettingSmtp = "E-Mail Settings (SMTP)" + , emailSettingImap = "E-Mail Settings (IMAP)" + , changePassword = "Change Password" + , uiSettingsInfo = + "These settings only affect the web ui. They are stored in the browser, " + ++ "so they are separated between browsers and devices." + , notificationInfoText = + """ + Docspell can notify you once the due dates of your items + come closer. Notification is done via e-mail. You need to + provide a connection in your e-mail settings.""" + , notificationRemindDaysInfo = + "Docspell finds all items that are due in *Remind Days* days and sends this list via e-mail." + , scanMailboxInfo1 = + "Docspell can scan folders of your mailbox to import your mails. " + ++ "You need to provide a connection in " + ++ "your e-mail (imap) settings." + , scanMailboxInfo2 = + """ + Docspell goes through all configured folders and imports + mails matching the search criteria. Mails are skipped if + they were imported in a previous run and the corresponding + items still exist. After submitting a mail into docspell, + you can choose to move it to another folder, to delete it + or to just leave it there. In the latter case you should + adjust the schedule to avoid reading over the same mails + again.""" + } + + +de : Texts +de = + gb diff --git a/modules/webapp/src/main/elm/Messages/UiLanguage.elm b/modules/webapp/src/main/elm/Messages/UiLanguage.elm new file mode 100644 index 00000000..57446cec --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/UiLanguage.elm @@ -0,0 +1,19 @@ +module Messages.UiLanguage exposing + ( UiLanguage(..) + , all + ) + +{-| This module defines the languages supported in the web app. +-} + + +type UiLanguage + = English + | German + + +all : List UiLanguage +all = + [ English + , German + ] diff --git a/modules/webapp/src/main/elm/Page/CollectiveSettings/View2.elm b/modules/webapp/src/main/elm/Page/CollectiveSettings/View2.elm index 7a7ac428..54fecf9c 100644 --- a/modules/webapp/src/main/elm/Page/CollectiveSettings/View2.elm +++ b/modules/webapp/src/main/elm/Page/CollectiveSettings/View2.elm @@ -11,14 +11,15 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Page.CollectiveSettings exposing (Texts) import Page.CollectiveSettings.Data exposing (..) import Styles as S import Util.Maybe import Util.Size -viewSidebar : Bool -> Flags -> UiSettings -> Model -> Html Msg -viewSidebar visible _ _ model = +viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg +viewSidebar texts visible _ _ model = div [ id "sidebar" , class S.sidebar @@ -27,7 +28,7 @@ viewSidebar visible _ _ model = ] [ div [ class "" ] [ h1 [ class S.header1 ] - [ text "Collective Settings" + [ text texts.collectiveSettings ] ] , div [ class "flex flex-col my-2" ] @@ -40,7 +41,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-chart-bar" ] [] , span [ class "ml-3" ] - [ text "Insights" ] + [ text texts.insights ] ] , a [ href "#" @@ -51,7 +52,7 @@ viewSidebar visible _ _ model = [ Icons.sourceIcon2 "" , span [ class "ml-3" ] - [ text "Sources" ] + [ text texts.sources ] ] , a [ href "#" @@ -62,7 +63,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-cog" ] [] , span [ class "ml-3" ] - [ text "Settings" ] + [ text texts.settings ] ] , a [ href "#" @@ -73,30 +74,30 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-user" ] [] , span [ class "ml-3" ] - [ text "Users" ] + [ text texts.users ] ] ] ] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent flags settings model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts flags settings model = div [ id "content" , class S.content ] (case model.currentTab of Just UserTab -> - viewUsers settings model + viewUsers texts settings model Just SettingsTab -> - viewSettings flags settings model + viewSettings texts flags settings model Just InsightsTab -> - viewInsights flags model + viewInsights texts flags model Just SourceTab -> - viewSources flags settings model + viewSources texts flags settings model Nothing -> [] @@ -116,8 +117,8 @@ menuEntryActive model tab = class "" -viewInsights : Flags -> Model -> List (Html Msg) -viewInsights flags model = +viewInsights : Texts -> Flags -> Model -> List (Html Msg) +viewInsights texts flags model = let ( coll, user ) = Maybe.map (\a -> ( a.collective, a.user )) flags.account @@ -126,7 +127,7 @@ viewInsights flags model = [ h1 [ class S.header1 ] [ i [ class "fa fa-chart-bar font-thin" ] [] , span [ class "ml-2" ] - [ text "Insights" + [ text texts.insights ] ] , div [ class "mb-4" ] @@ -136,7 +137,7 @@ viewInsights flags model = [ div [ class "flex flex-row space-x-6" ] [ div [ class "" - , title "Collective" + , title texts.collective ] [ i [ class "fa fa-users" ] [] , span [ class "ml-2" ] @@ -145,7 +146,7 @@ viewInsights flags model = ] , div [ class "" - , title "User" + , title texts.user ] [ i [ class "fa fa-user font-thin" ] [] , span [ class "ml-2" ] @@ -161,26 +162,26 @@ viewInsights flags model = [ text "Items" ] , div [ class "flex px-4 flex-wrap" ] - [ stats (String.fromInt (model.insights.incomingCount + model.insights.outgoingCount)) "Items" - , stats (String.fromInt model.insights.incomingCount) "Incoming" - , stats (String.fromInt model.insights.outgoingCount) "Outgoing" + [ stats (String.fromInt (model.insights.incomingCount + model.insights.outgoingCount)) texts.basics.items + , stats (String.fromInt model.insights.incomingCount) texts.basics.incoming + , stats (String.fromInt model.insights.outgoingCount) texts.basics.outgoing ] ] , div [ class "py-2" ] [ h4 [ class S.header3 ] - [ text "Size" + [ text texts.size ] , div [ class "flex px-4 flex-wrap" ] - [ stats (toFloat model.insights.itemSize |> Util.Size.bytesReadable Util.Size.B) "Size" + [ stats (toFloat model.insights.itemSize |> Util.Size.bytesReadable Util.Size.B) texts.size ] ] , div [ class "py-2" ] [ h4 [ class S.header3 ] - [ text "Tags" + [ text texts.basics.tags ] , div [ class "flex px-4 flex-wrap" ] (List.map makeTagStats @@ -207,54 +208,66 @@ makeTagStats nc = stats (String.fromInt nc.count) nc.tag.name -viewSources : Flags -> UiSettings -> Model -> List (Html Msg) -viewSources flags settings model = +viewSources : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewSources texts flags settings model = [ h1 [ class S.header1 , class "inline-flex items-center" ] [ Icons.sourceIcon2 "" , div [ class "ml-3" ] - [ text "Sources" + [ text texts.sources ] ] - , Html.map SourceMsg (Comp.SourceManage.view2 flags settings model.sourceModel) + , Html.map SourceMsg (Comp.SourceManage.view2 texts.sourceManage flags settings model.sourceModel) ] -viewUsers : UiSettings -> Model -> List (Html Msg) -viewUsers settings model = +viewUsers : Texts -> UiSettings -> Model -> List (Html Msg) +viewUsers texts settings model = [ h1 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-user" ] [] , div [ class "ml-3" ] - [ text "Users" + [ text texts.users ] ] - , Html.map UserMsg (Comp.UserManage.view2 settings model.userModel) + , Html.map UserMsg (Comp.UserManage.view2 texts.userManage settings model.userModel) ] -viewSettings : Flags -> UiSettings -> Model -> List (Html Msg) -viewSettings flags settings model = +viewSettings : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewSettings texts flags settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-cog" ] [] , span [ class "ml-3" ] - [ text "Collective Settings" + [ text texts.collectiveSettings ] ] , Html.map SettingsFormMsg - (Comp.CollectiveSettingsForm.view2 flags settings model.settingsModel) + (Comp.CollectiveSettingsForm.view2 + flags + texts.collectiveSettingsForm + settings + model.settingsModel + ) , div [ classList [ ( "hidden", Util.Maybe.isEmpty model.submitResult ) - , ( S.successMessage, Maybe.map .success model.submitResult |> Maybe.withDefault False ) - , ( S.errorMessage, Maybe.map .success model.submitResult |> Maybe.map not |> Maybe.withDefault False ) + , ( S.successMessage + , Maybe.map .success model.submitResult + |> Maybe.withDefault False + ) + , ( S.errorMessage + , Maybe.map .success model.submitResult + |> Maybe.map not + |> Maybe.withDefault False + ) ] , class "mt-2" ] diff --git a/modules/webapp/src/main/elm/Page/Home/Data.elm b/modules/webapp/src/main/elm/Page/Home/Data.elm index 6112de60..2190afb7 100644 --- a/modules/webapp/src/main/elm/Page/Home/Data.elm +++ b/modules/webapp/src/main/elm/Page/Home/Data.elm @@ -1,5 +1,6 @@ module Page.Home.Data exposing - ( Model + ( ConfirmModalValue(..) + , Model , Msg(..) , SearchParam , SearchType(..) @@ -13,7 +14,6 @@ module Page.Home.Data exposing , itemNav , menuCollapsed , resultsBelowLimit - , searchTypeString , selectActive ) @@ -22,15 +22,12 @@ import Api.Model.BasicResult exposing (BasicResult) import Api.Model.ItemLightList exposing (ItemLightList) import Api.Model.SearchStats exposing (SearchStats) import Browser.Dom as Dom -import Comp.ConfirmModal -import Comp.FixedDropdown import Comp.ItemCardList import Comp.ItemDetail.FormChange exposing (FormChange) import Comp.ItemDetail.MultiEditMenu exposing (SaveNameState(..)) import Comp.LinkTarget exposing (LinkTarget) import Comp.PowerSearchInput import Comp.SearchMenu -import Comp.YesNoDimmer import Data.Flags exposing (Flags) import Data.ItemNav exposing (ItemNav) import Data.ItemQuery as Q @@ -52,7 +49,6 @@ type alias Model = , moreAvailable : Bool , moreInProgress : Bool , throttle : Throttle Msg - , searchTypeDropdown : Comp.FixedDropdown.Model SearchType , searchTypeDropdownValue : SearchType , lastSearchType : SearchType , dragDropData : DD.DragDropData @@ -62,10 +58,15 @@ type alias Model = } +type ConfirmModalValue + = ConfirmReprocessItems + | ConfirmDelete + + type alias SelectViewModel = { ids : Set String , action : SelectActionMode - , confirmModal : Maybe (Comp.ConfirmModal.Settings Msg) + , confirmModal : Maybe ConfirmModalValue , editModel : Comp.ItemDetail.MultiEditMenu.Model , saveNameState : SaveNameState , saveCustomFieldState : Set String @@ -94,13 +95,6 @@ init flags viewMode = let searchMenuModel = Comp.SearchMenu.init flags - - searchTypeOptions = - if flags.config.fullTextSearchEnabled then - [ BasicSearch, ContentOnlySearch ] - - else - [ BasicSearch ] in { searchMenuModel = searchMenuModel , itemListModel = Comp.ItemCardList.init @@ -109,9 +103,6 @@ init flags viewMode = , moreAvailable = True , moreInProgress = False , throttle = Throttle.create 1 - , searchTypeDropdown = - Comp.FixedDropdown.initMap searchTypeString - searchTypeOptions , searchTypeDropdownValue = if Comp.SearchMenu.isFulltextSearch searchMenuModel then ContentOnlySearch @@ -180,7 +171,6 @@ type Msg | LoadMore | UpdateThrottle | SetBasicSearch String - | SearchTypeMsg (Comp.FixedDropdown.Msg SearchType) | ToggleSearchType | KeyUpSearchbarMsg (Maybe KeyCode) | ScrollResult (Result Dom.Error ()) @@ -226,16 +216,6 @@ type alias SearchParam = } -searchTypeString : SearchType -> String -searchTypeString st = - case st of - BasicSearch -> - "Names" - - ContentOnlySearch -> - "Contents" - - itemNav : String -> Model -> ItemNav itemNav id model = Data.ItemNav.fromList model.itemListModel.results id diff --git a/modules/webapp/src/main/elm/Page/Home/SideMenu.elm b/modules/webapp/src/main/elm/Page/Home/SideMenu.elm index 7875e48f..79433f0a 100644 --- a/modules/webapp/src/main/elm/Page/Home/SideMenu.elm +++ b/modules/webapp/src/main/elm/Page/Home/SideMenu.elm @@ -9,13 +9,14 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Page.HomeSideMenu exposing (Texts) import Page.Home.Data exposing (..) import Set import Styles as S -view : Flags -> UiSettings -> Model -> Html Msg -view flags settings model = +view : Texts -> Flags -> UiSettings -> Model -> Html Msg +view texts flags settings model = div [ class "flex flex-col" ] @@ -25,7 +26,7 @@ view flags settings model = { tagger = ToggleSelectView , label = "" , icon = Just "fa fa-tasks" - , title = "Edit Mode" + , title = texts.editMode , inputClass = [ ( S.secondaryBasicButton, True ) , ( "bg-gray-200 dark:bg-bluegray-600", selectActive model ) @@ -35,7 +36,7 @@ view flags settings model = { tagger = ResetSearch , label = "" , icon = Just "fa fa-sync" - , title = "Reset search form" + , title = texts.resetSearchForm , inputClass = [ ( S.secondaryBasicButton, True ) ] } ] @@ -47,19 +48,19 @@ view flags settings model = SelectView svm -> case svm.action of EditSelected -> - viewEditMenu svm settings + viewEditMenu texts flags svm settings _ -> - viewSearch flags settings model + viewSearch texts flags settings model _ -> - viewSearch flags settings model + viewSearch texts flags settings model ) ] -viewSearch : Flags -> UiSettings -> Model -> List (Html Msg) -viewSearch flags settings model = +viewSearch : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewSearch texts flags settings model = [ MB.viewSide { start = [ MB.CustomElement <| @@ -75,7 +76,8 @@ viewSearch flags settings model = , rootClasses = "my-1 text-xs hidden sm:flex" } , Html.map SearchMenuMsg - (Comp.SearchMenu.viewDrop2 model.dragDropData + (Comp.SearchMenu.viewDrop2 texts.searchMenu + model.dragDropData flags settings model.searchMenuModel @@ -83,8 +85,8 @@ viewSearch flags settings model = ] -viewEditMenu : SelectViewModel -> UiSettings -> List (Html Msg) -viewEditMenu svm settings = +viewEditMenu : Texts -> Flags -> SelectViewModel -> UiSettings -> List (Html Msg) +viewEditMenu texts flags svm settings = let cfg_ = Comp.ItemDetail.MultiEditMenu.defaultViewConfig @@ -104,17 +106,17 @@ viewEditMenu svm settings = [ div [ class S.header2 ] [ i [ class "fa fa-edit" ] [] , span [ class "ml-2" ] - [ text "Multi-Edit" + [ text texts.multiEditHeader ] ] , div [ class S.infoMessage ] - [ text "Note that a change here immediatly affects all selected items on the right!" + [ text texts.multiEditInfo ] , MB.viewSide { start = [ MB.CustomElement <| B.secondaryButton - { label = "Close" + { label = texts.close , disabled = False , icon = "fa fa-times" , handler = onClick ToggleSelectView @@ -127,5 +129,11 @@ viewEditMenu svm settings = , rootClasses = "mt-2 text-sm" } , Html.map EditMenuMsg - (Comp.ItemDetail.MultiEditMenu.view2 cfg settings svm.editModel) + (Comp.ItemDetail.MultiEditMenu.view2 + texts.multiEdit + flags + cfg + settings + svm.editModel + ) ] diff --git a/modules/webapp/src/main/elm/Page/Home/Update.elm b/modules/webapp/src/main/elm/Page/Home/Update.elm index 04ad7529..97abd815 100644 --- a/modules/webapp/src/main/elm/Page/Home/Update.elm +++ b/modules/webapp/src/main/elm/Page/Home/Update.elm @@ -3,8 +3,6 @@ module Page.Home.Update exposing (update) import Api import Api.Model.ItemLightList exposing (ItemLightList) import Browser.Navigation as Nav -import Comp.ConfirmModal -import Comp.FixedDropdown import Comp.ItemCardList import Comp.ItemDetail.FormChange exposing (FormChange(..)) import Comp.ItemDetail.MultiEditMenu exposing (SaveNameState(..)) @@ -27,7 +25,6 @@ import Throttle import Time import Util.Html exposing (KeyCode(..)) import Util.ItemDragDrop as DD -import Util.Maybe import Util.Update @@ -277,38 +274,6 @@ update mId key flags settings msg model = ContentOnlySearch -> update mId key flags settings (SearchMenuMsg Comp.SearchMenu.SetNamesSearch) model - SearchTypeMsg lm -> - let - ( sm, mv ) = - Comp.FixedDropdown.update lm model.searchTypeDropdown - - mvChange = - Util.Maybe.filter (\a -> a /= model.searchTypeDropdownValue) mv - - m0 = - { model - | searchTypeDropdown = sm - , searchTypeDropdownValue = Maybe.withDefault model.searchTypeDropdownValue mv - } - - next = - case mvChange of - Just BasicSearch -> - Just Comp.SearchMenu.SetNamesSearch - - Just ContentOnlySearch -> - Just Comp.SearchMenu.SetFulltextSearch - - _ -> - Nothing - in - case next of - Just lm_ -> - update mId key flags settings (SearchMenuMsg lm_) m0 - - Nothing -> - withSub ( m0, Cmd.none ) - KeyUpSearchbarMsg (Just Enter) -> update mId key flags settings (DoSearch model.searchTypeDropdownValue) model @@ -410,19 +375,13 @@ update mId key flags settings msg model = else let - lmsg = - Comp.ConfirmModal.defaultSettings - ReprocessSelectedConfirmed - CloseConfirmModal - "Really reprocess all selected items? Metadata of unconfirmed items may change." - model_ = { model | viewMode = SelectView { svm | action = ReprocessSelected - , confirmModal = Just lmsg + , confirmModal = Just ConfirmReprocessItems } } in @@ -478,19 +437,13 @@ update mId key flags settings msg model = else let - lmsg = - Comp.ConfirmModal.defaultSettings - DeleteSelectedConfirmed - CloseConfirmModal - "Really delete all selected items?" - model_ = { model | viewMode = SelectView { svm | action = DeleteSelected - , confirmModal = Just lmsg + , confirmModal = Just ConfirmDelete } } in diff --git a/modules/webapp/src/main/elm/Page/Home/View2.elm b/modules/webapp/src/main/elm/Page/Home/View2.elm index 15602b8a..e31f5545 100644 --- a/modules/webapp/src/main/elm/Page/Home/View2.elm +++ b/modules/webapp/src/main/elm/Page/Home/View2.elm @@ -13,6 +13,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput) +import Messages.Page.Home exposing (Texts) import Page exposing (Page(..)) import Page.Home.Data exposing (..) import Page.Home.SideMenu @@ -21,28 +22,28 @@ import Styles as S import Util.Html -viewSidebar : Bool -> Flags -> UiSettings -> Model -> Html Msg -viewSidebar visible flags settings model = +viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg +viewSidebar texts visible flags settings model = div [ id "sidebar" , class S.sidebar , class S.sidebarBg , classList [ ( "hidden", not visible ) ] ] - [ Page.Home.SideMenu.view flags settings model + [ Page.Home.SideMenu.view texts.sideMenu flags settings model ] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent flags settings model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts flags settings model = div [ id "item-card-list" -- this id is used in scroll-to-card , class S.content ] - (searchStats flags settings model - ++ itemsBar flags settings model - ++ itemCardList flags settings model - ++ deleteSelectedDimmer model + (searchStats texts flags settings model + ++ itemsBar texts flags settings model + ++ itemCardList texts flags settings model + ++ confirmModal texts model ) @@ -50,13 +51,32 @@ viewContent flags settings model = --- Helpers -deleteSelectedDimmer : Model -> List (Html Msg) -deleteSelectedDimmer model = +confirmModal : Texts -> Model -> List (Html Msg) +confirmModal texts model = + let + settings modalValue = + case modalValue of + ConfirmReprocessItems -> + Comp.ConfirmModal.defaultSettings + ReprocessSelectedConfirmed + CloseConfirmModal + texts.basics.yes + texts.basics.no + texts.reallyReprocessQuestion + + ConfirmDelete -> + Comp.ConfirmModal.defaultSettings + DeleteSelectedConfirmed + CloseConfirmModal + texts.basics.yes + texts.basics.no + texts.reallyDeleteQuestion + in case model.viewMode of SelectView svm -> case svm.confirmModal of Just confirm -> - [ Comp.ConfirmModal.view confirm + [ Comp.ConfirmModal.view (settings confirm) ] Nothing -> @@ -66,21 +86,21 @@ deleteSelectedDimmer model = [] -itemsBar : Flags -> UiSettings -> Model -> List (Html Msg) -itemsBar flags settings model = +itemsBar : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +itemsBar texts flags settings model = case model.viewMode of SimpleView -> - [ defaultMenuBar flags settings model ] + [ defaultMenuBar texts flags settings model ] SearchView -> - [ defaultMenuBar flags settings model ] + [ defaultMenuBar texts flags settings model ] SelectView svm -> - [ editMenuBar model svm ] + [ editMenuBar texts model svm ] -defaultMenuBar : Flags -> UiSettings -> Model -> Html Msg -defaultMenuBar _ settings model = +defaultMenuBar : Texts -> Flags -> UiSettings -> Model -> Html Msg +defaultMenuBar texts _ settings model = let btnStyle = S.secondaryBasicButton ++ " text-sm" @@ -97,10 +117,10 @@ defaultMenuBar _ settings model = , placeholder (case model.searchTypeDropdownValue of ContentOnlySearch -> - "Content search…" + texts.contentSearch BasicSearch -> - "Search in names…" + texts.searchInNames ) , onInput SetBasicSearch , Util.Html.onKeyUpCode KeyUpSearchbarMsg @@ -124,7 +144,10 @@ defaultMenuBar _ settings model = div [ class "relative flex flex-grow flex-row" ] [ Html.map PowerSearchMsg - (Comp.PowerSearchInput.viewInput [] + (Comp.PowerSearchInput.viewInput + { placeholder = texts.powerSearchPlaceholder + , extraAttrs = [] + } model.powerSearchInput ) , Html.map PowerSearchMsg @@ -150,7 +173,7 @@ defaultMenuBar _ settings model = { tagger = ToggleSelectView , label = "" , icon = Just "fa fa-tasks" - , title = "Select Mode" + , title = texts.selectModeTitle , inputClass = [ ( btnStyle, True ) , ( "bg-gray-200 dark:bg-bluegray-600", selectActive model ) @@ -170,10 +193,10 @@ defaultMenuBar _ settings model = , icon = Just "fa fa-expand" , title = if settings.cardPreviewFullWidth then - "Full height preview" + texts.fullHeightPreviewTitle else - "Full width preview" + texts.fullHeightPreviewTitle , inputClass = [ ( btnStyle, True ) , ( "hidden sm:inline-block", False ) @@ -185,11 +208,11 @@ defaultMenuBar _ settings model = } -editMenuBar : Model -> SelectViewModel -> Html Msg -editMenuBar model svm = +editMenuBar : Texts -> Model -> SelectViewModel -> Html Msg +editMenuBar texts model svm = let selectCount = - Set.size svm.ids |> String.fromInt + Set.size svm.ids btnStyle = S.secondaryBasicButton ++ " text-sm" @@ -200,7 +223,7 @@ editMenuBar model svm = { tagger = EditSelectedItems , label = "" , icon = Just "fa fa-edit" - , title = "Edit " ++ selectCount ++ " selected items" + , title = texts.editSelectedItems selectCount , inputClass = [ ( btnStyle, True ) , ( "bg-gray-200 dark:bg-bluegray-600", svm.action == EditSelected ) @@ -210,7 +233,7 @@ editMenuBar model svm = { tagger = RequestReprocessSelected , label = "" , icon = Just "fa fa-redo" - , title = "Reprocess " ++ selectCount ++ " selected items" + , title = texts.reprocessSelectedItems selectCount , inputClass = [ ( btnStyle, True ) , ( "bg-gray-200 dark:bg-bluegray-600", svm.action == ReprocessSelected ) @@ -220,7 +243,7 @@ editMenuBar model svm = { tagger = RequestDeleteSelected , label = "" , icon = Just "fa fa-trash" - , title = "Delete " ++ selectCount ++ " selected items" + , title = texts.deleteSelectedItems selectCount , inputClass = [ ( btnStyle, True ) , ( "bg-gray-200 dark:bg-bluegray-600", svm.action == DeleteSelected ) @@ -232,7 +255,7 @@ editMenuBar model svm = { tagger = SelectAllItems , label = "" , icon = Just "fa fa-check-square font-thin" - , title = "Select all visible" + , title = texts.selectAllVisible , inputClass = [ ( btnStyle, True ) ] @@ -241,21 +264,21 @@ editMenuBar model svm = { tagger = SelectNoItems , label = "" , icon = Just "fa fa-square font-thin" - , title = "Select none" + , title = texts.selectNone , inputClass = [ ( btnStyle, True ) ] } , MB.TextLabel { icon = "" - , label = selectCount + , label = String.fromInt selectCount , class = "px-4 py-2 w-10 rounded-full font-bold bg-blue-100 dark:bg-lightblue-600 " } , MB.CustomButton { tagger = ResetSearch , label = "" , icon = Just "fa fa-sync" - , title = "Reset search form" + , title = texts.resetSearchForm , inputClass = [ ( btnStyle, True ) , ( "hidden sm:block", True ) @@ -265,7 +288,7 @@ editMenuBar model svm = { tagger = ToggleSelectView , label = "" , icon = Just "fa fa-tasks" - , title = "Exit Select Mode" + , title = texts.exitSelectMode , inputClass = [ ( btnStyle, True ) , ( "bg-gray-200 dark:bg-bluegray-600", selectActive model ) @@ -276,18 +299,18 @@ editMenuBar model svm = } -searchStats : Flags -> UiSettings -> Model -> List (Html Msg) -searchStats _ settings model = +searchStats : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +searchStats texts _ settings model = if settings.searchStatsVisible then - [ Comp.SearchStatsView.view2 "my-2" model.searchStats + [ Comp.SearchStatsView.view2 texts.searchStatsView "my-2" model.searchStats ] else [] -itemCardList : Flags -> UiSettings -> Model -> List (Html Msg) -itemCardList _ settings model = +itemCardList : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +itemCardList texts _ settings model = let itemViewCfg = case model.viewMode of @@ -302,7 +325,11 @@ itemCardList _ settings model = Data.ItemSelection.Inactive in [ Html.map ItemCardListMsg - (Comp.ItemCardList.view2 itemViewCfg settings model.itemListModel) + (Comp.ItemCardList.view2 texts.itemCardList + itemViewCfg + settings + model.itemListModel + ) , loadMore settings model ] diff --git a/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm b/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm index 7ac8b9fe..17c61fe6 100644 --- a/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm +++ b/modules/webapp/src/main/elm/Page/ItemDetail/View2.elm @@ -11,12 +11,13 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Page.ItemDetail exposing (Texts) import Page.ItemDetail.Data exposing (..) import Styles as S -viewSidebar : Bool -> Flags -> UiSettings -> Model -> Html Msg -viewSidebar visible _ settings model = +viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg +viewSidebar texts visible flags settings model = div [ id "sidebar" , class S.sidebar @@ -28,7 +29,7 @@ viewSidebar visible _ settings model = , class "font-bold mt-2" ] [ i [ class "fa fa-pencil-alt mr-2" ] [] - , text "Edit Metadata" + , text texts.editMetadata ] , MB.viewSide { start = @@ -39,7 +40,7 @@ viewSidebar visible _ settings model = , disabled = model.detail.item.state == "created" , handler = onClick (ItemDetailMsg Comp.ItemDetail.Model.ToggleOpenAllAkkordionTabs) , attrs = - [ title "Collapse/Expand" + [ title texts.collapseExpand , href "#" ] } @@ -48,16 +49,16 @@ viewSidebar visible _ settings model = , rootClasses = "text-sm mb-3 " } , Html.map ItemDetailMsg - (Comp.ItemDetail.EditForm.view2 settings model.detail) + (Comp.ItemDetail.EditForm.view2 texts.editForm flags settings model.detail) ] -viewContent : ItemNav -> Flags -> UiSettings -> Model -> Html Msg -viewContent inav _ settings model = +viewContent : Texts -> ItemNav -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts inav _ settings model = div [ id "content" , class S.content ] [ Html.map ItemDetailMsg - (Comp.ItemDetail.view2 inav settings model.detail) + (Comp.ItemDetail.view2 texts.itemDetail inav settings model.detail) ] diff --git a/modules/webapp/src/main/elm/Page/Login/View2.elm b/modules/webapp/src/main/elm/Page/Login/View2.elm index 9f5e8695..c3a2d972 100644 --- a/modules/webapp/src/main/elm/Page/Login/View2.elm +++ b/modules/webapp/src/main/elm/Page/Login/View2.elm @@ -6,6 +6,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onInput, onSubmit) +import Messages.Page.Login exposing (Texts) import Page exposing (Page(..)) import Page.Login.Data exposing (..) import Styles as S @@ -20,8 +21,8 @@ viewSidebar _ _ _ _ = [] -viewContent : Flags -> VersionInfo -> UiSettings -> Model -> Html Msg -viewContent flags versionInfo _ model = +viewContent : Texts -> Flags -> VersionInfo -> UiSettings -> Model -> Html Msg +viewContent texts flags versionInfo _ model = div [ id "content" , class "h-full flex flex-col items-center justify-center w-full" @@ -36,7 +37,7 @@ viewContent flags versionInfo _ model = [] ] , div [ class "font-medium self-center text-xl sm:text-2xl" ] - [ text "Login to Docspell" + [ text texts.loginToDocspell ] , Html.form [ action "#" @@ -48,7 +49,7 @@ viewContent flags versionInfo _ model = [ for "username" , class S.inputLabel ] - [ text "Username" + [ text texts.username ] , div [ class "relative" ] [ div [ class S.inputIcon ] @@ -62,7 +63,7 @@ viewContent flags versionInfo _ model = , value model.username , autofocus True , class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput) - , placeholder "Collective / Login" + , placeholder texts.collectiveSlashLogin ] [] ] @@ -72,7 +73,7 @@ viewContent flags versionInfo _ model = [ for "password" , class S.inputLabel ] - [ text "Password" + [ text texts.password ] , div [ class "relative" ] [ div [ class S.inputIcon ] @@ -85,7 +86,7 @@ viewContent flags versionInfo _ model = , onInput SetPassword , value model.password , class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput) - , placeholder "Password" + , placeholder texts.password ] [] ] @@ -107,7 +108,7 @@ viewContent flags versionInfo _ model = , span [ class "mb-1 ml-2 text-xs sm:text-sm tracking-wide my-1" ] - [ text "Remember Me" + [ text texts.rememberMe ] ] ] @@ -116,23 +117,23 @@ viewContent flags versionInfo _ model = [ type_ "submit" , class S.primaryButton ] - [ text "Login" + [ text texts.loginButton ] ] - , resultMessage model + , resultMessage texts model , div [ class "flex justify-end text-sm pt-4" , classList [ ( "hidden", flags.config.signupMode == "closed" ) ] ] [ span [] - [ text "No account?" + [ text texts.noAccount ] , a [ Page.href RegisterPage , class ("ml-2" ++ S.link) ] [ i [ class "fa fa-user-plus mr-1" ] [] - , text "Sign up" + , text texts.signupLink ] ] ] @@ -155,13 +156,13 @@ viewContent flags versionInfo _ model = ] -resultMessage : Model -> Html Msg -resultMessage model = +resultMessage : Texts -> Model -> Html Msg +resultMessage texts model = case model.result of Just r -> if r.success then div [ class ("my-2" ++ S.successMessage) ] - [ text "Login successful." + [ text texts.loginSuccessful ] else diff --git a/modules/webapp/src/main/elm/Page/ManageData/View2.elm b/modules/webapp/src/main/elm/Page/ManageData/View2.elm index aee4d244..70ec2102 100644 --- a/modules/webapp/src/main/elm/Page/ManageData/View2.elm +++ b/modules/webapp/src/main/elm/Page/ManageData/View2.elm @@ -13,12 +13,13 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Page.ManageData exposing (Texts) import Page.ManageData.Data exposing (..) import Styles as S -viewSidebar : Bool -> Flags -> UiSettings -> Model -> Html Msg -viewSidebar visible _ settings model = +viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg +viewSidebar texts visible _ settings model = div [ id "sidebar" , class S.sidebar @@ -27,7 +28,7 @@ viewSidebar visible _ settings model = ] [ div [ class "" ] [ h1 [ class S.header1 ] - [ text "Manage Data" + [ text texts.manageData ] ] , div [ class "flex flex-col my-2" ] @@ -40,7 +41,8 @@ viewSidebar visible _ settings model = [ Icons.tagIcon2 "" , span [ class "ml-3" ] - [ text "Tags" ] + [ text texts.basics.tags + ] ] , a [ href "#" @@ -51,7 +53,8 @@ viewSidebar visible _ settings model = [ Icons.equipmentIcon2 "" , span [ class "ml-3" ] - [ text "Equipment" ] + [ text texts.basics.equipment + ] ] , a [ href "#" @@ -62,7 +65,8 @@ viewSidebar visible _ settings model = [ Icons.organizationIcon2 "" , span [ class "ml-3" ] - [ text "Organization" ] + [ text texts.basics.organization + ] ] , a [ href "#" @@ -73,7 +77,8 @@ viewSidebar visible _ settings model = [ Icons.personIcon2 "" , span [ class "ml-3" ] - [ text "Person" ] + [ text texts.basics.person + ] ] , a [ href "#" @@ -89,7 +94,8 @@ viewSidebar visible _ settings model = [ Icons.folderIcon2 "" , span [ class "ml-3" ] - [ text "Folder" ] + [ text texts.basics.folder + ] ] , a [ href "#" @@ -105,36 +111,37 @@ viewSidebar visible _ settings model = [ Icons.customFieldIcon2 "" , span [ class "ml-3" ] - [ text "Custom Fields" ] + [ text texts.basics.customFields + ] ] ] ] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent flags settings model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts flags settings model = div [ id "content" , class S.content ] (case model.currentTab of Just TagTab -> - viewTags model + viewTags texts model Just EquipTab -> - viewEquip model + viewEquip texts model Just OrgTab -> - viewOrg settings model + viewOrg texts settings model Just PersonTab -> - viewPerson settings model + viewPerson texts settings model Just FolderTab -> - viewFolder flags settings model + viewFolder texts flags settings model Just CustomFieldTab -> - viewCustomFields flags settings model + viewCustomFields texts flags settings model Nothing -> [] @@ -150,69 +157,83 @@ menuEntryActive model tab = class "" -viewTags : Model -> List (Html Msg) -viewTags model = +viewTags : Texts -> Model -> List (Html Msg) +viewTags texts model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ Icons.tagIcon2 "" , div [ class "ml-2" ] - [ text "Tags" + [ text texts.basics.tags ] ] - , Html.map TagManageMsg (Comp.TagManage.view2 model.tagManageModel) + , Html.map TagManageMsg + (Comp.TagManage.view2 + texts.tagManage + model.tagManageModel + ) ] -viewEquip : Model -> List (Html Msg) -viewEquip model = +viewEquip : Texts -> Model -> List (Html Msg) +viewEquip texts model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ Icons.equipmentIcon2 "" , div [ class "ml-2" ] - [ text "Equipment" + [ text texts.basics.equipment ] ] - , Html.map EquipManageMsg (Comp.EquipmentManage.view2 model.equipManageModel) + , Html.map EquipManageMsg + (Comp.EquipmentManage.view2 texts.equipmentManage + model.equipManageModel + ) ] -viewOrg : UiSettings -> Model -> List (Html Msg) -viewOrg settings model = +viewOrg : Texts -> UiSettings -> Model -> List (Html Msg) +viewOrg texts settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ Icons.organizationIcon2 "" , div [ class "ml-2" ] - [ text "Organizations" + [ text texts.basics.organization ] ] - , Html.map OrgManageMsg (Comp.OrgManage.view2 settings model.orgManageModel) + , Html.map OrgManageMsg + (Comp.OrgManage.view2 texts.orgManage + settings + model.orgManageModel + ) ] -viewPerson : UiSettings -> Model -> List (Html Msg) -viewPerson settings model = +viewPerson : Texts -> UiSettings -> Model -> List (Html Msg) +viewPerson texts settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ Icons.personIcon2 "" , div [ class "ml-2" ] - [ text "Person" + [ text texts.basics.person ] ] , Html.map PersonManageMsg - (Comp.PersonManage.view2 settings model.personManageModel) + (Comp.PersonManage.view2 texts.personManage + settings + model.personManageModel + ) ] -viewFolder : Flags -> UiSettings -> Model -> List (Html Msg) -viewFolder flags _ model = +viewFolder : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewFolder texts flags _ model = [ h2 [ class S.header1 , class "inline-flex items-center" @@ -221,25 +242,28 @@ viewFolder flags _ model = , div [ class "ml-2" ] - [ text "Folder" + [ text texts.basics.folder ] ] , Html.map FolderMsg - (Comp.FolderManage.view2 flags model.folderManageModel) + (Comp.FolderManage.view2 texts.folderManage flags model.folderManageModel) ] -viewCustomFields : Flags -> UiSettings -> Model -> List (Html Msg) -viewCustomFields flags _ model = +viewCustomFields : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewCustomFields texts flags _ model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ Icons.customFieldIcon2 "" , div [ class "ml-2" ] - [ text "Custom Fields" + [ text texts.basics.customFields ] ] , Html.map CustomFieldMsg - (Comp.CustomFieldManage.view2 flags model.fieldManageModel) + (Comp.CustomFieldManage.view2 texts.customFieldManage + flags + model.fieldManageModel + ) ] diff --git a/modules/webapp/src/main/elm/Page/NewInvite/View2.elm b/modules/webapp/src/main/elm/Page/NewInvite/View2.elm index 1350e0ba..5b0368ba 100644 --- a/modules/webapp/src/main/elm/Page/NewInvite/View2.elm +++ b/modules/webapp/src/main/elm/Page/NewInvite/View2.elm @@ -5,6 +5,8 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput, onSubmit) +import Markdown +import Messages.Page.NewInvite exposing (Texts) import Page.NewInvite.Data exposing (..) import Styles as S @@ -18,15 +20,15 @@ viewSidebar _ _ _ _ = [] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent flags _ model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts flags _ model = div [ id "content" , class "flex flex-col md:w-3/5 px-2" , class S.content ] - [ h1 [ class S.header1 ] [ text "Create new invitations" ] - , inviteMessage flags + [ h1 [ class S.header1 ] [ text texts.createNewInvitations ] + , inviteMessage texts flags , div [ class " py-2 mt-6 rounded" ] [ Html.form [ action "#" @@ -38,7 +40,7 @@ viewContent flags _ model = [ for "invitekey" , class "mb-1 text-xs sm:text-sm tracking-wide " ] - [ text "Invitation key" + [ text texts.invitationKey ] , div [ class "relative" ] [ div [ class "inline-flex items-center justify-center absolute left-0 top-0 h-full w-10 text-gray-400 dark:text-bluegray-400 " ] @@ -53,7 +55,7 @@ viewContent flags _ model = , value model.password , autofocus True , class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput) - , placeholder "Password" + , placeholder texts.password ] [] ] @@ -64,25 +66,25 @@ viewContent flags _ model = [ type_ "submit" , class (S.primaryButton ++ "inline-flex") ] - [ text "Submit" + [ text texts.basics.submit ] , a [ class S.secondaryButton , href "#" , onClick Reset ] - [ text "Reset" + [ text texts.reset ] ] ] - , resultMessage model + , resultMessage texts model ] ] ] -resultMessage : Model -> Html Msg -resultMessage model = +resultMessage : Texts -> Model -> Html Msg +resultMessage texts model = div [ classList [ ( S.errorMessage, isFailed model.result ) @@ -98,7 +100,7 @@ resultMessage model = div [ class "" ] [ p [] [ text r.message - , text " Invitation Key:" + , text (" " ++ texts.invitationKey ++ ":") ] , pre [ class "text-center font-mono mt-4" ] [ Maybe.withDefault "" r.key |> text @@ -110,28 +112,13 @@ resultMessage model = ] -inviteMessage : Flags -> Html Msg -inviteMessage flags = +inviteMessage : Texts -> Flags -> Html Msg +inviteMessage texts flags = div [ class (S.message ++ "text-sm") , classList [ ( "hidden", flags.config.signupMode /= "invite" ) ] ] - [ p [] - [ text - """Docspell requires an invite when signing up. You can - create these invites here and send them to friends so - they can signup with docspell.""" - ] - , p [] - [ text - """Each invite can only be used once. You'll need to - create one key for each person you want to invite.""" - ] - , p [] - [ text - """Creating an invite requires providing the password - from the configuration.""" - ] + [ Markdown.toHtml [] texts.inviteInfo ] diff --git a/modules/webapp/src/main/elm/Page/Queue/View2.elm b/modules/webapp/src/main/elm/Page/Queue/View2.elm index a59534b4..f1f62704 100644 --- a/modules/webapp/src/main/elm/Page/Queue/View2.elm +++ b/modules/webapp/src/main/elm/Page/Queue/View2.elm @@ -10,13 +10,14 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Messages.Page.Queue exposing (Texts) import Page.Queue.Data exposing (..) import Styles as S import Util.Time exposing (formatDateTime, formatIsoDateTime) -viewSidebar : Bool -> Flags -> UiSettings -> Model -> Html Msg -viewSidebar visible _ _ model = +viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg +viewSidebar texts visible _ _ model = let count v = case v of @@ -68,17 +69,17 @@ viewSidebar visible _ _ model = ] ] , div [ class "flex flex-col my-2" ] - [ tabLink "" CurrentJobs "fa fa-play-circle" "Currently Running" - , tabLink "" QueueAll "fa fa-hourglass-half" "Queue" - , tabLink "ml-8" QueueWaiting "fa fa-clock" "Waiting" - , tabLink "ml-8" QueueError "fa fa-bolt" "Errored" - , tabLink "ml-8" QueueSuccess "fa fa-check" "Success" + [ tabLink "" CurrentJobs "fa fa-play-circle" texts.currentlyRunning + , tabLink "" QueueAll "fa fa-hourglass-half" texts.queue + , tabLink "ml-8" QueueWaiting "fa fa-clock" texts.waiting + , tabLink "ml-8" QueueError "fa fa-bolt" texts.errored + , tabLink "ml-8" QueueSuccess "fa fa-check" texts.success ] ] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent _ _ model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts _ _ model = let gridStyle = "grid gap-4 grid-cols-1 md:grid-cols-2" @@ -103,29 +104,29 @@ viewContent _ _ model = , case model.queueView of CurrentJobs -> if List.isEmpty model.state.progress then - message "No jobs currently running." + message texts.noJobsRunning else div [ class "flex flex-col space-y-2" ] - (List.map (renderProgressCard model) model.state.progress) + (List.map (renderProgressCard texts model) model.state.progress) QueueAll -> if List.isEmpty model.state.completed && List.isEmpty model.state.completed then - message "No jobs to display." + message texts.noJobsDisplay else div [ class gridStyle ] - (List.map (renderInfoCard model) + (List.map (renderInfoCard texts model) (model.state.queued ++ model.state.completed) ) QueueWaiting -> if List.isEmpty model.state.queued then - message "No waiting jobs." + message texts.noJobsWaiting else div [ class gridStyle ] - (List.map (renderInfoCard model) model.state.queued) + (List.map (renderInfoCard texts model) model.state.queued) QueueError -> let @@ -133,11 +134,11 @@ viewContent _ _ model = filterJobDetails model.state.completed "failed" in if List.isEmpty items then - message "No failed jobs to display." + message texts.noJobsFailed else div [ class gridStyle ] - (List.map (renderInfoCard model) items) + (List.map (renderInfoCard texts model) items) QueueSuccess -> let @@ -145,11 +146,11 @@ viewContent _ _ model = filterJobDetails model.state.completed "success" in if List.isEmpty items then - message "No succesfull jobs to display." + message texts.noJobsSuccess else div [ class gridStyle ] - (List.map (renderInfoCard model) items) + (List.map (renderInfoCard texts model) items) ] @@ -189,14 +190,14 @@ renderJobLog job = ] -renderProgressCard : Model -> JobDetail -> Html Msg -renderProgressCard model job = +renderProgressCard : Texts -> Model -> JobDetail -> Html Msg +renderProgressCard texts model job = div [ class (S.box ++ "px-2 flex flex-col") ] [ Comp.Progress.topAttachedIndicating job.progress , Html.map (DimmerMsg job) (Comp.YesNoDimmer.viewN (model.cancelJobRequest == Just job.id) - dimmerSettings + (dimmerSettings texts) model.deleteConfirm ) , div [ class "py-2 flex flex-row x-space-2 items-center" ] @@ -227,7 +228,7 @@ renderProgressCard model job = ] , div [ class "py-2 flex flex-row justify-end" ] [ button [ class S.secondaryButton, onClick (RequestCancelJob job) ] - [ text "Cancel" + [ text texts.basics.cancel ] ] ] @@ -282,22 +283,21 @@ isFinal job = False -dimmerSettings : Comp.YesNoDimmer.Settings -dimmerSettings = +dimmerSettings : Texts -> Comp.YesNoDimmer.Settings +dimmerSettings texts = let defaults = - Comp.YesNoDimmer.defaultSettings + Comp.YesNoDimmer.defaultSettings texts.deleteThisJob texts.basics.yes texts.basics.no in { defaults | headerClass = "text-lg text-white" , headerIcon = "" , extraClass = "rounded" - , message = "Cancel/Delete this job?" } -renderInfoCard : Model -> JobDetail -> Html Msg -renderInfoCard model job = +renderInfoCard : Texts -> Model -> JobDetail -> Html Msg +renderInfoCard texts model job = let prio = Data.Priority.fromString job.priority @@ -315,7 +315,7 @@ renderInfoCard model job = [ Html.map (DimmerMsg job) (Comp.YesNoDimmer.viewN (model.cancelJobRequest == Just job.id) - dimmerSettings + (dimmerSettings texts) model.deleteConfirm ) , div [ class "flex flex-row" ] @@ -345,10 +345,14 @@ renderInfoCard model job = , class S.link , classList [ ( "hidden", not (isFinal job || job.state == "stuck") ) ] ] - [ i [ class "fa fa-file", title "Show log" ] [] + [ i + [ class "fa fa-file" + , title texts.showLog + ] + [] ] , a - [ title "Remove" + [ title texts.remove , href "#" , class S.link , onClick (RequestCancelJob job) @@ -391,7 +395,7 @@ renderInfoCard model job = ] , div [ class (labelStyle False) ] [ span [ class "mr-3" ] - [ text "Retries" + [ text texts.retries ] , span [] [ job.retries |> String.fromInt |> text @@ -403,7 +407,7 @@ renderInfoCard model job = [ class (labelStyle False) , onClick (ChangePrio job.id (Data.Priority.next prio)) , href "#" - , title "Change priority of this job" + , title texts.changePriority ] [ i [ class "sort numeric up icon" ] [] , text "Prio" @@ -422,7 +426,7 @@ renderInfoCard model job = [ class (labelStyle False) ] [ span [ class "mr-3" ] - [ text "Prio" + [ text texts.prio ] , code [ class "font-mono" ] [ Data.Priority.fromString job.priority diff --git a/modules/webapp/src/main/elm/Page/Register/View2.elm b/modules/webapp/src/main/elm/Page/Register/View2.elm index d056f69c..d71cb3d8 100644 --- a/modules/webapp/src/main/elm/Page/Register/View2.elm +++ b/modules/webapp/src/main/elm/Page/Register/View2.elm @@ -6,6 +6,7 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick, onInput, onSubmit) +import Messages.Page.Register exposing (Texts) import Page exposing (Page(..)) import Page.Register.Data exposing (..) import Styles as S @@ -20,8 +21,8 @@ viewSidebar _ _ _ _ = [] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent flags _ model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts flags _ model = div [ id "content" , class "h-full flex flex-col items-center justify-center w-full" @@ -36,7 +37,7 @@ viewContent flags _ model = [] ] , div [ class "font-medium self-center text-xl sm:text-2xl" ] - [ text "Signup to Docspell" + [ text texts.signupToDocspell ] , Html.form [ action "#" @@ -48,7 +49,7 @@ viewContent flags _ model = [ for "username" , class S.inputLabel ] - [ text "Collective ID" + [ text texts.collectiveId , B.inputRequired ] , div [ class "relative" ] @@ -63,7 +64,7 @@ viewContent flags _ model = , value model.collId , autofocus True , class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput) - , placeholder "Collective" + , placeholder texts.collective ] [] ] @@ -73,7 +74,7 @@ viewContent flags _ model = [ for "user" , class S.inputLabel ] - [ text "User Login" + [ text texts.userLogin , B.inputRequired ] , div [ class "relative" ] @@ -87,7 +88,7 @@ viewContent flags _ model = , onInput SetLogin , value model.login , class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput) - , placeholder "Username" + , placeholder texts.username ] [] ] @@ -97,7 +98,7 @@ viewContent flags _ model = [ for "passw1" , class S.inputLabel ] - [ text "Password" + [ text texts.password , B.inputRequired ] , div [ class "relative" ] @@ -124,7 +125,7 @@ viewContent flags _ model = , onInput SetPass1 , value model.pass1 , class ("pl-10 pr-10 py-2 rounded-lg" ++ S.textInput) - , placeholder "Password" + , placeholder texts.password ] [] , a @@ -141,7 +142,7 @@ viewContent flags _ model = [ for "passw2" , class S.inputLabel ] - [ text "Password (repeat)" + [ text texts.passwordRepeat , B.inputRequired ] , div [ class "relative" ] @@ -168,7 +169,7 @@ viewContent flags _ model = , onInput SetPass2 , value model.pass2 , class ("pl-10 pr-10 py-2 rounded-lg" ++ S.textInput) - , placeholder "Password (repeat)" + , placeholder texts.passwordRepeat ] [] , a @@ -188,7 +189,7 @@ viewContent flags _ model = [ for "invitekey" , class S.inputLabel ] - [ text "Invitation Key" + [ text texts.invitationKey , B.inputRequired ] , div [ class "relative" ] @@ -202,7 +203,7 @@ viewContent flags _ model = , onInput SetInvite , model.invite |> Maybe.withDefault "" |> value , class ("pl-10 pr-4 py-2 rounded-lg" ++ S.textInput) - , placeholder "Invitation Key" + , placeholder texts.invitationKey ] [] ] @@ -212,23 +213,23 @@ viewContent flags _ model = [ type_ "submit" , class S.primaryButton ] - [ text "Submit" + [ text texts.basics.submit ] ] - , resultMessage model + , resultMessage texts model , div [ class "flex justify-end text-sm pt-4" , classList [ ( "hidden", flags.config.signupMode == "closed" ) ] ] [ span [] - [ text "Already signed up?" + [ text texts.alreadySignedUp ] , a [ Page.href (LoginPage Nothing) , class ("ml-2" ++ S.link) ] [ i [ class "fa fa-user-plus mr-1" ] [] - , text "Sign in" + , text texts.signIn ] ] ] @@ -236,13 +237,13 @@ viewContent flags _ model = ] -resultMessage : Model -> Html Msg -resultMessage model = +resultMessage : Texts -> Model -> Html Msg +resultMessage texts model = case model.result of Just r -> if r.success then div [ class S.successMessage ] - [ text "Registration successful." + [ text texts.registrationSuccessful ] else diff --git a/modules/webapp/src/main/elm/Page/Upload/Data.elm b/modules/webapp/src/main/elm/Page/Upload/Data.elm index 8c4632c3..7274c8f5 100644 --- a/modules/webapp/src/main/elm/Page/Upload/Data.elm +++ b/modules/webapp/src/main/elm/Page/Upload/Data.elm @@ -9,7 +9,6 @@ module Page.Upload.Data exposing , isIdle , isLoading , isSuccessAll - , mkLanguageItem , uploadAllTracker ) @@ -38,11 +37,6 @@ type alias Model = } -mkLanguageItem : Language -> Comp.FixedDropdown.Item Language -mkLanguageItem lang = - Comp.FixedDropdown.Item lang (Data.Language.toName lang) - - emptyModel : Model emptyModel = { incoming = True @@ -54,8 +48,7 @@ emptyModel = , dropzone = Comp.Dropzone.init [] , skipDuplicates = True , languageModel = - Comp.FixedDropdown.init - (List.map mkLanguageItem Data.Language.all) + Comp.FixedDropdown.init Data.Language.all , language = Nothing } diff --git a/modules/webapp/src/main/elm/Page/Upload/View2.elm b/modules/webapp/src/main/elm/Page/Upload/View2.elm index a685c50b..7abc6006 100644 --- a/modules/webapp/src/main/elm/Page/Upload/View2.elm +++ b/modules/webapp/src/main/elm/Page/Upload/View2.elm @@ -11,6 +11,7 @@ import File exposing (File) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onClick) +import Messages.Page.Upload exposing (Texts) import Page exposing (Page(..)) import Page.Upload.Data exposing (..) import Styles as S @@ -28,8 +29,8 @@ viewSidebar _ _ _ _ _ = [] -viewContent : Maybe String -> Flags -> UiSettings -> Model -> Html Msg -viewContent mid _ _ model = +viewContent : Texts -> Maybe String -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts mid _ _ model = div [ id "content" , class S.content @@ -37,11 +38,11 @@ viewContent mid _ _ model = [ div [ class "container mx-auto" ] [ div [ class "px-0 flex flex-col" ] [ div [ class "py-4" ] - [ renderForm model + [ renderForm texts model ] , div [ class "py-0" ] [ Html.map DropzoneMsg - (Comp.Dropzone.view2 model.dropzone) + (Comp.Dropzone.view2 texts.dropzone model.dropzone) ] , div [ class "py-4" ] [ a @@ -49,7 +50,7 @@ viewContent mid _ _ model = , href "#" , onClick SubmitUpload ] - [ text "Submit" + [ text texts.basics.submit ] , a [ class S.secondaryButton @@ -57,19 +58,26 @@ viewContent mid _ _ model = , href "#" , onClick Clear ] - [ text "Reset" + [ text texts.reset ] ] ] - , renderErrorMsg model - , renderSuccessMsg (Util.Maybe.nonEmpty mid) model - , renderUploads model + , renderErrorMsg texts model + , renderSuccessMsg texts (Util.Maybe.nonEmpty mid) model + , renderUploads texts model ] ] -renderForm : Model -> Html Msg -renderForm model = +renderForm : Texts -> Model -> Html Msg +renderForm texts model = + let + languageCfg = + { display = texts.languageLabel + , icon = \_ -> Nothing + , style = DS.mainStyleWith "w-40" + } + in div [ class "row" ] [ Html.form [ action "#" ] [ div [ class "flex flex-col mb-3" ] @@ -81,7 +89,7 @@ renderForm model = , class S.radioInput ] [] - , span [ class "ml-2" ] [ text "Incoming" ] + , span [ class "ml-2" ] [ text texts.basics.incoming ] ] , label [ class "inline-flex items-center" ] [ input @@ -91,7 +99,7 @@ renderForm model = , class S.radioInput ] [] - , span [ class "ml-2" ] [ text "Outgoing" ] + , span [ class "ml-2" ] [ text texts.basics.outgoing ] ] ] , div [ class "flex flex-col mb-3" ] @@ -104,7 +112,7 @@ renderForm model = ] [] , span [ class "ml-2" ] - [ text "All files are one single item" + [ text texts.allFilesOneItem ] ] ] @@ -118,46 +126,45 @@ renderForm model = ] [] , span [ class "ml-2" ] - [ text "Skip files already present in docspell" + [ text texts.skipExistingFiles ] ] ] , div [ class "flex flex-col mb-3" ] [ label [ class "inline-flex items-center mb-2" ] - [ span [ class "mr-2" ] [ text "Language:" ] + [ span [ class "mr-2" ] [ text (texts.language ++ ":") ] , Html.map LanguageMsg (Comp.FixedDropdown.viewStyled2 - (DS.mainStyleWith "w-40") + languageCfg False - (Maybe.map mkLanguageItem model.language) + model.language model.languageModel ) ] , div [ class "text-gray-400 text-xs" ] - [ text "Used for text extraction and analysis. The collective's " - , text "default language is used if not specified here." + [ text texts.languageInfo ] ] ] ] -renderErrorMsg : Model -> Html Msg -renderErrorMsg model = +renderErrorMsg : Texts -> Model -> Html Msg +renderErrorMsg texts model = div [ class "row" , classList [ ( "hidden", not (isDone model && hasErrors model) ) ] ] [ div [ class "mt-4" ] [ div [ class S.errorMessage ] - [ text "There were errors uploading some files." + [ text texts.uploadErrorMessage ] ] ] -renderSuccessMsg : Bool -> Model -> Html Msg -renderSuccessMsg public model = +renderSuccessMsg : Texts -> Bool -> Model -> Html Msg +renderSuccessMsg texts public model = div [ class "row" , classList [ ( "hidden", List.isEmpty model.files || not (isSuccessAll model) ) ] @@ -167,47 +174,46 @@ renderSuccessMsg public model = [ h3 [ class S.header2, class "text-green-800 dark:text-lime-800" ] [ i [ class "fa fa-smile font-thin" ] [] , span [ class "ml-2" ] - [ text "All files uploaded" + [ text texts.successBox.allFilesUploaded ] ] , p [ classList [ ( "hidden", public ) ] ] - [ text "Your files have been successfully uploaded. " - , text "They are now being processed. Check the " + [ text texts.successBox.line1 , a [ class S.successMessageLink , Page.href HomePage ] - [ text "Items page" + [ text texts.successBox.itemsPage ] - , text " later where the files will arrive eventually. Or go to the " + , text texts.successBox.line2 , a [ class S.successMessageLink , Page.href QueuePage ] - [ text "Processing Page" + [ text texts.successBox.processingPage ] - , text " to view the current processing state." + , text texts.successBox.line3 ] , p [] - [ text "Click " + [ text texts.successBox.resetLine1 , a [ class S.successMessageLink , href "#" , onClick Clear ] - [ text "Reset" + [ text texts.successBox.reset ] - , text " to upload more files." + , text texts.successBox.resetLine2 ] ] ] ] -renderUploads : Model -> Html Msg -renderUploads model = +renderUploads : Texts -> Model -> Html Msg +renderUploads texts model = div [ class "mt-4" , classList [ ( "hidden", List.isEmpty model.files || isSuccessAll model ) ] @@ -215,7 +221,7 @@ renderUploads model = [ div [ class "sixteen wide column" ] [ div [ class "ui basic segment" ] [ h2 [ class S.header2 ] - [ text "Selected Files" + [ text texts.selectedFiles ] , div [ class "ui items" ] <| if model.singleItem then diff --git a/modules/webapp/src/main/elm/Page/UserSettings/View2.elm b/modules/webapp/src/main/elm/Page/UserSettings/View2.elm index 8d6fc120..a29a37bf 100644 --- a/modules/webapp/src/main/elm/Page/UserSettings/View2.elm +++ b/modules/webapp/src/main/elm/Page/UserSettings/View2.elm @@ -11,12 +11,14 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Markdown +import Messages.Page.UserSettings exposing (Texts) import Page.UserSettings.Data exposing (..) import Styles as S -viewSidebar : Bool -> Flags -> UiSettings -> Model -> Html Msg -viewSidebar visible _ _ model = +viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg +viewSidebar texts visible _ _ model = div [ id "sidebar" , class S.sidebar @@ -25,7 +27,7 @@ viewSidebar visible _ _ model = ] [ div [ class "" ] [ h1 [ class S.header1 ] - [ text "User Settings" + [ text texts.userSettings ] ] , div [ class "flex flex-col my-2" ] @@ -38,7 +40,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-cog" ] [] , span [ class "ml-3" ] - [ text "UI Settings" ] + [ text texts.uiSettings ] ] , a [ href "#" @@ -49,7 +51,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-bullhorn" ] [] , span [ class "ml-3" ] - [ text "Notifications" ] + [ text texts.notifications ] ] , a [ href "#" @@ -60,7 +62,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-envelope-open font-thin" ] [] , span [ class "ml-3" ] - [ text "Scan Mailbox" ] + [ text texts.scanMailbox ] ] , a [ href "#" @@ -71,7 +73,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-envelope" ] [] , span [ class "ml-3" ] - [ text "E-Mail Settings (SMTP)" ] + [ text texts.emailSettingSmtp ] ] , a [ href "#" @@ -82,7 +84,7 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-envelope" ] [] , span [ class "ml-3" ] - [ text "E-Mail Settings (IMAP)" ] + [ text texts.emailSettingImap ] ] , a [ href "#" @@ -93,36 +95,36 @@ viewSidebar visible _ _ model = [ i [ class "fa fa-user-secret" ] [] , span [ class "ml-3" ] - [ text "Change Password" ] + [ text texts.changePassword ] ] ] ] -viewContent : Flags -> UiSettings -> Model -> Html Msg -viewContent flags settings model = +viewContent : Texts -> Flags -> UiSettings -> Model -> Html Msg +viewContent texts flags settings model = div [ id "content" , class S.content ] (case model.currentTab of Just ChangePassTab -> - viewChangePassword model + viewChangePassword texts model Just EmailSettingsTab -> - viewEmailSettings settings model + viewEmailSettings texts settings model Just NotificationTab -> - viewNotificationManage settings model + viewNotificationManage texts settings model Just ImapSettingsTab -> - viewImapSettings settings model + viewImapSettings texts settings model Just ScanMailboxTab -> - viewScanMailboxManage settings model + viewScanMailboxManage texts flags settings model Just UiSettingsTab -> - viewUiSettings flags settings model + viewUiSettings texts flags settings model Nothing -> [] @@ -142,38 +144,41 @@ menuEntryActive model tab = class "" -viewChangePassword : Model -> List (Html Msg) -viewChangePassword model = +viewChangePassword : Texts -> Model -> List (Html Msg) +viewChangePassword texts model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-user-secret" ] [] , div [ class "ml-3" ] - [ text "Change Password" + [ text texts.changePassword ] ] - , Html.map ChangePassMsg (Comp.ChangePasswordForm.view2 model.changePassModel) + , Html.map ChangePassMsg + (Comp.ChangePasswordForm.view2 texts.changePasswordForm + model.changePassModel + ) ] -viewUiSettings : Flags -> UiSettings -> Model -> List (Html Msg) -viewUiSettings flags settings model = +viewUiSettings : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewUiSettings texts flags settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-cog" ] [] , span [ class "ml-3" ] - [ text "UI Settings" + [ text texts.uiSettings ] ] , p [ class "opacity-75 text-lg mb-4" ] - [ text "These settings only affect the web ui. They are stored in the browser, " - , text "so they are separated between browsers and devices." + [ text texts.uiSettingsInfo ] , Html.map UiSettingsMsg (Comp.UiSettingsManage.view2 + texts.uiSettingsManage flags settings "" @@ -182,100 +187,92 @@ viewUiSettings flags settings model = ] -viewEmailSettings : UiSettings -> Model -> List (Html Msg) -viewEmailSettings settings model = +viewEmailSettings : Texts -> UiSettings -> Model -> List (Html Msg) +viewEmailSettings texts settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-envelope" ] [] , div [ class "ml-3" ] - [ text "E-Mail Settings (Smtp)" + [ text texts.emailSettingSmtp ] ] , Html.map EmailSettingsMsg (Comp.EmailSettingsManage.view2 + texts.emailSettingsManage settings model.emailSettingsModel ) ] -viewImapSettings : UiSettings -> Model -> List (Html Msg) -viewImapSettings settings model = +viewImapSettings : Texts -> UiSettings -> Model -> List (Html Msg) +viewImapSettings texts settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-envelope" ] [] , div [ class "ml-3" ] - [ text "E-Mail Settings (Imap)" + [ text texts.emailSettingImap ] ] , Html.map ImapSettingsMsg (Comp.ImapSettingsManage.view2 + texts.imapSettingsManage settings model.imapSettingsModel ) ] -viewNotificationManage : UiSettings -> Model -> List (Html Msg) -viewNotificationManage settings model = +viewNotificationManage : Texts -> UiSettings -> Model -> List (Html Msg) +viewNotificationManage texts settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-bullhorn" ] [] , div [ class "ml-3" ] - [ text "Notification" + [ text texts.notifications ] ] , p [ class "opacity-80 text-lg mb-3" ] - [ text """ - Docspell can notify you once the due dates of your items - come closer. Notification is done via e-mail. You need to - provide a connection in your e-mail settings.""" + [ text texts.notificationInfoText ] , p [ class "opacity-80 text-lg mb-3" ] - [ text "Docspell finds all items that are due in " - , em [ class "font-italic" ] [ text "Remind Days" ] - , text " days and sends this list via e-mail." + [ Markdown.toHtml [] texts.notificationRemindDaysInfo ] , Html.map NotificationMsg - (Comp.NotificationManage.view2 settings model.notificationModel) + (Comp.NotificationManage.view2 texts.notificationManage + settings + model.notificationModel + ) ] -viewScanMailboxManage : UiSettings -> Model -> List (Html Msg) -viewScanMailboxManage settings model = +viewScanMailboxManage : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +viewScanMailboxManage texts flags settings model = [ h2 [ class S.header1 , class "inline-flex items-center" ] [ i [ class "fa fa-envelope-open font-thin" ] [] , div [ class "ml-3" ] - [ text "Scan Mailbox" + [ text texts.scanMailbox ] ] , p [ class "opacity-80 text-lg mb-3" ] - [ text "Docspell can scan folders of your mailbox to import your mails. " - , text "You need to provide a connection in " - , text "your e-mail (imap) settings." + [ text texts.scanMailboxInfo1 ] , p [ class "opacity-80 text-lg mb-3 hidden" ] - [ text """ - Docspell goes through all configured folders and imports - mails matching the search criteria. Mails are skipped if - they were imported in a previous run and the corresponding - items still exist. After submitting a mail into docspell, - you can choose to move it to another folder, to delete it - or to just leave it there. In the latter case you should - adjust the schedule to avoid reading over the same mails - again.""" + [ text texts.scanMailboxInfo2 ] , Html.map ScanMailboxMsg (Comp.ScanMailboxManage.view2 + texts.scanMailboxManage + flags settings model.scanMailboxModel ) diff --git a/modules/webapp/src/main/elm/Util/Folder.elm b/modules/webapp/src/main/elm/Util/Folder.elm index ba32bb67..db6d5dec 100644 --- a/modules/webapp/src/main/elm/Util/Folder.elm +++ b/modules/webapp/src/main/elm/Util/Folder.elm @@ -37,7 +37,7 @@ mkFolderOption flags allFolders idref = else "" in - { value = idref.id, text = idref.name, additional = adds } + { text = idref.name, additional = adds } isFolderMember : List FolderItem -> Maybe String -> Bool diff --git a/modules/webapp/src/main/elm/Util/Person.elm b/modules/webapp/src/main/elm/Util/Person.elm new file mode 100644 index 00000000..cb61762c --- /dev/null +++ b/modules/webapp/src/main/elm/Util/Person.elm @@ -0,0 +1,20 @@ +module Util.Person exposing (mkPersonOption) + +import Api.Model.IdName exposing (IdName) +import Api.Model.Person exposing (Person) +import Comp.Dropdown +import Dict exposing (Dict) +import Util.String + + +mkPersonOption : IdName -> Dict String Person -> Comp.Dropdown.Option +mkPersonOption idref personDict = + let + org = + Dict.get idref.id personDict + |> Maybe.andThen .organization + |> Maybe.map .name + |> Maybe.map (Util.String.ellipsis 15) + |> Maybe.withDefault "" + in + Comp.Dropdown.Option idref.name org diff --git a/modules/webapp/src/main/elm/Util/Tag.elm b/modules/webapp/src/main/elm/Util/Tag.elm index c095c6ff..583f3f0a 100644 --- a/modules/webapp/src/main/elm/Util/Tag.elm +++ b/modules/webapp/src/main/elm/Util/Tag.elm @@ -1,12 +1,14 @@ module Util.Tag exposing - ( getCategories + ( catSettings + , getCategories , makeCatDropdownModel , makeDropdownModel - , makeDropdownModel2 + , tagSettings ) import Api.Model.Tag exposing (Tag) import Comp.Dropdown +import Data.DropdownStyle as DS import Data.UiSettings import Util.List @@ -16,30 +18,19 @@ makeDropdownModel = Comp.Dropdown.makeModel { multiple = True , searchable = \n -> n > 0 - , makeOption = \tag -> { value = tag.id, text = tag.name, additional = "" } - , labelColor = - \tag -> - \settings -> - "basic " ++ Data.UiSettings.tagColorString tag settings - , placeholder = "Choose a tag…" } -makeDropdownModel2 : Comp.Dropdown.Model Tag -makeDropdownModel2 = - Comp.Dropdown.makeModel - { multiple = True - , searchable = \n -> n > 0 - , makeOption = \tag -> { value = tag.id, text = tag.name, additional = "" } - , labelColor = - \tag -> - \settings -> - Data.UiSettings.tagColorString2 tag settings - ++ -- legacy colors - " basic " - ++ Data.UiSettings.tagColorString tag settings - , placeholder = "Choose a tag…" - } +tagSettings : String -> DS.DropdownStyle -> Comp.Dropdown.ViewSettings Tag +tagSettings placeholder ds = + { makeOption = \tag -> { text = tag.name, additional = "" } + , labelColor = + \tag -> + \settings -> + Data.UiSettings.tagColorString2 tag settings + , placeholder = placeholder + , style = ds + } makeCatDropdownModel : Comp.Dropdown.Model String @@ -47,12 +38,18 @@ makeCatDropdownModel = Comp.Dropdown.makeModel { multiple = True , searchable = \n -> n > 0 - , makeOption = \cat -> { value = cat, text = cat, additional = "" } - , labelColor = \_ -> \_ -> "" - , placeholder = "Choose a tag category…" } +catSettings : String -> DS.DropdownStyle -> Comp.Dropdown.ViewSettings String +catSettings placeholder ds = + { makeOption = \cat -> { text = cat, additional = "" } + , labelColor = \_ -> \_ -> "" + , placeholder = placeholder + , style = ds + } + + getCategories : List Tag -> List String getCategories tags = List.filterMap .category tags diff --git a/modules/webapp/src/main/styles/index.css b/modules/webapp/src/main/styles/index.css index 0639a27c..274ad20a 100644 --- a/modules/webapp/src/main/styles/index.css +++ b/modules/webapp/src/main/styles/index.css @@ -1,4 +1,5 @@ @import "@fortawesome/fontawesome-free/css/all"; +@import "flag-icon-css/css/flag-icon.min"; /* all @import must be above this line */ diff --git a/package-lock.json b/package-lock.json index 4bb4daf1..b39dbf8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,9 +28,9 @@ } }, "@fortawesome/fontawesome-free": { - "version": "5.15.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz", - "integrity": "sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA==" + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz", + "integrity": "sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w==" }, "@fullhuman/postcss-purgecss": { "version": "3.1.3", @@ -147,22 +147,46 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" }, "autoprefixer": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.4.tgz", - "integrity": "sha512-DCCdUQiMD+P/as8m3XkeTUkUKuuRqLGcwD0nll7wevhqoJfMRpJlkFd1+MQh1pvupjiQuip42lc/VFvfUTMSKw==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.5.tgz", + "integrity": "sha512-7H4AJZXvSsn62SqZyJCP+1AWwOuoYpUfK6ot9vm0e87XD6mT8lDywc9D9OTJPMULyGcvmIxzTAMeG2Cc+YX+fA==", "requires": { - "browserslist": "^4.16.1", - "caniuse-lite": "^1.0.30001181", - "colorette": "^1.2.1", + "browserslist": "^4.16.3", + "caniuse-lite": "^1.0.30001196", + "colorette": "^1.2.2", "fraction.js": "^4.0.13", "normalize-range": "^0.1.2", "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "browserslist": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", + "requires": { + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.649", + "escalade": "^3.1.1", + "node-releases": "^1.1.70" + } + }, + "caniuse-lite": { + "version": "1.0.30001204", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001204.tgz", + "integrity": "sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ==" + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" + } } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "binary-extensions": { "version": "2.2.0", @@ -192,15 +216,15 @@ } }, "browserslist": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", - "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", "requires": { - "caniuse-lite": "^1.0.30001173", + "caniuse-lite": "^1.0.30001181", "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.634", + "electron-to-chromium": "^1.3.649", "escalade": "^3.1.1", - "node-releases": "^1.1.69" + "node-releases": "^1.1.70" } }, "bytes": { @@ -255,9 +279,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001181", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001181.tgz", - "integrity": "sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ==" + "version": "1.0.30001208", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz", + "integrity": "sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA==" }, "chalk": { "version": "2.4.2", @@ -337,9 +361,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", - "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -438,12 +462,12 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "cssnano": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", - "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", "requires": { "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.7", + "cssnano-preset-default": "^4.0.8", "is-resolvable": "^1.0.0", "postcss": "^7.0.0" }, @@ -461,9 +485,9 @@ } }, "cssnano-preset-default": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", - "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", "requires": { "css-declaration-sorter": "^4.0.1", "cssnano-util-raw-cache": "^4.0.1", @@ -493,7 +517,7 @@ "postcss-ordered-values": "^4.1.2", "postcss-reduce-initial": "^4.0.3", "postcss-reduce-transforms": "^4.0.2", - "postcss-svgo": "^4.0.2", + "postcss-svgo": "^4.0.3", "postcss-unique-selectors": "^4.0.1" }, "dependencies": { @@ -553,9 +577,9 @@ }, "dependencies": { "css-tree": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.2.tgz", - "integrity": "sha512-wCoWush5Aeo48GLhfHPbmvZs59Z+M7k5+B1xDnXbdWNcEF423DoFdqSWE0PM5aNk5nI5cp1q7ms36zGApY/sKQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "requires": { "mdn-data": "2.0.14", "source-map": "^0.6.1" @@ -609,6 +633,11 @@ "path-type": "^4.0.0" } }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -619,9 +648,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", - "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" } } }, @@ -671,24 +700,26 @@ } }, "es-abstract": { - "version": "1.18.0-next.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", - "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", "object-inspect": "^1.9.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.3", - "string.prototype.trimstart": "^1.0.3" + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" } }, "es-to-primitive": { @@ -745,6 +776,11 @@ "to-regex-range": "^5.0.1" } }, + "flag-icon-css": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/flag-icon-css/-/flag-icon-css-3.5.0.tgz", + "integrity": "sha512-pgJnJLrtb0tcDgU1fzGaQXmR8h++nXvILJ+r5SmOXaaL/2pocunQo2a8TAXhjQnBpRLPtZ1KCz/TYpqeNuE2ew==" + }, "fraction.js": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.13.tgz", @@ -783,9 +819,9 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz", - "integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -810,6 +846,38 @@ "path-is-absolute": "^1.0.0" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -844,15 +912,20 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "hex-color-regex": { "version": "1.1.0", @@ -869,11 +942,6 @@ "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" - }, "html-tags": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", @@ -945,6 +1013,11 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==" + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -953,10 +1026,18 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "requires": { + "call-bind": "^1.0.0" + } + }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" }, "is-color-stop": { "version": "1.1.0", @@ -989,6 +1070,11 @@ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1017,16 +1103,22 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" + }, "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" } }, @@ -1035,13 +1127,10 @@ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" }, - "is-svg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", - "requires": { - "html-comment-regex": "^1.1.0" - } + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" }, "is-symbol": { "version": "1.0.3", @@ -1090,9 +1179,9 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.difference": { "version": "4.5.0", @@ -1129,6 +1218,11 @@ "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" }, + "lodash.topath": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", + "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -1185,9 +1279,9 @@ "integrity": "sha512-1lM+BMLGuDfsdwf3rsgBSrxJwAZHFIrQ8YR61xIqdHo0uNKI9M52wNpHSrliZATJp51On6JD0AfRxd4YGSU0lw==" }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz", + "integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==" }, "node-emoji": { "version": "1.10.0", @@ -1257,23 +1351,23 @@ } }, "object.getownpropertydescriptors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", - "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "es-abstract": "^1.18.0-next.2" } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, @@ -1300,6 +1394,32 @@ } } }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -1335,13 +1455,20 @@ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "postcss": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.4.tgz", - "integrity": "sha512-kRFftRoExRVXZlwUuay9iC824qmXPcQQVzAjbCCgjpXnkdMCJYBu2gTwAaFBzv8ewND6O8xFb3aELmEkh9zTzg==", + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.9.tgz", + "integrity": "sha512-b+TmuIL4jGtCHtoLi+G/PisuIl9avxs8IZMSmlABRwNz5RLUUACrC+ws81dcomz1nRezm5YPdXiMEzBEKgYn+Q==", "requires": { - "colorette": "^1.2.1", - "nanoid": "^3.1.20", + "colorette": "^1.2.2", + "nanoid": "^3.1.22", "source-map": "^0.6.1" + }, + "dependencies": { + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" + } } }, "postcss-calc": { @@ -1602,9 +1729,9 @@ } }, "postcss-import": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.0.0.tgz", - "integrity": "sha512-gFDDzXhqr9ELmnLHgCC3TbGfA6Dm/YMb/UN8/f7Uuq4fL7VTk2vOIj6hwINEwbokEmp123bLD7a5m+E+KIetRg==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.0.1.tgz", + "integrity": "sha512-Xn2+z++vWObbEPhiiKO1a78JiyhqipyrXHBb3AHpv0ks7Cdg+GxQQJ24ODNMTanldf7197gSP3axppO9yaG0lA==", "requires": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -1849,9 +1976,9 @@ } }, "postcss-nested": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.3.tgz", - "integrity": "sha512-R2LHPw+u5hFfDgJG748KpGbJyTv7Yr33/2tIMWxquYuHTd9EXu27PYnKi7BxMXLtzKC0a0WVsqHtd7qIluQu/g==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.5.tgz", + "integrity": "sha512-GSRXYz5bccobpTzLQZXOnSOfKl6TwVr5CyAQJUPub4nuRJSOECK5AqurxVgmtxP48p0Kc/ndY/YyS1yqldX0Ew==", "requires": { "postcss-selector-parser": "^6.0.4" } @@ -2197,11 +2324,10 @@ } }, "postcss-svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", - "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", "requires": { - "is-svg": "^3.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "svgo": "^1.0.0" @@ -2272,6 +2398,11 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -2310,11 +2441,11 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "requires": { - "is-core-module": "^2.1.0", + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -2394,20 +2525,20 @@ } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, @@ -2480,30 +2611,37 @@ } }, "tailwindcss": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-2.0.2.tgz", - "integrity": "sha512-nO9JRE1pO7SF9RnYAl6g7uzeHdrmKAFqNjT9NtZUfxqimJZAOOLOEyIEUiMq12+xIc7mC2Ey3Vf90XjHpWKfbw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-2.1.1.tgz", + "integrity": "sha512-zZ6axGqpSZOCBS7wITm/WNHkBzDt5CIZlDlx0eCVldwTxFPELCVGbgh7Xpb3/kZp3cUxOmK7bZUjqhuMrbN6xQ==", "requires": { - "@fullhuman/postcss-purgecss": "^3.0.0", + "@fullhuman/postcss-purgecss": "^3.1.3", "bytes": "^3.0.0", "chalk": "^4.1.0", + "chokidar": "^3.5.1", "color": "^3.1.3", "detective": "^5.2.0", "didyoumean": "^1.2.1", - "fs-extra": "^9.0.1", + "dlv": "^1.1.3", + "fast-glob": "^3.2.5", + "fs-extra": "^9.1.0", "html-tags": "^3.1.0", - "lodash": "^4.17.20", + "lodash": "^4.17.21", + "lodash.topath": "^4.5.2", "modern-normalize": "^1.0.0", "node-emoji": "^1.8.1", - "object-hash": "^2.0.3", + "normalize-path": "^3.0.0", + "object-hash": "^2.1.1", + "parse-glob": "^3.0.4", "postcss-functions": "^3", "postcss-js": "^3.0.3", - "postcss-nested": "^5.0.1", + "postcss-nested": "5.0.5", "postcss-selector-parser": "^6.0.4", "postcss-value-parser": "^4.1.0", "pretty-hrtime": "^1.0.3", - "reduce-css-calc": "^2.1.6", - "resolve": "^1.19.0" + "quick-lru": "^5.1.1", + "reduce-css-calc": "^2.1.8", + "resolve": "^1.20.0" }, "dependencies": { "ansi-styles": { @@ -2564,6 +2702,17 @@ "is-number": "^7.0.0" } }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", @@ -2598,26 +2747,6 @@ "es-abstract": "^1.17.2", "has-symbols": "^1.0.1", "object.getownpropertydescriptors": "^2.1.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } } }, "vendors": { @@ -2625,6 +2754,18 @@ "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 33a7d4e0..3ea8ba06 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,14 @@ "version": "1.0.0", "private": true, "dependencies": { - "@fortawesome/fontawesome-free": "^5.15.2", + "@fortawesome/fontawesome-free": "^5.15.3", "@tailwindcss/forms": "^0.2.1", - "autoprefixer": "^10.2.4", - "cssnano": "^4.1.10", - "postcss": "^8.2.4", + "autoprefixer": "^10.2.5", + "cssnano": "^4.1.11", + "flag-icon-css": "^3.5.0", + "postcss": "^8.2.9", "postcss-cli": "^8.3.1", - "postcss-import": "^14.0.0", - "tailwindcss": "^2.0.2" + "postcss-import": "^14.0.1", + "tailwindcss": "^2.1.1" } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 0d483c19..fa99e02a 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -272,7 +272,7 @@ object Dependencies { ).map(_ % Test) val munit = Seq( - "org.scalameta" %% "munit" % MUnitVersion, + "org.scalameta" %% "munit" % MUnitVersion, "org.scalameta" %% "munit-scalacheck" % MUnitVersion ) @@ -280,9 +280,9 @@ object Dependencies { val betterMonadicFor = "com.olegpy" %% "better-monadic-for" % BetterMonadicForVersion val webjars = Seq( - "org.webjars" % "swagger-ui" % SwaggerUIVersion, - "org.webjars" % "viewerjs" % ViewerJSVersion, - "org.webjars" % "clipboard.js" % ClipboardJsVersion + "org.webjars" % "swagger-ui" % SwaggerUIVersion, + "org.webjars" % "viewerjs" % ViewerJSVersion, + "org.webjars" % "clipboard.js" % ClipboardJsVersion ) val icu4j = Seq( diff --git a/project/StylesPlugin.scala b/project/StylesPlugin.scala index ce6f1d1e..e41af9c8 100644 --- a/project/StylesPlugin.scala +++ b/project/StylesPlugin.scala @@ -54,7 +54,8 @@ object StylesPlugin extends AutoPlugin { val mode = stylesMode.value npmInstall(npm, wd, logger) val files = postCss(npx, inDir, outDir, wd, mode, logger) ++ - copyWebfonts(wd, outDir, logger) + copyWebfonts(wd, outDir, logger) ++ + copyFlags(wd, outDir, logger) logger.info("Styles built") files }, @@ -63,6 +64,7 @@ object StylesPlugin extends AutoPlugin { val npm = stylesNpmCommand.value val wd = (LocalRootProject / baseDirectory).value npmInstall(npm, wd, logger) + } ) @@ -118,4 +120,20 @@ object StylesPlugin extends AutoPlugin { IO.copy(fontDir.listFiles().map(f => f -> targetDir / f.name).toSeq) IO.listFiles(targetDir).toSeq } + + def copyFlags(baseDir: File, outDir: File, logger: Logger): Seq[File] = { + val flagDir = + baseDir / "node_modules" / "flag-icon-css" / "flags" + val targetDir = outDir / "flags" + IO.createDirectory(targetDir) + + val files = (flagDir ** "*") + .filter(_.isFile) + .get + .pair(Path.relativeTo(flagDir)) + .map(t => (t._1, targetDir / t._2)) + + IO.copy(files) + (targetDir ** "*.svg").get() + } } diff --git a/project/ZolaPlugin.scala b/project/ZolaPlugin.scala index b2a559b5..fab7c076 100644 --- a/project/ZolaPlugin.scala +++ b/project/ZolaPlugin.scala @@ -35,7 +35,7 @@ object ZolaPlugin extends AutoPlugin { zolaBuild := { val logger = streams.value.log logger.info("Building web site using zola ...") - (Compile/resources).value + (Compile / resources).value buildSite(zolaCommand.value, zolaRootDir.value, zolaOutputDir.value, None, logger) logger.info("Website built") }, @@ -43,7 +43,7 @@ object ZolaPlugin extends AutoPlugin { val logger = streams.value.log val baseurl = zolaTestBaseUrl.value logger.info("Building web site (test) using zola ...") - (Compile/resources).value + (Compile / resources).value buildSite( zolaCommand.value, zolaRootDir.value, diff --git a/project/plugins.sbt b/project/plugins.sbt index 20d5d4f8..fa86567b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,13 +1,13 @@ -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.27") -addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0") -addSbtPlugin("com.github.eikek" % "sbt-openapi-schema" % "0.7.1") -addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") -addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3") -addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.1") -addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.27") +addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0") +addSbtPlugin("com.github.eikek" % "sbt-openapi-schema" % "0.7.1") +addSbtPlugin("com.github.sbt" % "sbt-release" % "1.0.15") +addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") +addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3") +addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.1") +addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.5.1") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.5.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.7")