Skip to content

Commit

Permalink
Merge pull request #325 from jp7677/container-sections
Browse files Browse the repository at this point in the history
Add support for documentation sections on containers
  • Loading branch information
jp7677 authored Oct 20, 2023
2 parents 5312147 + 74a9f96 commit 7b64727
Show file tree
Hide file tree
Showing 26 changed files with 342 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Inner workings

This is how this thing works.
1 change: 1 addition & 0 deletions docs/example/workspace.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
webApplication = container "Web Application" "Delivers the static content and the Internet banking single page application." "Java and Spring MVC"
apiApplication = container "API Application" "Provides Internet banking functionality via a JSON/HTTPS API." "Java and Spring MVC" {
!adrs internet-banking-system/api-application/adr
!docs internet-banking-system/api-application/docs
signinController = component "Sign In Controller" "Allows users to sign in to the Internet Banking System." "Spring MVC Rest Controller"
accountsSummaryController = component "Accounts Summary Controller" "Provides customers with a summary of their bank accounts." "Spring MVC Rest Controller"
resetPasswordController = component "Reset Password Controller" "Allows users to reset their passwords with a single use URL." "Spring MVC Rest Controller"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ fun SoftwareSystem.hasContainerDecisions() = containers.any { it.hasDecisions()

fun SoftwareSystem.hasDocumentationSections() = documentation.sections.size >= 2

fun SoftwareSystem.hasContainerDocumentationSections() = containers.any { it.hasSections() }

fun Container.hasDecisions() = documentation.decisions.isNotEmpty()

fun Container.hasSections() = documentation.sections.isNotEmpty()

fun ViewSet.hasSystemContextViews(softwareSystem: SoftwareSystem) =
systemContextViews.any { it.softwareSystem == softwareSystem }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,22 @@ private fun generateHtmlFiles(context: GeneratorContext, branchDir: File) {
}

it.containers
.filter { container -> container.documentation.decisions.isNotEmpty() }
.forEach { container ->
add { writeHtmlFile(branchDir, SoftwareSystemContainerDecisionsPageViewModel(context, container)) }
container.documentation.decisions.forEach { decision ->
add { writeHtmlFile(branchDir, SoftwareSystemContainerDecisionPageViewModel(context, container, decision)) }
}
.filter { container -> container.documentation.decisions.isNotEmpty() }
.forEach { container ->
add { writeHtmlFile(branchDir, SoftwareSystemContainerDecisionsPageViewModel(context, container)) }
container.documentation.decisions.forEach { decision ->
add { writeHtmlFile(branchDir, SoftwareSystemContainerDecisionPageViewModel(context, container, decision)) }
}
}

it.containers
.filter { container -> container.documentation.sections.isNotEmpty() }
.forEach { container ->
add { writeHtmlFile(branchDir, SoftwareSystemContainerSectionsPageViewModel(context, container)) }
container.documentation.sections.forEach { section ->
add { writeHtmlFile(branchDir, SoftwareSystemContainerSectionPageViewModel(context, container, section)) }
}
}

it.documentation.sections.filter { section -> section.order != 1 }.forEach { section ->
add { writeHtmlFile(branchDir, SoftwareSystemSectionPageViewModel(context, it, section)) }
Expand All @@ -173,6 +182,8 @@ private fun writeHtmlFile(exportDir: File, viewModel: PageViewModel) {
is SoftwareSystemContainerPageViewModel -> softwareSystemContainerPage(viewModel)
is SoftwareSystemContainerDecisionPageViewModel -> softwareSystemContainerDecisionPage(viewModel)
is SoftwareSystemContainerDecisionsPageViewModel -> softwareSystemContainerDecisionsPage(viewModel)
is SoftwareSystemContainerSectionPageViewModel -> softwareSystemContainerSectionPage(viewModel)
is SoftwareSystemContainerSectionsPageViewModel -> softwareSystemContainerSectionsPage(viewModel)
is SoftwareSystemComponentPageViewModel -> softwareSystemComponentPage(viewModel)
is SoftwareSystemDeploymentPageViewModel -> softwareSystemDeploymentPage(viewModel)
is SoftwareSystemDependenciesPageViewModel -> softwareSystemDependenciesPage(viewModel)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,32 +1,5 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.model.SoftwareSystem
import nl.avisi.structurizr.site.generatr.hasDecisions

data class DecisionTabViewModel(val pageViewModel: SoftwareSystemPageViewModel, val title: String, val url: String) {
val link = LinkViewModel(pageViewModel, title, url, true)
}

fun SoftwareSystemPageViewModel.createDecisionsTabViewModel(softwareSystem: SoftwareSystem, tab: SoftwareSystemPageViewModel.Tab): List<DecisionTabViewModel> {
val tabs = buildList<DecisionTabViewModel> {
if (softwareSystem.hasDecisions()) {
add(DecisionTabViewModel(
this@createDecisionsTabViewModel,
"System",
SoftwareSystemPageViewModel.url(softwareSystem, tab)
))
}
softwareSystem
.containers
.filter { it.hasDecisions() }
.map {
DecisionTabViewModel(
this@createDecisionsTabViewModel,
it.name,
SoftwareSystemContainerDecisionsPageViewModel.url(it)
)
}
.forEach { add(it) }
}
return tabs
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.documentation.Decision
import com.structurizr.model.SoftwareSystem
import nl.avisi.structurizr.site.generatr.hasDecisions
import nl.avisi.structurizr.site.generatr.site.formatDate

fun PageViewModel.createDecisionsTableViewModel(decisions: Collection<Decision>, hrefFactory: (Decision) -> String) =
Expand All @@ -17,3 +19,29 @@ fun PageViewModel.createDecisionsTableViewModel(decisions: Collection<Decision>,
)
}
}

fun SoftwareSystemPageViewModel.createDecisionsTabViewModel(
softwareSystem: SoftwareSystem,
tab: SoftwareSystemPageViewModel.Tab
) = buildList {
if (softwareSystem.hasDecisions()) {
add(
DecisionTabViewModel(
this@createDecisionsTabViewModel,
"System",
SoftwareSystemPageViewModel.url(softwareSystem, tab)
)
)
}
softwareSystem
.containers
.filter { it.hasDecisions() }
.map {
DecisionTabViewModel(
this@createDecisionsTabViewModel,
it.name,
SoftwareSystemContainerDecisionsPageViewModel.url(it)
)
}
.forEach { add(it) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package nl.avisi.structurizr.site.generatr.site.model

data class SectionTabViewModel(val pageViewModel: SoftwareSystemPageViewModel, val title: String, val url: String) {
val link = LinkViewModel(pageViewModel, title, url, true)
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,47 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.documentation.Section
import com.structurizr.model.SoftwareSystem
import nl.avisi.structurizr.site.generatr.hasDocumentationSections
import nl.avisi.structurizr.site.generatr.hasSections

fun PageViewModel.createSectionsTableViewModel(sections: Collection<Section>, hrefFactory: (Section) -> String) =
fun PageViewModel.createSectionsTableViewModel(sections: Collection<Section>, dropFirst: Boolean = true, hrefFactory: (Section) -> String) =
TableViewModel.create {
headerRow(headerCell("#"), headerCell("Title"))
sections
.sortedBy { it.order }
.drop(1)
.associateWith { it.order - 1 }
.drop(if (dropFirst) 1 else 0)
.associateWith { if (dropFirst) it.order - 1 else it.order }
.forEach { (section, index) ->
bodyRow(
cellWithIndex(index.toString()),
cellWithLink(this@createSectionsTableViewModel, section.contentTitle(), hrefFactory(section))
)
}
}

fun SoftwareSystemPageViewModel.createSectionsTabViewModel(
softwareSystem: SoftwareSystem,
tab: SoftwareSystemPageViewModel.Tab
) = buildList {
if (softwareSystem.hasDocumentationSections()) {
add(
SectionTabViewModel(
this@createSectionsTabViewModel,
"System",
SoftwareSystemPageViewModel.url(softwareSystem, tab)
)
)
}
softwareSystem
.containers
.filter { it.hasSections() }
.map {
SectionTabViewModel(
this@createSectionsTabViewModel,
it.name,
SoftwareSystemContainerSectionsPageViewModel.url(it)
)
}
.forEach { add(it) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class SoftwareSystemContainerDecisionsPageViewModel(generatorContext: GeneratorC
val decisionTabs = createDecisionsTabViewModel(container.softwareSystem, Tab.DECISIONS)

companion object {
fun url(container: Container) =
"${url(container.softwareSystem, Tab.DECISIONS)}/${container.name.normalize()}"
fun url(container: Container) = "${url(container.softwareSystem, Tab.DECISIONS)}/${container.name.normalize()}"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.documentation.Section
import com.structurizr.model.Container
import nl.avisi.structurizr.site.generatr.normalize
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

class SoftwareSystemContainerSectionPageViewModel(
generatorContext: GeneratorContext,
container: Container,
section: Section
) : SoftwareSystemPageViewModel(generatorContext, container.softwareSystem, Tab.SECTIONS) {
override val url = url(container, section)

val content = markdownToHtml(this, section.content, generatorContext.svgFactory)

companion object {
fun url(container: Container, section: Section) =
"${url(container.softwareSystem, Tab.SECTIONS)}/${container.name.normalize()}/${section.order}"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.model.Container
import nl.avisi.structurizr.site.generatr.hasSections
import nl.avisi.structurizr.site.generatr.normalize
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

class SoftwareSystemContainerSectionsPageViewModel(generatorContext: GeneratorContext, container: Container) :
SoftwareSystemPageViewModel(generatorContext, container.softwareSystem, Tab.SECTIONS) {
override val url = url(container)
val sectionsTable = createSectionsTableViewModel(container.documentation.sections, dropFirst = false) {
"$url/${it.order}"
}

val visible = container.hasSections()
val sectionsTabs = createSectionsTabViewModel(container.softwareSystem, Tab.SECTIONS)

companion object {
fun url(container: Container) = "${url(container.softwareSystem, Tab.SECTIONS)}/${container.name.normalize()}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ class SoftwareSystemDecisionsPageViewModel(generatorContext: GeneratorContext, s
val onlyContainersDecisionsVisible = !softwareSystemDecisionsVisible and containerDecisionsVisible

val decisionTabs = createDecisionsTabViewModel(softwareSystem, Tab.DECISIONS)

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ open class SoftwareSystemPageViewModel(
Tab.COMPONENT -> generatorContext.workspace.views.hasComponentViews(softwareSystem)
Tab.DEPLOYMENT -> generatorContext.workspace.views.hasDeploymentViews(softwareSystem)
Tab.DECISIONS -> softwareSystem.hasDecisions() or softwareSystem.hasContainerDecisions()
Tab.SECTIONS -> softwareSystem.hasDocumentationSections()
Tab.SECTIONS -> softwareSystem.hasDocumentationSections() or softwareSystem.hasContainerDocumentationSections()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.model.SoftwareSystem
import nl.avisi.structurizr.site.generatr.hasContainerDocumentationSections
import nl.avisi.structurizr.site.generatr.hasDocumentationSections
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

Expand All @@ -9,5 +10,12 @@ class SoftwareSystemSectionsPageViewModel(generatorContext: GeneratorContext, so
val sectionsTable = createSectionsTableViewModel(softwareSystem.documentation.sections) {
"$url/${it.order}"
}
val visible = softwareSystem.hasDocumentationSections()

private val containerSectionsVisible = softwareSystem.hasContainerDocumentationSections()
val softwareSystemSectionsVisible = softwareSystem.hasDocumentationSections()

val visible = softwareSystemSectionsVisible or containerSectionsVisible
val onlyContainerSectionsVisible = !softwareSystemSectionsVisible and containerSectionsVisible

val sectionTabs = createSectionsTabViewModel(softwareSystem, Tab.SECTIONS)
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ private fun HTML.bodyFragment(viewModel: PageViewModel, block: DIV.() -> Unit) {

mermaidScript(viewModel)

if (viewModel.includeTreeview){
script(type = ScriptType.textJavaScript,src = "../" + "/treeview.js".asUrlToFile(viewModel.url)) { }
if (viewModel.includeTreeview) {
script(type = ScriptType.textJavaScript, src = "../" + "/treeview.js".asUrlToFile(viewModel.url)) { }
script(type = ScriptType.textJavaScript) { unsafe { +"listree();" } }
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package nl.avisi.structurizr.site.generatr.site.views

import kotlinx.html.HTML
import nl.avisi.structurizr.site.generatr.site.model.SoftwareSystemContainerSectionPageViewModel

fun HTML.softwareSystemContainerSectionPage(viewModel: SoftwareSystemContainerSectionPageViewModel) {
softwareSystemPage(viewModel) {
rawHtml(viewModel.content)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nl.avisi.structurizr.site.generatr.site.views

import kotlinx.html.HTML
import kotlinx.html.div
import kotlinx.html.li
import kotlinx.html.ul
import nl.avisi.structurizr.site.generatr.site.model.SoftwareSystemContainerSectionsPageViewModel

fun HTML.softwareSystemContainerSectionsPage(viewModel: SoftwareSystemContainerSectionsPageViewModel) {
if (viewModel.visible)
softwareSystemPage(viewModel) {
div(classes = "tabs") {
ul(classes = "m-0") {
viewModel.sectionsTabs
.forEach {
li(classes = if (it.link.active) "is-active" else null) {
link(it.link)
}
}
}
}
table(viewModel.sectionsTable)
}
else
redirectUpPage()
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ fun HTML.softwareSystemDecisionsPage(viewModel: SoftwareSystemDecisionsPageViewM
table(viewModel.decisionsTable)
}
}
}
else
} else
redirectUpPage()
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
package nl.avisi.structurizr.site.generatr.site.views

import kotlinx.html.HTML
import kotlinx.html.div
import kotlinx.html.li
import kotlinx.html.ul
import nl.avisi.structurizr.site.generatr.site.model.SoftwareSystemSectionsPageViewModel

fun HTML.softwareSystemSectionsPage(viewModel: SoftwareSystemSectionsPageViewModel) {
if (viewModel.visible)
if (viewModel.onlyContainerSectionsVisible) {
redirectRelative(
viewModel.sectionTabs.first().link.relativeHref
)
} else if (viewModel.visible)
softwareSystemPage(viewModel) {
table(viewModel.sectionsTable)
div(classes = "tabs") {
ul(classes = "m-0") {
viewModel.sectionTabs
.forEach {
li(classes = if (it.link.active) "is-active" else null) {
link(it.link)
}
}
}
}

if (viewModel.softwareSystemSectionsVisible) {
table(viewModel.sectionsTable)
}
}
else
redirectUpPage()
Expand Down
Loading

0 comments on commit 7b64727

Please sign in to comment.