Skip to content
This repository has been archived by the owner on Jan 10, 2024. It is now read-only.

Honor shapes in C4-Plantuml exporter #21

Closed
dgutson opened this issue Oct 24, 2022 · 12 comments
Closed

Honor shapes in C4-Plantuml exporter #21

dgutson opened this issue Oct 24, 2022 · 12 comments

Comments

@dgutson
Copy link

dgutson commented Oct 24, 2022

This is related to #11 but not exactly.
Now that C4-Plantuml added the robot shape, it would be useful that the exporter honors the Robot shape in styles:

    views {
        styles {
            element "robot_user" {
                shape Robot
            }
        }
    }

That should be translated as the sprite "robot".

@simonbrowndotje
Copy link
Contributor

Since C4-PlantUML doesn't have a robot shape, I'm not sure it makes sense to convert a Structurizr shape into a sprite, particularly since there are multiple robot sprites. So I've done something different instead, which provides you with the ability to choose which sprite you want to use. For example, this DSL:

workspace {

    model {
        user = person "Robot" {
            tags "Robot"
        }
    }

    views {
        systemLandscape {
            include *
            autoLayout
        }

        styles {
            element "Element" {
                background #dd0000
                color #ffffff
            }
            element "Robot" {
                properties {
                    c4plantuml.sprite robot2
                }
            }
        }
        
        properties {
            c4plantuml.tags true
        }
    }
    
}

Will create this C4-PlantUML diagram:

image

There are two things to note here:

  1. You need to add a view property named c4plantuml.tags with a value of true.
  2. Sprites can be defined for an element style via a property named c4plantuml.sprite.

@dgutson
Copy link
Author

dgutson commented Oct 24, 2022

@simonbrowndotje that's great!
Note that C4-Plantuml just added the robot shape (sprite) yesterday. Does this change anything?
plantuml-stdlib/C4-PlantUML#244 where you did comment there.

@simonbrowndotje
Copy link
Contributor

Note that C4-Plantuml just added the robot shape (sprite) yesterday. Does this change anything?

No, that's actually how the above example works ... it's using one of the new robot sprites that were added yesterday.

@dgutson

This comment was marked as off-topic.

@simonbrowndotje

This comment was marked as off-topic.

@dgutson
Copy link
Author

dgutson commented Oct 24, 2022

