Add more properties to upload meta data

This commit is contained in:
Eike Kettner 2020-11-11 01:08:07 +01:00
parent a21a97f7d5
commit 55a6f7aaf6
10 changed files with 70 additions and 21 deletions

View File

@ -124,9 +124,8 @@ val buildInfoSettings = Seq(
val openapiScalaSettings = Seq( val openapiScalaSettings = Seq(
openapiScalaConfig := ScalaConfig() openapiScalaConfig := ScalaConfig()
.withJson(ScalaJson.circeSemiauto) .withJson(ScalaJson.circeSemiauto)
.addMapping(CustomMapping.forType({ .addMapping(CustomMapping.forType({ case TypeDef("LocalDateTime", _) =>
case TypeDef("LocalDateTime", _) => TypeDef("Timestamp", Imports("docspell.common.Timestamp"))
TypeDef("Timestamp", Imports("docspell.common.Timestamp"))
})) }))
.addMapping(CustomMapping.forFormatType({ .addMapping(CustomMapping.forFormatType({
case "ident" => case "ident" =>
@ -182,6 +181,8 @@ val openapiScalaSettings = Seq(
) )
) )
) )
case "glob" =>
field => field.copy(typeDef = TypeDef("Glob", Imports("docspell.common.Glob")))
})) }))
) )
@ -595,11 +596,10 @@ def copyWebjarResources(
src.flatMap { dir => src.flatMap { dir =>
if (dir.isDirectory) { if (dir.isDirectory) {
val files = (dir ** "*").filter(_.isFile).get.pair(Path.relativeTo(dir)) val files = (dir ** "*").filter(_.isFile).get.pair(Path.relativeTo(dir))
files.flatMap { files.flatMap { case (f, name) =>
case (f, name) => val target = targetDir / name
val target = targetDir / name IO.createDirectories(Seq(target.getParentFile))
IO.createDirectories(Seq(target.getParentFile)) copyWithGZ(f, target)
copyWithGZ(f, target)
} }
} else { } else {
val target = targetDir / dir.name val target = targetDir / dir.name
@ -633,11 +633,13 @@ def compileElm(
} }
def createWebjarSource(wj: Seq[ModuleID], out: File): Seq[File] = { def createWebjarSource(wj: Seq[ModuleID], out: File): Seq[File] = {
val target = out / "Webjars.scala" val target = out / "Webjars.scala"
val badChars = "-.".toSet val badChars = "-.".toSet
val fields = wj val fields = wj
.map(m => .map(m =>
s"""val ${m.name.toLowerCase.filter(c => !badChars.contains(c))} = "/${m.name}/${m.revision}" """ s"""val ${m.name.toLowerCase.filter(c =>
!badChars.contains(c)
)} = "/${m.name}/${m.revision}" """
) )
.mkString("\n\n") .mkString("\n\n")
val content = s"""package docspell.restserver.webapp val content = s"""package docspell.restserver.webapp

View File

@ -60,7 +60,9 @@ object OUpload {
sourceAbbrev: String, sourceAbbrev: String,
folderId: Option[Ident], folderId: Option[Ident],
validFileTypes: Seq[MimeType], validFileTypes: Seq[MimeType],
skipDuplicates: Boolean skipDuplicates: Boolean,
fileFilter: Option[Glob],
tags: List[String]
) )
case class UploadData[F[_]]( case class UploadData[F[_]](
@ -127,7 +129,9 @@ object OUpload {
data.meta.sourceAbbrev, data.meta.sourceAbbrev,
data.meta.folderId, data.meta.folderId,
data.meta.validFileTypes, data.meta.validFileTypes,
data.meta.skipDuplicates data.meta.skipDuplicates,
data.meta.fileFilter,
data.meta.tags.some
) )
args = args =
if (data.multiple) files.map(f => ProcessItemArgs(meta, List(f))) if (data.multiple) files.map(f => ProcessItemArgs(meta, List(f)))

View File

@ -38,7 +38,9 @@ object ProcessItemArgs {
sourceAbbrev: String, sourceAbbrev: String,
folderId: Option[Ident], folderId: Option[Ident],
validFileTypes: Seq[MimeType], validFileTypes: Seq[MimeType],
skipDuplicate: Boolean skipDuplicate: Boolean,
fileFilter: Option[Glob],
tags: Option[List[String]]
) )
object ProcessMeta { object ProcessMeta {

View File

@ -29,7 +29,11 @@ case class ScanMailboxArgs(
// set the direction when submitting // set the direction when submitting
direction: Option[Direction], direction: Option[Direction],
// set a folder for items // set a folder for items
itemFolder: Option[Ident] itemFolder: Option[Ident],
// set a filter for files when importing archives
fileFilter: Option[Glob],
// set a list of tags to apply to new item
tags: Option[List[String]]
) )
object ScanMailboxArgs { object ScanMailboxArgs {

View File

@ -91,7 +91,9 @@ object ReProcessItem {
"", //source-id "", //source-id
None, //folder None, //folder
Seq.empty, Seq.empty,
false false,
None,
None
), ),
Nil Nil
).pure[F] ).pure[F]

View File

@ -47,7 +47,9 @@ object TextExtraction {
_ <- fts.indexData(ctx.logger, (idxItem +: txt.map(_.td)).toSeq: _*) _ <- fts.indexData(ctx.logger, (idxItem +: txt.map(_.td)).toSeq: _*)
dur <- start dur <- start
_ <- ctx.logger.info(s"Text extraction finished in ${dur.formatExact}") _ <- ctx.logger.info(s"Text extraction finished in ${dur.formatExact}")
} yield item.copy(metas = txt.map(_.am), tags = txt.flatMap(_.tags).distinct.toList) } yield item
.copy(metas = txt.map(_.am))
.appendTags(txt.flatMap(_.tags).distinct.toList)
} }
// -- helpers // -- helpers

View File

@ -255,7 +255,9 @@ object ScanMailboxTask {
s"mailbox-${ctx.args.account.user.id}", s"mailbox-${ctx.args.account.user.id}",
args.itemFolder, args.itemFolder,
Seq.empty, Seq.empty,
true true,
args.fileFilter,
args.tags.getOrElse(Nil)
) )
data = OUpload.UploadData( data = OUpload.UploadData(
multiple = false, multiple = false,

View File

@ -3499,6 +3499,14 @@ components:
The folder id that is applied to items resulting from The folder id that is applied to items resulting from
importing mails. If the folder id is not valid when the importing mails. If the folder id is not valid when the
task executes, items have no folder set. task executes, items have no folder set.
tags:
$ref: "#/components/schemas/StringList"
fileFilter:
description: |
A glob to filter attachments to import.
type: string
format: glob
ImapSettingsList: ImapSettingsList:
description: | description: |
A list of user email settings. A list of user email settings.
@ -4256,6 +4264,18 @@ components:
A folderId can be given, the item is placed into this folder A folderId can be given, the item is placed into this folder
after creation. after creation.
The `fileFilter` is an optional glob for filtering files to
import. Only applicable if archive files are uploaded. It
applies to all of them. For example, to only import pdf files
when uploading e-mails, use `*.pdf`. If the pattern doesn't
contain a slash `/`, then it is applied to all file names.
Otherwise it is applied to the complete path in the archive
(useful for zip files). Note that the archive file itself is
always saved completely, too.
The `tags` input allows to provide tags that should be applied
to the item being created. This only works if the tags already
exist. It is possible to specify their ids or names.
required: required:
- multiple - multiple
properties: properties:
@ -4271,6 +4291,11 @@ components:
skipDuplicates: skipDuplicates:
type: boolean type: boolean
default: false default: false
tags:
$ref: "#/components/schemas/StringList"
fileFilter:
type: string
format: glob
Collective: Collective:
description: | description: |

View File

@ -310,13 +310,15 @@ trait Conversions {
sourceName, sourceName,
m.folder, m.folder,
validFileTypes, validFileTypes,
m.skipDuplicates.getOrElse(false) m.skipDuplicates.getOrElse(false),
m.fileFilter,
m.tags.map(_.items).getOrElse(Nil)
) )
) )
) )
) )
.getOrElse( .getOrElse(
(true, UploadMeta(None, sourceName, None, validFileTypes, false)).pure[F] (true, UploadMeta(None, sourceName, None, validFileTypes, false, None, Nil)).pure[F]
) )
val files = mp.parts val files = mp.parts

View File

@ -113,7 +113,9 @@ object ScanMailboxRoutes {
settings.targetFolder, settings.targetFolder,
settings.deleteMail, settings.deleteMail,
settings.direction, settings.direction,
settings.itemFolder settings.itemFolder,
settings.fileFilter,
settings.tags.map(_.items)
) )
) )
) )
@ -141,6 +143,8 @@ object ScanMailboxRoutes {
task.args.targetFolder, task.args.targetFolder,
task.args.deleteMail, task.args.deleteMail,
task.args.direction, task.args.direction,
task.args.itemFolder task.args.itemFolder,
task.args.tags.map(StringList.apply),
task.args.fileFilter
) )
} }