Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
### Added

- Added barcode and QR code support
- Cell overflow options

### Changed

- Shape (line) in Migration Model Example moved to header part of the document to avoid collision with new and dynamic content
- **Breaking** Pages in Interactive output no longer create standalone template .jld file, but are still taken into
account when distributing content to Interactive flows. Templates also work directly with areas in its content.

### Fixed

- First match snippet in Designer output rendered as an inline first match flow to better fit its inline nature
- Wrapping cell content to block in Interactive output for specific cases
- Image dimensions in Interactive can be editable even without specified height or width

## [17.0.21] - 2026-05-07

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static void run(Migration migration, Path path) {

areasFile.withWriter { writer ->
def headers = [
Mapping.displayHeader("templateId", true),
Mapping.displayHeader("templateId", false),
Mapping.displayHeader("templateName", true),
Mapping.displayHeader("pageId", false),
Mapping.displayHeader("pageName", true),
Expand All @@ -63,6 +63,11 @@ static void run(Migration migration, Path path) {
writer.writeLine(buildArea(migration, idx, area, page, template))
}
}

def directAreas = template.content.findAll { it instanceof Area } as List<Area>
directAreas.eachWithIndex { area, idx ->
writer.writeLine(buildArea(migration, idx, area, null, template))
}
}

if (usedPageIds.size() != pageIds.size()) {
Expand All @@ -83,8 +88,8 @@ static String buildArea(Migration migration, Number idx, Area area, DocumentObje
def builder = new StringBuilder()
builder.append(Csv.serialize(template?.id) + ",")
builder.append(Csv.serialize(template?.name) + ",")
builder.append(Csv.serialize(page.id) + ",")
builder.append(Csv.serialize(page.name) + ",")
builder.append(Csv.serialize(page?.id) + ",")
builder.append(Csv.serialize(page?.name) + ",")
builder.append(Csv.serialize(area.interactiveFlowName) + ",")
builder.append(Csv.serialize(area.flowToNextPage) + ",")
builder.append(Csv.serialize(area.position.x) + ",")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
//! ---
//! displayName: Import Areas
//! category: Mapping
//! description: Import areas with modified interactive flow names to their respective pages
//! description: Import areas with modified interactive flow names to their respective pages and templates
//! target: gradle
//! ---
package com.quadient.migration.example.common.mapping

import com.quadient.migration.api.Migration
import com.quadient.migration.api.dto.migrationmodel.Area
import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.example.common.util.Csv
Expand All @@ -26,27 +25,29 @@ static void run(Migration migration, Path path) {
def fileLines = path.toFile().readLines()
def columnNames = Csv.parseColumnNames(fileLines.removeFirst()).collect { Mapping.normalizeHeader(it) }

DocumentObject currentPage = null
DocumentObject currentDocumentObject = null
MappingItem.Area mapping = null
int areaIndex = 0
for (line in fileLines) {
def values = Csv.getCells(line, columnNames)

def pageId = Csv.deserialize(values.get("pageId"), String.class)
def templateId = Csv.deserialize(values.get("templateId"), String.class)
def documentObjectId = pageId ?: templateId

if (currentPage?.id != pageId) {
if (currentPage != null) {
migration.mappingRepository.upsert(currentPage.id, mapping)
migration.mappingRepository.applyAreaMapping(currentPage.id)
if (currentDocumentObject?.id != documentObjectId) {
if (currentDocumentObject != null) {
migration.mappingRepository.upsert(currentDocumentObject.id, mapping)
migration.mappingRepository.applyAreaMapping(currentDocumentObject.id)
}

def pageModel = migration.documentObjectRepository.find(pageId)
if (!pageModel) {
throw new IllegalStateException("Page '${pageId}' not found.")
def documentObjectModel = migration.documentObjectRepository.find(documentObjectId)
if (!documentObjectModel) {
throw new IllegalStateException("Document object '${documentObjectId}' not found.")
}

mapping = migration.mappingRepository.getAreaMapping(pageId)
currentPage = pageModel
mapping = migration.mappingRepository.getAreaMapping(documentObjectId)
currentDocumentObject = documentObjectModel
areaIndex = 0
}

Expand All @@ -59,8 +60,8 @@ static void run(Migration migration, Path path) {
areaIndex++
}

if (currentPage != null) {
migration.mappingRepository.upsert(currentPage.id, mapping)
migration.mappingRepository.applyAreaMapping(currentPage.id)
if (currentDocumentObject != null) {
migration.mappingRepository.upsert(currentDocumentObject.id, mapping)
migration.mappingRepository.applyAreaMapping(currentDocumentObject.id)
}
}
23 changes: 22 additions & 1 deletion migration-examples/src/test/groovy/AreasExportTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class AreasExportTest {
AreasExport.run(migration, mappingFile)

def expected = """\
templateId (read-only),templateName (read-only),pageId,pageName (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),contentPreview (read-only)
templateId,templateName (read-only),pageId,pageName (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),contentPreview (read-only)
full tmpl,,full page,,test flow2,false,0mm,0mm,0mm,0mm,
full tmpl,,full page,,test flow3,true,0mm,0mm,0mm,0mm,
full tmpl,,full page,,,false,0mm,0mm,0mm,0mm,
Expand All @@ -55,6 +55,27 @@ class AreasExportTest {
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}

@Test
void exportTemplateDirectAreas() {
Path mappingFile = Paths.get(dir.path, "testProject.csv")
when(migration.mappingRepository.getAreaMapping(any())).thenReturn(new MappingItem.Area(null, [:], [:]))
when((migration.documentObjectRepository as DocumentObjectRepository).list(any())).thenReturn([
new DocumentObjectBuilder("tmpl with areas", DocumentObjectType.Template)
.content([createArea("Address Content"), createArea(null, true), createArea("Footer")])
.build(),
])

AreasExport.run(migration, mappingFile)

def expected = """\
templateId,templateName (read-only),pageId,pageName (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),contentPreview (read-only)
tmpl with areas,,,,Address Content,false,0mm,0mm,0mm,0mm,
tmpl with areas,,,,,true,0mm,0mm,0mm,0mm,
tmpl with areas,,,,Footer,false,0mm,0mm,0mm,0mm,
""".stripIndent()
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}

static Area createArea(String flowName, Boolean flowToNextPage = false) {
def areaBuilder = new AreaBuilder()
.position(new Position(Size.ofMillimeters(0), Size.ofMillimeters(0), Size.ofMillimeters(0), Size.ofMillimeters(0)))
Expand Down
26 changes: 26 additions & 0 deletions migration-examples/src/test/groovy/AreasImportTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,32 @@ class AreasImportTest {
verify(migration.mappingRepository).applyAreaMapping("page3")
}

@Test
void importTemplateDirectAreas() {
Path mappingFile = Paths.get(dir.path, "testProject.csv")

when(migration.mappingRepository.getAreaMapping("tmpl1")).thenReturn(new MappingItem.Area(null, [:], [:]))

when(migration.documentObjectRepository.find("tmpl1")).thenReturn(
new DocumentObjectBuilder("tmpl1", DocumentObjectType.Template)
.content([createArea("Address Content", false), createArea(null, false), createArea("Footer", false)])
.build()
)

def input = """\
templateId,templateName,pageId,pageName,interactiveFlowName,flowToNextPage,x,y,width,height,contentPreview
tmpl1,,,,Updated Address,true,0.0mm,0.0mm,0.0mm,0.0mm,
tmpl1,,,,New Header,false,0.0mm,0.0mm,0.0mm,0.0mm,
tmpl1,,,,Footer,true,0.0mm,0.0mm,0.0mm,0.0mm,
""".stripIndent()
mappingFile.toFile().write(input)

AreasImport.run(migration, mappingFile)

verify(migration.mappingRepository).upsert("tmpl1", new MappingItem.Area(null, [0: "Updated Address", 1: "New Header", 2: "Footer"], [0: true, 1: false, 2: true]))
verify(migration.mappingRepository).applyAreaMapping("tmpl1")
}

static Area createArea(String flowName, boolean flowToNextPage) {
def areaBuilder = new AreaBuilder()
.position(new Position(Size.ofMillimeters(0), Size.ofMillimeters(0), Size.ofMillimeters(0), Size.ofMillimeters(0)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.quadient.migration.api.dto.migrationmodel.TableRow as TableRowModel
import com.quadient.migration.shared.BorderOptions
import com.quadient.migration.shared.CellAlignment
import com.quadient.migration.shared.CellHeight
import com.quadient.migration.shared.CellOverflow
import com.quadient.migration.shared.VariablePath
import com.quadient.migration.shared.LiteralPath
import com.quadient.migration.shared.Size
Expand Down Expand Up @@ -189,12 +190,14 @@ class TableBuilder : RowBuilderBase<TableBuilder>, HasBorder<TableBuilder> {
var height: CellHeight? = null
override var border: BorderOptions? = null
var alignment: CellAlignment? = null
var overflow: CellOverflow? = null

fun mergeLeft(value: Boolean) = apply { mergeLeft = value }
fun mergeUp(value: Boolean) = apply { mergeUp = value }
fun heightFixed(size: Size) = apply { height = CellHeight.Fixed(size) }
fun heightCustom(minHeight: Size, maxHeight: Size) = apply { height = CellHeight.Custom(minHeight, maxHeight) }
fun alignment(alignment: CellAlignment) = apply { this.alignment = alignment }
fun overflow(overflow: CellOverflow) = apply { this.overflow = overflow }

fun build(): Table.Cell {
return Table.Cell(
Expand All @@ -204,6 +207,7 @@ class TableBuilder : RowBuilderBase<TableBuilder>, HasBorder<TableBuilder> {
height = height,
border = border,
alignment = alignment,
overflow = overflow,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.quadient.migration.persistence.migrationmodel.TableEntity
import com.quadient.migration.shared.BorderOptions
import com.quadient.migration.shared.CellAlignment
import com.quadient.migration.shared.CellHeight
import com.quadient.migration.shared.CellOverflow
import com.quadient.migration.shared.VariablePath
import com.quadient.migration.shared.Size
import com.quadient.migration.shared.TableAlignment
Expand Down Expand Up @@ -126,6 +127,7 @@ data class Table(
val height: CellHeight?,
val border: BorderOptions? = null,
val alignment: CellAlignment? = null,
val overflow: CellOverflow? = null,
) : RefValidatable {
override fun collectRefs(): List<Ref> {
return content.flatMap {
Expand All @@ -145,6 +147,7 @@ data class Table(
height = cell.height,
border = cell.border,
alignment = cell.alignment,
overflow = cell.overflow,
)
}
}
Expand All @@ -157,6 +160,7 @@ data class Table(
height = height,
border = border,
alignment = alignment,
overflow = overflow,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.quadient.migration.persistence.migrationmodel
import com.quadient.migration.shared.BorderOptions
import com.quadient.migration.shared.CellAlignment
import com.quadient.migration.shared.CellHeight
import com.quadient.migration.shared.CellOverflow
import com.quadient.migration.shared.Color
import com.quadient.migration.shared.VariablePath
import com.quadient.migration.shared.Position
Expand Down Expand Up @@ -64,6 +65,7 @@ data class TableEntity(
val height: CellHeight? = null,
val border: BorderOptions? = null,
val alignment: CellAlignment? = null,
val overflow: CellOverflow? = null,
)

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.quadient.migration.service.ipsclient.OperationResult
import com.quadient.migration.service.resolveTarget
import com.quadient.migration.shared.IcmPath
import com.quadient.migration.shared.Jrd
import com.quadient.migration.shared.DocumentObjectType
import kotlin.time.Clock
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.eq
Expand Down Expand Up @@ -88,14 +89,17 @@ class InteractiveDeployClient(
}

override fun shouldIncludeDependency(documentObject: DocumentObject): Boolean {
return documentObject.internal != true
return documentObject.type != DocumentObjectType.Page && documentObject.internal != true
}

override fun getAllDocumentObjectsToDeploy(): List<DocumentObject> {
return documentObjectRepository.list(
DocumentObjectTable.skip.extract<String>("skipped") eq "false" and DocumentObjectTable.internal.eq(
false
)
(DocumentObjectTable.type inList listOf(
DocumentObjectType.Template.toString(),
DocumentObjectType.Block.toString(),
DocumentObjectType.Section.toString(),
DocumentObjectType.Snippet.toString()
) and DocumentObjectTable.internal.eq(false) and (DocumentObjectTable.skip.extract<String>("skipped") eq "false"))
)
}

Expand Down Expand Up @@ -127,7 +131,7 @@ class InteractiveDeployClient(
}
require(error.isEmpty()) { error }

return documentObjects
return documentObjects.filter { it.type != DocumentObjectType.Page }
}

private fun deployDisplayRules(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import com.quadient.migration.shared.AttachmentType
import com.quadient.migration.shared.BorderOptions
import com.quadient.migration.shared.CellAlignment
import com.quadient.migration.shared.CellHeight
import com.quadient.migration.shared.CellOverflow
import com.quadient.migration.shared.Function
import com.quadient.migration.shared.Group
import com.quadient.migration.shared.IcmPath
Expand Down Expand Up @@ -408,7 +409,7 @@ abstract class InspireDocumentObjectBuilder(
val singleFlow = if (this.size == 1) {
this[0]
} else {
val sectionFlow = layout.addFlow().setType(Flow.Type.SIMPLE).setSectionFlow(true)
val sectionFlow = layout.addFlow().setType(Flow.Type.SIMPLE).setSectionFlow(true).setWebEditingType(SECTION)
flowName?.let { sectionFlow.setName(it) }

val sectionFlowText = sectionFlow.addParagraph().addText()
Expand Down Expand Up @@ -655,7 +656,8 @@ abstract class InspireDocumentObjectBuilder(

protected fun getOrBuildImage(layout: Layout, imageModel: Image, alternateText: String? = null): WfdXmlImage {
val image = getImageByName(layout, imageModel.nameOrId()) ?: layout.addImage().setName(imageModel.nameOrId())
.setImageLocation(getImagePath(imageModel).toString(), LocationType.ICM)
.setImageLocation(getImagePath(imageModel).toString(), LocationType.ICM).setUseResizeWidth(true)
.setUseResizeHeight(true)

val options = imageModel.options
if (options != null) {
Expand Down Expand Up @@ -1125,15 +1127,13 @@ abstract class InspireDocumentObjectBuilder(
val cellContentFlow = buildDocumentContentAsSingleFlow(
layout, variableStructure, cellModel.content, null, null, languages
)
val cellFlow =
if (cellContentFlow.type === Flow.Type.SELECT_BY_INLINE_CONDITION || cellContentFlow.type === Flow.Type.SELECT_BY_CONDITION) {
layout.addFlow().setType(Flow.Type.SIMPLE).setSectionFlow(true)
.setWebEditingType(SECTION)
val cellFlow = if (cellContentFlow.type !== Flow.Type.SIMPLE) {
layout.addFlow().setType(Flow.Type.SIMPLE).setSectionFlow(true).setWebEditingType(SECTION)
.also { it.addParagraph().addText().appendFlow(cellContentFlow) }
} else cellContentFlow

val cell = layout.addCell().setSpanLeft(cellModel.mergeLeft).setSpanUp(cellModel.mergeUp)
.setFlowToNextPage(true).setFlow(cellFlow)
.setFlowToNextPage(cellModel.overflow != CellOverflow.MoveCellToNextPage).setFlow(cellFlow)

when (cellModel.height) {
is CellHeight.Custom -> {
Expand Down
Loading
Loading