Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for image Views. #338

Closed
wants to merge 16 commits into from
Closed
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
Binary file added docs/example/atm/atm-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 19 additions & 68 deletions docs/example/workspace.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
}

customer = person "Personal Banking Customer" "A customer of the bank, with personal bank accounts." "Customer"

acquirer = softwaresystem "Acquirer" "Facilitates PIN transactions for merchants." "External System"

group "Big Bank plc" {
Expand Down Expand Up @@ -115,7 +114,6 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
softwareSystemInstance mainframe
}
}

}

deploymentEnvironment "Live" {
Expand All @@ -127,7 +125,6 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
liveSinglePageApplicationInstance = containerInstance singlePageApplication
}
}

deploymentNode "Big Bank plc" "" "Big Bank plc data center" {
deploymentNode "bigbank-web***" "" "Ubuntu 16.04 LTS" "" 4 {
deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
Expand All @@ -139,7 +136,6 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
liveApiApplicationInstance = containerInstance apiApplication
}
}

deploymentNode "bigbank-db01" "" "Ubuntu 16.04 LTS" {
primaryDatabaseServer = deploymentNode "Oracle - Primary" "" "Oracle 12c" {
livePrimaryDatabaseInstance = containerInstance database
Expand All @@ -154,7 +150,6 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
softwareSystemInstance mainframe
}
}

primaryDatabaseServer -> secondaryDatabaseServer "Replicates data to"
}
}
Expand All @@ -167,63 +162,41 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
"generatr.style.colors.secondary" "#ffffff"
"generatr.style.faviconPath" "site/favicon.ico"
"generatr.style.logoPath" "site/logo.png"

// Absolute URL's like "https://example.com/custom.css" are also supported
"generatr.style.customStylesheet" "site/custom.css"

"generatr.search.language" "en"
"generatr.svglink.target" "_self"

// Full list of available "generatr.markdown.flexmark.extensions"
// "Abbreviation,Admonition,AnchorLink,Aside,Attributes,Autolink,Definition,Emoji,EnumeratedReference,Footnotes,GfmIssues,GfmStrikethroughSubscript,GfmTaskList,GfmUsers,GitLab,Ins,Macros,MediaTags,ResizableImage,Superscript,Tables,TableOfContents,SimulatedTableOfContents,Typographic,WikiLinks,XWikiMacro,YAMLFrontMatter,YouTubeLink"
// see https://github.com/vsch/flexmark-java/wiki/Extensions
// ATTENTION:
// * "generatr.markdown.flexmark.extensions" values must be separated by comma
// * it's not possible to use "GitLab" and "ResizableImage" extensions together
// default behaviour, if no generatr.markdown.flexmark.extensions property is specified, is to load the Tables extension only
"generatr.site.nestGroups" "false"
"generatr.markdown.flexmark.extensions" "Abbreviation,Admonition,AnchorLink,Attributes,Autolink,Definition,Emoji,Footnotes,GfmTaskList,GitLab,MediaTags,Tables,TableOfContents,Typographic"

"generatr.site.exporter" "c4"
"generatr.site.externalTag" "External System"
"generatr.site.nestGroups" "false"
}

systemlandscape "SystemLandscape" {
include *
autoLayout
!script groovy {
workspace.views.createDefaultViews()
}

systemcontext internetBankingSystem "SystemContext" {
include *
animation {
internetBankingSystem
customer
mainframe
email
}
autoLayout
image atm {
image atm/atm-example.png
title "ATM System"
description "Image View to show how the ATM system works internally"
}

container internetBankingSystem "Containers" {
include *
animation {
customer mainframe email
webApplication
singlePageApplication
mobileApp
apiApplication
database
}
autoLayout
image database {
image internet-banking-system/database-erd-example.jpg
title "Database Entity Relationship Diagram"
description "Image View to show the ERD diagram for the database container"
}

image accountsSummaryController {
image internet-banking-system/uml-class-diagram.png
title "Sample ImageView - accountsSummaryController Component"
description "This is a sample imageView for code of a component"
}

component apiApplication "Components" {
systemlandscape "SystemLandscape" {
include *
animation {
singlePageApplication mobileApp database email mainframe
signinController securityComponent
accountsSummaryController mainframeBankingSystemFacade
resetPasswordController emailComponent
}
autoLayout
}

Expand All @@ -237,28 +210,6 @@ workspace "Big Bank plc" "This is an example workspace to illustrate the key fea
autoLayout
}

deployment internetBankingSystem "Development" "DevelopmentDeployment" {
include *
animation {
developerSinglePageApplicationInstance
developerWebApplicationInstance developerApiApplicationInstance
developerDatabaseInstance
}
autoLayout
}

deployment internetBankingSystem "Live" "LiveDeployment" {
include *
animation {
liveSinglePageApplicationInstance
liveMobileAppInstance
liveWebApplicationInstance liveApiApplicationInstance
livePrimaryDatabaseInstance
liveSecondaryDatabaseInstance
}
autoLayout
}

styles {
element "Person" {
color #ffffff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import com.structurizr.Workspace
import com.structurizr.model.Container
import com.structurizr.model.Location
import com.structurizr.model.SoftwareSystem
import com.structurizr.view.ImageView
import com.structurizr.view.ViewSet
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

val Workspace.includedSoftwareSystems: List<SoftwareSystem>
get() = model.softwareSystems.filter {
Expand Down Expand Up @@ -36,14 +38,49 @@ fun Container.hasSections() = documentation.sections.isNotEmpty()
fun ViewSet.hasSystemContextViews(softwareSystem: SoftwareSystem) =
systemContextViews.any { it.softwareSystem == softwareSystem }

fun ViewSet.hasContainerViews(softwareSystem: SoftwareSystem) =
containerViews.any { it.softwareSystem == softwareSystem }
fun ViewSet.hasContainerViews(generatorContext: GeneratorContext, softwareSystem: SoftwareSystem) =
containerViews.any { it.softwareSystem == softwareSystem } || getImagesForSystem(generatorContext.workspace, softwareSystem).isNotEmpty()

fun ViewSet.hasComponentViews(softwareSystem: SoftwareSystem) =
componentViews.any { it.softwareSystem == softwareSystem }
fun ViewSet.hasComponentViews(generatorContext: GeneratorContext, softwareSystem: SoftwareSystem) =
componentViews.any { it.softwareSystem == softwareSystem } || getImagesForContainer(generatorContext.workspace, softwareSystem).isNotEmpty()

fun ViewSet.hasCodeViews(generatorContext: GeneratorContext, softwareSystem: SoftwareSystem) =
componentViews.any { it.softwareSystem == softwareSystem } || getImagesForComponent(generatorContext, softwareSystem).isNotEmpty()

fun ViewSet.hasDynamicViews(softwareSystem: SoftwareSystem) =
dynamicViews.any { it.softwareSystem == softwareSystem }

fun ViewSet.hasDeploymentViews(softwareSystem: SoftwareSystem) =
deploymentViews.any { it.softwareSystem == softwareSystem }

fun getImageViewsForId(workspace: Workspace, id: String): List<ImageView> {
return workspace.views.imageViews
.filter { it.elementId == id }
.sortedBy { it.key }
}

fun getImagesForSystem(workspace: Workspace, softwareSystem: SoftwareSystem): List<ImageView> {
return workspace.views.imageViews
.filter { it.elementId == softwareSystem.id }
.sortedBy { it.key }
}

fun getImagesForContainer(workspace: Workspace, softwareSystem: SoftwareSystem): List<ImageView> {
val images = mutableListOf<ImageView>()
softwareSystem.containers.forEach{ container ->
images += workspace.views.imageViews
.filter { it.elementId == container.id }
}
return images
}

fun getImagesForComponent(generatorContext: GeneratorContext, softwareSystem: SoftwareSystem): List<ImageView> {
val images = mutableListOf<ImageView>()
softwareSystem.containers.forEach { container ->
container.components.forEach { component ->
images += generatorContext.workspace.views.imageViews
.filter { it.elementId == component.id }
}
}
return images
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.structurizr.export.Diagram
import com.structurizr.export.IndentingWriter
import com.structurizr.export.plantuml.C4PlantUMLExporter
import com.structurizr.export.plantuml.StructurizrPlantUMLExporter
import com.structurizr.model.Component
import com.structurizr.model.Container
import com.structurizr.model.Element
import com.structurizr.model.SoftwareSystem
Expand Down Expand Up @@ -78,9 +79,10 @@ private class WriterWithElementLinks(
writeElementFn: (view: ModelView?, element: Element?, writer: IndentingWriter?) -> Unit
) {
val url = when {
needsLinkToSoftwareSystem(element, view) -> getUrlToSoftwareSystem(element)
needsLinkToContainerViews(element, view) -> getUrlToContainerViews(element)
needsLinkToComponentViews(element, view) -> getUrlToComponentViews(element)
needsLinkToSoftwareSystem(element, view) -> getUrlToViewsPage(element?.name?.normalize(), "context")
needsLinkToContainerViews(element, view, workspace) -> getUrlToViewsPage(element?.name?.normalize(), "container")
needsLinkToComponentViews(element, view, workspace) -> getUrlToViewsPage(element?.parent?.name?.normalize(), "component")
needsLinkToCodeViews(element, workspace) -> getUrlToViewsPage(element?.parent?.parent?.name?.normalize(), "code")
else -> null
}

Expand All @@ -93,24 +95,23 @@ private class WriterWithElementLinks(
private fun needsLinkToSoftwareSystem(element: Element?, view: ModelView?) =
element is SoftwareSystem && workspace.includedSoftwareSystems.contains(element) && element != view?.softwareSystem

private fun getUrlToSoftwareSystem(element: Element?): String {
val path = "/${element?.name?.normalize()}/context/".asUrlToDirectory(url)
return "$TEMP_URI$path"
}
private fun needsLinkToContainerViews(element: Element?, view: ModelView?, workspace: Workspace) =
element is SoftwareSystem
&& workspace.includedSoftwareSystems.contains(element)
&& element == view?.softwareSystem
&& ( element.hasContainers || getImageViewsForId(workspace, element.id).isNotEmpty())

private fun needsLinkToContainerViews(element: Element?, view: ModelView?) =
element is SoftwareSystem && workspace.includedSoftwareSystems.contains(element) && element == view?.softwareSystem && element.hasContainers
private fun needsLinkToComponentViews(element: Element?, view: ModelView?, workspace: Workspace) =
element is Container
&& ( element.hasComponents || getImageViewsForId(workspace, element.id).isNotEmpty())
&& view !is ComponentView

private fun getUrlToContainerViews(element: Element?): String {
val path = "/${element?.name?.normalize()}/container/".asUrlToDirectory(url)
return "$TEMP_URI$path"
}
private fun needsLinkToCodeViews(element: Element?, workspace: Workspace) =
element is Component
&& getImageViewsForId(workspace, element.id).isNotEmpty()

private fun needsLinkToComponentViews(element: Element?, view: ModelView?) =
element is Container && element.hasComponents && view !is ComponentView

private fun getUrlToComponentViews(element: Element?): String {
val path = "/${element?.parent?.name?.normalize()}/component/".asUrlToDirectory(url)
private fun getUrlToViewsPage(systemName: String?, page: String): String {
val path = "/$systemName/$page/".asUrlToDirectory(url)
return "$TEMP_URI$path"
}

Expand Down Expand Up @@ -147,7 +148,7 @@ class C4PlantUmlExporterWithElementLinks(workspace: Workspace, url: String) : C4
withElementLinks.writeHeader(view, writer) { v, w -> super.writeHeader(v, w) }
}

override fun writeElement(view: ModelView?, element: Element?, writer: IndentingWriter?) {
override fun writeElement(view: ModelView?, element: Element?, writer: IndentingWriter?) {
withElementLinks.writeElement(view, element, writer) { v, e, w -> super.writeElement(v, e, w) }
}
}
Expand All @@ -162,4 +163,5 @@ class StructurizrPlantUmlExporterWithElementLinks(workspace: Workspace, url: Str
override fun writeElement(view: ModelView?, element: Element?, writer: IndentingWriter?) {
withElementLinks.writeElement(view, element, writer) { v, e, w -> super.writeElement(v, e, w) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ private fun generateHtmlFiles(context: GeneratorContext, branchDir: File) {
add { writeHtmlFile(branchDir, SoftwareSystemContextPageViewModel(context, it)) }
add { writeHtmlFile(branchDir, SoftwareSystemContainerPageViewModel(context, it)) }
add { writeHtmlFile(branchDir, SoftwareSystemComponentPageViewModel(context, it)) }
add { writeHtmlFile(branchDir, SoftwareSystemCodePageViewModel(context, it)) }
add { writeHtmlFile(branchDir, SoftwareSystemDynamicPageViewModel(context, it)) }
add { writeHtmlFile(branchDir, SoftwareSystemDeploymentPageViewModel(context, it)) }
add { writeHtmlFile(branchDir, SoftwareSystemDependenciesPageViewModel(context, it)) }
Expand Down Expand Up @@ -189,6 +190,7 @@ private fun writeHtmlFile(exportDir: File, viewModel: PageViewModel) {
is SoftwareSystemContainerSectionPageViewModel -> softwareSystemContainerSectionPage(viewModel)
is SoftwareSystemContainerSectionsPageViewModel -> softwareSystemContainerSectionsPage(viewModel)
is SoftwareSystemComponentPageViewModel -> softwareSystemComponentPage(viewModel)
is SoftwareSystemCodePageViewModel -> softwareSystemCodePage(viewModel)
is SoftwareSystemDynamicPageViewModel -> softwareSystemDynamicPage(viewModel)
is SoftwareSystemDeploymentPageViewModel -> softwareSystemDeploymentPage(viewModel)
is SoftwareSystemDependenciesPageViewModel -> softwareSystemDependenciesPage(viewModel)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nl.avisi.structurizr.site.generatr.site.model

import com.structurizr.model.SoftwareSystem
import nl.avisi.structurizr.site.generatr.getImagesForComponent
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

class SoftwareSystemCodePageViewModel(generatorContext: GeneratorContext, softwareSystem: SoftwareSystem) :
SoftwareSystemPageViewModel(generatorContext, softwareSystem, Tab.CODE) {
val images = getImagesForComponent(generatorContext,softwareSystem)
val imagesVisible = images.isNotEmpty()
}


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.getImagesForContainer
import nl.avisi.structurizr.site.generatr.hasComponentViews
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

Expand All @@ -10,5 +11,9 @@ class SoftwareSystemComponentPageViewModel(generatorContext: GeneratorContext, s
.filter { it.softwareSystem == softwareSystem }
.sortedBy { it.key }
.map { DiagramViewModel.forView(this, it, generatorContext.svgFactory) }
val visible = generatorContext.workspace.views.hasComponentViews(softwareSystem)
val images = getImagesForContainer(generatorContext.workspace,softwareSystem)
val diagramsVisible = generatorContext.workspace.views.hasComponentViews(generatorContext, softwareSystem)
val imagesVisible = images.isNotEmpty()
}


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.getImagesForSystem
import nl.avisi.structurizr.site.generatr.hasContainerViews
import nl.avisi.structurizr.site.generatr.site.GeneratorContext

Expand All @@ -10,5 +11,7 @@ class SoftwareSystemContainerPageViewModel(generatorContext: GeneratorContext, s
.filter { it.softwareSystem == softwareSystem }
.sortedBy { it.key }
.map { DiagramViewModel.forView(this, it, generatorContext.svgFactory) }
val visible = generatorContext.workspace.views.hasContainerViews(softwareSystem)
val images = getImagesForSystem(generatorContext.workspace,softwareSystem)
val diagramsVisible = generatorContext.workspace.views.hasContainerViews(generatorContext, softwareSystem)
val imagesVisible = images.isNotEmpty()
}
Loading