I think something is broken, now despite I added the property c4plantuml.tags, tags are not added for Systems:

    views {
        properties {
            "c4plantuml.tags" "true"
            "plantuml.legend" "false"
        }

Generated:

Boundary(group_0, "Customer") {
  System(XXX, "YYY", "ZZZ", $tags="Software System")

I tried to add the tag both before the braces, and inside with tags.

Before this change, my tags showed up in the $tags string.

@simonbrowndotje
Copy link
Contributor

It's hard to say what's going on without a full DSL example I'm afraid.

@dgutson
Copy link
Author

dgutson commented Oct 24, 2022

test.dsl:

workspace "Test Product Architecture" "Model of the Test Platform." {

    !identifiers hierarchical

    model {
        group Customer {
            ees_user = person "EES users" "" "users"
            ends_user = person "ENDS user"
            frontend_user = person "FE user"
            webhooks_user = person "Webhooks User" "" "robot_user"
            EAS = softwaresystem "EAS" "Service1" {
                SP = container "Processor" "Something" "Node.js"
                engine = container "Engine" "Processes the data" "Go"

                SP -> engine "Sends data"
                engine -> SP "Send results"
            }

            backend = softwaresystem "Backend" "Backend1" "multi" {
                database = container "DB" "" "MongoDB" "DB"
                app = container "App" "Backend Server" "Node.js"

                app -> database "Uses"
            }

            backend.app -> EAS.SP "Send data"
            EAS.SP -> backend.app "Send results"
        }
    }

    views {
        properties {
            "plantuml.includes" "extra_styles.puml"
            "c4plantuml.tags" "true"
            "plantuml.legend" "false"
        }

        systemlandscape TheSystemLandscape {
            include *
            autoLayout
        }

        theme default

        styles {
            element "DB" {
                shape Cylinder
            }

            element "dataset" {
                background #006400
            }

            element "robot_user" {
                properties {
                    c4plantuml.sprite robot
                }
            }

            element "users" {
                properties {
                    c4plantuml.sprite users
                }
            }
        }
    }
}

stricturizr-TheSystemLandscape.puml:

@startuml
title System Landscape

top to bottom direction

!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4.puml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
!include extra_styles.puml

AddElementTag("Software System", $bgColor="#1168bd", $borderColor="#0b4884", $fontColor="#ffffff", $sprite="")
AddElementTag("Person,users", $bgColor="#08427b", $borderColor="#052e56", $fontColor="#ffffff", $sprite="users")
AddElementTag("Person,robot_user", $bgColor="#08427b", $borderColor="#052e56", $fontColor="#ffffff", $sprite="robot")
AddElementTag("Person", $bgColor="#08427b", $borderColor="#052e56", $fontColor="#ffffff", $sprite="")

AddRelTag("Relationship", $textColor="#707070", $lineColor="#707070")

Boundary(group_0, "Customer") {
  Person(EESusers, "EES users", "", $tags="Person,users")
  System(Backend, "Backend", "Backend1", $tags="Software System")
  Person(ENDSuser, "ENDS user", "", $tags="Person")
  Person(FEuser, "FE user", "", $tags="Person")
  Person(WebhooksUser, "Webhooks User", "", $tags="Person,robot_user")
  System(EAS, "EAS", "Service1", $tags="Software System")
}


Rel_D(Backend, EAS, "Send data", $tags="Relationship")
Rel_D(EAS, Backend, "Send results", $tags="Relationship")
@enduml

The tag "multi" does not show up in the .puml file.

Just for this to compile - extra_styles.puml:

@startuml

!define FONTAWESOME5 https://raw.githubusercontent.com/plantuml/plantuml-stdlib/master/tupadr3/font-awesome-5
!include FONTAWESOME5/users.puml

'do this only if we're generating C4-puml:
!if (%function_exists("AddElementTag"))
AddElementTag("multi", $shadowing="true")
HIDE_STEREOTYPE()
!endif
@enduml

@simonbrowndotje
Copy link
Contributor

There's no element style for multi defined in your workspace, so it's being ignored. I've added support for an element style property named c4plantuml.shadow, for example:

element "multi" {
    properties {
        c4plantuml.shadow true
    }
}

@dgutson
Copy link
Author

dgutson commented Oct 24, 2022

Thanks for adding the shadow attribute!

Regarding the behavior, with a previous version (tag 0f71abe78aa8 built 9hs ago), there was no need for an element style to get the tag in the system:

workspace "Test Product Architecture" "Model of the Test Platform." {

    !identifiers hierarchical

    model {
        group Customer {
            ees_user = person "EES users" "" "users"
            ends_user = person "ENDS user"
            frontend_user = person "FE user"
            webhooks_user = person "Webhooks User" "" "robot_user"
            EAS = softwaresystem "EAS" "Service1" {
                SP = container "Processor" "Something" "Node.js"
                engine = container "Engine" "Processes the data" "Go"

                SP -> engine "Sends data"
                engine -> SP "Send results"
            }

            backend = softwaresystem "Backend" "Backend1" "multi" {
                database = container "DB" "" "MongoDB" "DB"
                app = container "App" "Backend Server" "Node.js"

                app -> database "Uses"
            }

            backend.app -> EAS.SP "Send data"
            EAS.SP -> backend.app "Send results"
        }
    }

    views {
        properties {
            "plantuml.includes" "extra_styles.puml"
            "c4plantuml.tags" "true"
            "plantuml.legend" "false"
        }

        systemlandscape TheSystemLandscape {
            include *
            autoLayout
        }

        theme default

        styles {
            element "DB" {
                shape Cylinder
            }

            element "dataset" {
                background #006400
            }

            element "robot_user" {
                #properties {
                #    c4plantuml.sprite robot
                #}
            }

            element "users" {
                #properties {
                #    c4plantuml.sprite users
                #}
            }

            #element "multi" {
            #
            #}
        }
    }
}

generates:

  System(Backend, "Backend", "Backend1", $tags="Element+Software System+multi")

I think this previous behavior was convenient because it gave the user more freedom.

@simonbrowndotje
Copy link
Contributor

Regarding the behavior, with a previous version (tag 0f71abe78aa8 built 9hs ago), there was no need for an element style to get the tag in the system:

Yes, I had to change this because there's a mismatch between how Structurizr treats tags vs how C4-PlantUML treats tags. Since this is an exporter from Structurizr, I decided to switch the semantics to better reflect how Structurizr deals with tags and styling, which provides a more consistent experience across the Structurizr renderer, the PlantUML exports, Mermaid export, etc. The old version used + to create a set of tags, whereas this new version creates a single tag based upon the tags/styles defined in the workspace. If this doesn't work for you, you may want to look at this alternative C4-PlantUML exporter instead.

@dgutson
Copy link
Author

dgutson commented Oct 24, 2022

It's fine, I have everything I need. I just thought that with the previous behavior, I was free to add as many AddElementTag as I needed in an external puml file. Now, you're right that this provides a better user experience at the cost of a little less flexibility.
My only need to add an external puml file is to provide additional includes for extra sprites (eg users from font-awesome-5) and to hide the stereotypes (which I will file a separate issue these days).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants