Skip to main content
Version: 2.5

Layout Widgets


Accordions dtl-fluent-accordion​

The accordion is a UI component used to display and organize content in a collapsible manner, allowing users to expand or collapse sections of content as needed. It consists of multiple sections or panels, with a title for each section and its associated content displayed in the body of the panel. When a user clicks on the title of a panel, the content of that panel is expanded, upon clicking again, it is collapsed.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-accordion"
},
"items": [],
"config": {
"accordions": [
{
"header": "Accordion",
"content": []
}
]
}
}

Inputs​

Key for accordions remembering cache

Key: storedAccordionsActiveIndex

Name: Key for accordions remembering cache

Description: A unique identifier that the application uses to store and retrieve the cached accordion data.

Default: ""

Disable lazy loading

Key: disableLazy

Name: Disable lazy loading

Description: Disables lazy loading of accordion content. Content is rendered immediately instead of after accordion selection.

Default: false

Accordion name

Key: header

Name: Accordion name

Description: The title which will be displayed for this component.

Default: "__expr:this.translocoService.translate( translation.fluentAccordionEditor.newTab, )"

Hidden

Key: hidden

Name: Hidden

Description: Tick the checkbox if you wish the component to be hidden. It can also be controlled with an expression using the expression editor.

Default: false

Privilege

Key: priv

Name: Privilege

Description: The privilege for displaying and editing this component.

Default: null

Icon

Key: icon

Name: Icon

Description: The icon of this component.

Default: null

iconColor

Key: iconColor

Name: iconColor

Default: null

Opened

Key: selected

Name: Opened

Description: Tick the checkbox if you wish the accordion to be expanded by default.

Default: null

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-accordion/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen disable lazy — gen-disable-lazy.json

Disable lazy loading: Disables lazy loading of accordion content. Content is rendered immediately instead of after accordion selection.

{
"type": "object",
"title": "Accordions — Disable lazy loading",
"description": "Disable lazy loading: Disables lazy loading of accordion content. Content is rendered immediately instead of after accordion selection.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-accordion"
},
"items": [],
"config": {
"accordions": [
{
"header": "Accordion",
"content": []
}
],
"disableLazy": true
}
}
]
}

Anchor dtl-fluent-anchor​

The widget inserts an HTML <div> with a specified ID into the DOM and automatically scrolls to it when the page loads. This is useful for directing users to a specific section of a webpage upon loading.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-anchor"
},
"items": [],
"config": {}
}

Inputs​

ID

Key: scrollId

Name: ID

Description: On an anchor with the selected ID, it will be automatically scrolled down in the form after it is opened, if the URL used to open the form contains this ID as a parameter.
Example: .../dashboard/9134d5eb-944c-4d09-ba62-b9be6458208e#SCROLL_TARGET_1

Default: ""


Back button tsm-button-back​

The back button element is used for returning to the previous page upon clicking.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "tsm-button-back"
}
}

Inputs​

Name

Key: label

Name: Name

Description: The title which will be displayed for this component.

Default: ""

Router link within the application

Key: routerLink

Name: Router link within the application

Description: The router link where the user will be navigated to upon clicking the button. For example "/ordering/order-type". If you wish to only redirect the user to the previous page, leave this option empty.

Default: ""

Keyboard shortcut

Key: hotkey

Name: Keyboard shortcut

Description: Global shortcut that triggers this button (e.g. Ctrl+S). Click the field and press the desired combination.

Default: null


Button bar dtl-fluent-bar​

The button bar component creates a section which you can open by clicking on it. Inside the section you can put additional content such as a Text item, Password field or a Checkbox. These items are only visible when the section is opened. You can add a custom text in the button bar label - for example "More", or "Click to view". There are other customizable options such as a tooltip or a CSS class.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-bar"
},
"items": []
}

Inputs​

Disable lazy loading

Key: disableLazy

Name: Disable lazy loading

Description: Disables lazy loading of the bar content. The inner widgets and their forms are instantiated immediately and remain alive even when the bar is closed (validation keeps running).

Default: false

Icon

Key: icon

Name: Icon

Description: The icon class for this component.

Default: "pi pi-chevron-down"

Icon position

Key: iconPos

Name: Icon position

Description: The position of the icon for this component. It can also be controlled with an expression using the expression editor.

Default: "right"

Button Appearance

Key: buttonAppearance

Name: Button Appearance

Description: Appearance defines the type of graphical design of the button.

Default: "p-button"

Button shape

Key: buttonShape

Name: Button shape

Description: Rounded shape renders a labeled button as a pill. An icon-only button becomes fully circular.

Default: "default"

Button Severity

Key: buttonSeverity

Name: Button Severity

Description: Severity defines the button's color design.

Default: "p-button-secondary"

Dismissable on outside click

Key: dismissable

Name: Dismissable on outside click

Description: When enabled, the panel closes when clicking outside of it.

Default: false

Close on content click

Key: closeOnContentClick

Name: Close on content click

Description: When enabled, the panel closes on any click inside its content, regardless of what was clicked.

Default: false

Button label

Key: label

Name: Button label

Description: The label for this component. Leave empty to render icon-only.

Default: "__expr:injectAndTranslateDefault(translationShared.shared.more)"

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-bar/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen close on content click — gen-close-on-content-click.json

Close on content click: When enabled, the panel closes on any click inside its content, regardless of what was clicked.

{
"type": "object",
"title": "Button bar — Close on content click",
"description": "Close on content click: When enabled, the panel closes on any click inside its content, regardless of what was clicked.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-bar"
},
"items": [],
"config": {
"closeOnContentClick": true
}
}
]
}

Gen disable lazy — gen-disable-lazy.json

Disable lazy loading: Disables lazy loading of the bar content. The inner widgets and their forms are instantiated immediately and remain alive even when the bar is closed (validation keeps running).

{
"type": "object",
"title": "Button bar — Disable lazy loading",
"description": "Disable lazy loading: Disables lazy loading of the bar content. The inner widgets and their forms are instantiated immediately and remain alive even when the bar is closed (validation keeps running).",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-bar"
},
"items": [],
"config": {
"disableLazy": true
}
}
]
}

Gen dismissable — gen-dismissable.json

Dismissable on outside click: When enabled, the panel closes when clicking outside of it.

{
"type": "object",
"title": "Button bar — Dismissable on outside click",
"description": "Dismissable on outside click: When enabled, the panel closes when clicking outside of it.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-bar"
},
"items": [],
"config": {
"dismissable": true
}
}
]
}

Gen icon pos — gen-icon-pos.json

Icon position: The position of the icon for this component. It can also be controlled with an expression using the expression editor.

{
"type": "object",
"title": "Button bar — Icon position",
"description": "Icon position: The position of the icon for this component. It can also be controlled with an expression using the expression editor.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-bar"
},
"items": [],
"config": {
"iconPos": "p-icon-search"
}
}
]
}

Gen icon — gen-icon.json

Icon: The icon class for this component.

{
"type": "object",
"title": "Button bar — Icon",
"description": "Icon: The icon class for this component.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-bar"
},
"items": [],
"config": {
"icon": "p-icon-search"
}
}
]
}

Card dtl-fluent-card​

The card component presents information in a compact, organized manner, and is commonly used to display information such as product detail or profiles.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": []
}

Inputs​

Card Title

Key: header

Name: Card Title

Description: The title of this card. It can also be controlled with an expression using the expression editor.

Default: null

Card title after minimize

Key: headerAfterMinimize

Name: Card title after minimize

Description: The title of this card after minimizing. It can also be controlled with an expression using the expression editor.

Default: null

Card title URL link

Key: headerLink

Name: Card title URL link

Description: Enter the URL to redirect the user when clicking on the card title. If left empty, the title will not be clickable.

Default: null

External link

Key: headerTarget

Name: External link

Description: Opens external link in a new tab

Default: false

Icon

Key: headerIconClass

Name: Icon

Description: The icon of this component. It can also be controlled with an expression using the expression editor.

Default: null

Color highlight

Key: cardType

Name: Color highlight

Description: Color highlighting of the card. It can also be controlled with an expression using the expression editor.

Default: null

Highlight side

Key: cardTypeSide

Name: Highlight side

Description: Which side of the card shows the colored highlight strip: top (default), right, bottom or left. It can also be controlled with an expression using the expression editor.

Default: "top"

Color background highlight

Key: cardColor

Name: Color background highlight

Description: Color background highlighting of the card. It can also be controlled with an expression using the expression editor.

Default: null

Remove card styling

Key: disableCard

Name: Remove card styling

Description: Removes the card's border, shadow, and background, displaying it as a plain container.

Default: false

Control buttons

Key: buttonsOnHover

Name: Control buttons

Default: false

Enable action button

Key: activeButton

Name: Enable action button

Description: Enable action button

Default: false

Disable maximize button

Key: disableMaximize

Name: Disable maximize button

Description: Tick the checkbox to disable the maximize button. The button is present only on forms of type Dashboard. It can also be controlled with an expression using the expression editor.

Default: false

Disable minimize button

Key: disableMinimize

Name: Disable minimize button

Description: Tick the checkbox to disable the minimize button. The button is present only on forms of type Dashboard. It can also be controlled with an expression using the expression editor.

Default: false

Minimized by default

Key: minimizedByDefault

Name: Minimized by default

Description: Tick the checkbox if you wish the card to be minimized by default. It can also be controlled with an expression using the expression editor.

Default: false

Fullscreen

Key: fullscreen

Name: Fullscreen

Description: Tick the checkbox if you wish the card to be in fullscreen mode.

Default: false

Disable fullscreen close

Key: disableFullscreenClose

Name: Disable fullscreen close

Description: Button close will be hidden in fullscreen mode

Default: false

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-card/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen active button — gen-active-button.json

Enable action button: Enable action button

{
"type": "object",
"title": "Card — Enable action button",
"description": "Enable action button: Enable action button",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [],
"config": {
"activeButton": true
}
}
]
}

Gen buttons on hover — gen-buttons-on-hover.json

Demonstrates config.buttonsOnHover = true on dtl-fluent-card.

{
"type": "object",
"title": "Card — Control buttons",
"description": "Demonstrates config.buttonsOnHover = true on dtl-fluent-card.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [],
"config": {
"buttonsOnHover": true
}
}
]
}

Gen disable card — gen-disable-card.json

Remove card styling: Removes the card's border, shadow, and background, displaying it as a plain container.

{
"type": "object",
"title": "Card — Remove card styling",
"description": "Remove card styling: Removes the card's border, shadow, and background, displaying it as a plain container.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [],
"config": {
"disableCard": true
}
}
]
}

Gen disable maximize — gen-disable-maximize.json

Disable maximize button: Tick the checkbox to disable the maximize button. The button is present only on forms of type Dashboard. It can also be controlled with an expression using the expression editor.

{
"type": "object",
"title": "Card — Disable maximize button",
"description": "Disable maximize button: Tick the checkbox to disable the maximize button. The button is present only on forms of type Dashboard. It can also be controlled with an expression using the expression editor.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [],
"config": {
"disableMaximize": true
}
}
]
}

Gen disable minimize — gen-disable-minimize.json

Disable minimize button: Tick the checkbox to disable the minimize button. The button is present only on forms of type Dashboard. It can also be controlled with an expression using the expression editor.

{
"type": "object",
"title": "Card — Disable minimize button",
"description": "Disable minimize button: Tick the checkbox to disable the minimize button. The button is present only on forms of type Dashboard. It can also be controlled with an expression using the expression editor.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [],
"config": {
"disableMinimize": true
}
}
]
}

Gen header target — gen-header-target.json

External link: Opens external link in a new tab

{
"type": "object",
"title": "Card — External link",
"description": "External link: Opens external link in a new tab",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"items": [],
"config": {
"headerTarget": true
}
}
]
}

Clone dtl-fluent-clone​

The special component to allow duplication of a form section to a different place. Use "Clone key" attribute of an object to mark the object with custom key (for example "productDetail") and then use the key in this component configuration. This is intended to position parts of the form in different sections based on the form usage. Typically this is the case of Detail form within listings or on a seperate page.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-clone"
},
"items": []
}

Inputs​

Clone key

Key: cloneKey

Name: Clone key

Description: The key for copying of content into the clone component

Default: ""


Content dtl-fluent-content​

The content component is used to embed text created with the Editor component(see Editor description).

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-content"
},
"config": {
"html": ""
}
}

Inputs​

Content

Key: html

Name: Content

Description: The content which will be displayed in the component. It is inputted using the editor.

Default: null


Delimited inline dtl-fluent-delimited​

The delimited inline layout renders child items next to each other and inserts a configurable separator only between adjacent non-empty values. It is useful for compact readonly combinations such as user / group pairs.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-delimited"
},
"config": {
"delimiter": "/"
},
"items": []
}

Inputs​

Delimiter

Key: delimiter

Name: Delimiter

Description: Separator rendered between inline items when both adjacent values are non-empty.

Default: "/"


External content dtl-fluent-iframe​

External content(iframe) is to embed external content into the current page. This makes it possible to view content from another source without leaving the current page. For example, an iframe can be used to display a map or a video from another website. The content can be interacted with within the iframe just as if it was being viewed on its own page.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-iframe"
},
"items": []
}

Inputs​

Title

Key: title

Name: Title

Description: The title which will be displayed for this component.

Default: ""

Source URL

Key: src

Name: Source URL

Description: The URL of the external resource to be displayed.

Default: ""

Hide title

Key: notitle

Name: Hide title

Description: Tick the checkbox if you wish to hide the title for this component. It can also be controlled with an expression using the expression editor.

Default: false

Height (px)

Key: height

Name: Height (px)

Description: The height in pixels. It can also be controlled with an expression using the expression editor.

Default: ""

Width (px)

Key: width

Name: Width (px)

Description: the width in pixels. It can also be controlled with an expression using the expression editor.

Default: ""


Fieldset dtl-fluent-fieldset​

The fieldset component is used to group related form controls or content into a single visually identifiable unit. It can be used to provide context and improve the overall organization of a form.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"items": [],
"widget": {
"type": "dtl-fluent-fieldset"
},
"config": {}
}

Inputs​

Read only

Key: readonly

Name: Read only

Default: false

Legend (title)

Key: legend

Name: Legend (title)

Description: Title displayed above the component.

Default: ""

Disable legend

Key: disableLegendForEmptyAndReadonly

Name: Disable legend

Description: Tick the checkbox if you wish to turn off the legend if readonly mode is enabled and the component does not contain any data.

Default: false

Default number of objects

Key: numberOfRows

Name: Default number of objects

Description: "value": displayed number of objects
"onlyForEmpty" = true: displayed set number of objects only if no data is stored in the array
"onlyForEmpty" = false: always displayed set number of objects (even if, for example, more are stored in the data)

Note: if the "onlyForEmpty" parameter is not set, the behavior corresponds to the "onlyForEmpty" = false setting

Default: null

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-fieldset/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen disable legend for empty and readonly — gen-disable-legend-for-empty-and-readonly.json

Disable legend: Tick the checkbox if you wish to turn off the legend if readonly mode is enabled and the component does not contain any data.

{
"type": "object",
"title": "Fieldset — Disable legend",
"description": "Disable legend: Tick the checkbox if you wish to turn off the legend if readonly mode is enabled and the component does not contain any data.",
"properties": {},
"layout": [
{
"type": "layout",
"items": [],
"widget": {
"type": "dtl-fluent-fieldset"
},
"config": {
"disableLegendForEmptyAndReadonly": true
}
}
]
}

Form section dtl-fluent-form-section​

Form section with a title, an optional description and a subtle bottom divider. Provides the unified sectioned look of form dialogs — the section title stands in for the labels of the fields inside. Turn off the bottom divider for the last section in a dialog.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-form-section"
},
"items": []
}

Inputs​

Section title

Key: label

Name: Section title

Description: Title of the form section. It stands in for the labels of the fields inside — field labels should not repeat it. Can be controlled by an expression using the expression editor.

Default: null

Section description

Key: description

Name: Section description

Description: Additional description displayed below the section title in a smaller muted font.

Default: null

Required section

Key: required

Name: Required section

Description: Shows a required asterisk after the section title (when the title stands in for a required field label).

Default: false

Top divider

Key: dividerTop

Name: Top divider

Description: Subtle divider line above the section. Turn on when the section is preceded by a block that is not a section (e.g. characteristics) and the line would be missing. Keep off between regular sections to avoid a double line.

Default: false

Bottom divider

Key: divider

Name: Bottom divider

Description: Subtle divider line below the section content. Turn off for the last section in a dialog.

Default: true

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-form-section/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen divider top — gen-divider-top.json

_Top divider: Subtle divider line above the section. Turn on when the section is preceded by a block that is not a section (e.g. characteristics) and the line would be missing. Keep off between regular sections to _

{
"type": "object",
"title": "Form section — Top divider",
"description": "Top divider: Subtle divider line above the section. Turn on when the section is preceded by a block that is not a section (e.g. characteristics) and the line would be missing. Keep off between regular sections to ",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-form-section"
},
"items": [],
"config": {
"dividerTop": true
}
}
]
}

Gen divider — gen-divider.json

Bottom divider: Subtle divider line below the section content. Turn off for the last section in a dialog.

{
"type": "object",
"title": "Form section — Bottom divider",
"description": "Bottom divider: Subtle divider line below the section content. Turn off for the last section in a dialog.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-form-section"
},
"items": [],
"config": {
"divider": false
}
}
]
}

Html dtl-fluent-html​

The Html component is used to embed plain html in a section which is then rendered.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-html"
}
}

Inputs​

HTML mapping

Key: htmlMapping

Name: HTML mapping

Description: Any string that will be replaced by a variable should be unique. For example: NAME

Default: "__expr:value?.htmlMapping ?? ''"

Variable

Key: htmlVariable

Name: Variable

Description: Variable that will replace the string defined in the mapping.

Default: "__expr:value?.htmlVariable ?? ''"

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-html/. Each is a complete validated FluentSchema — copy & adapt for your form.

Conditional warning — conditional-warning.json

Renders literal HTML from config.html and hides it when the required value is present.

{
"type": "object",
"title": "Conditional information message",
"description": "Renders literal HTML from config.html and hides it when the required value is present.",
"properties": {
"name": {
"type": "string",
"title": "Name",
"widget": {
"type": "text"
}
}
},
"layout": [
"name",
{
"type": "layout",
"config": {
"html": "Name is missing. You may save, but the record will not be sent."
},
"widget": {
"type": "html",
"hidden": "${!isNullOrEmpty($value.name)}"
}
}
]
}

Inplace dtl-fluent-inplace​

The form inplace component is a UI element that allows for in-place editing of data within a form. At first the data is in read-only mode intended for viewing, but edit mode can be entered by clicking on the edit icon. Afterwards changes can be made to the data and modifications saved or discarded by buttons.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": []
}

Inputs​

Clone key

Key: cloneKey

Name: Clone key

Description: The key for copying of content into the clone component

Default: null

Disable autofocus

Key: disableAutofocus

Name: Disable autofocus

Description: Disable autofocus on the first input in the form

Default: false

Save on click outside

Key: saveOnClickOutside

Name: Save on click outside

Description: By default the form is reset (unsaved changes are confirmed before being discarded), by enabling this the form is saved instead.

Default: false

Display field borders even in readonly mode

Key: alwaysShowBorders

Name: Display field borders even in readonly mode

Description: Displays field borders even in readonly mode. Fields will look editable but remain non-editable (readonly). This setting applies only in readonly mode; in edit mode, no changes are applied.

Default: false

Label (column) width

Key: labelWidth

Name: Label (column) width

Description: Overrides the default 40% label column width for all form-field fields inside this inplace section (left-aligned columnar layout). Enter a CSS length, e.g. "30%" or "12rem". Empty = default 40%. The 50% row width cap still applies to this override too.

Default: null

Align labels right

Key: labelAlignRight

Name: Align labels right

Description: Right-aligns the label text of form-fields inside this section (only for the "label left" layout). Does not change the layout type or arrangement — only the label text alignment. Some users find the form easier to read this way.

Default: false

Value font weight

Key: valueFontWeight

Name: Value font weight

Description: Font weight of all displayed field values (readonly text) inside this section. Affects only the displayed value — labels, edit-mode inputs and empty "none" placeholders stay unchanged.

Default: null

Disable count is single child

Key: disableCountIsSingleChild

Name: Disable count is single child

Description: If checked, editing fields in the characteristic in the fluent-inplace component will never autosave.

Default: false

saveSuccessActions

Key: saveSuccessActions

Name: saveSuccessActions

Default: []

saveErrorActions

Key: saveErrorActions

Name: saveErrorActions

Default: []

Script

Key: scriptCode

Name: Script

Default: ""

Script data

Key: scriptData

Name: Script data

Description: Additional params for script evaluation

Default: {}

Hide script errors

Key: hideScriptError

Name: Hide script errors

Description: Whether to hide script errors from the user

Default: false

successActions

Key: successActions

Name: successActions

Default: []

errorActions

Key: errorActions

Name: errorActions

Default: []

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-inplace/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen always show borders — gen-always-show-borders.json

Display field borders even in readonly mode: Displays field borders even in readonly mode. Fields will look editable but remain non-editable (readonly). This setting applies only in readonly mode; in edit mode, no changes are applied.

{
"type": "object",
"title": "Inplace — Display field borders even in readonly mode",
"description": "Display field borders even in readonly mode: Displays field borders even in readonly mode. Fields will look editable but remain non-editable (readonly). This setting applies only in readonly mode; in edit mode, no changes are applied.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": [],
"config": {
"alwaysShowBorders": true
}
}
]
}

Gen disable autofocus — gen-disable-autofocus.json

Disable autofocus: Disable autofocus on the first input in the form

{
"type": "object",
"title": "Inplace — Disable autofocus",
"description": "Disable autofocus: Disable autofocus on the first input in the form",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": [],
"config": {
"disableAutofocus": true
}
}
]
}

Gen disable count is single child — gen-disable-count-is-single-child.json

Disable count is single child: If checked, editing fields in the characteristic in the fluent-inplace component will never autosave.

{
"type": "object",
"title": "Inplace — Disable count is single child",
"description": "Disable count is single child: If checked, editing fields in the characteristic in the fluent-inplace component will never autosave.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": [],
"config": {
"disableCountIsSingleChild": true
}
}
]
}

Gen hide script error — gen-hide-script-error.json

Hide script errors: Whether to hide script errors from the user

{
"type": "object",
"title": "Inplace — Hide script errors",
"description": "Hide script errors: Whether to hide script errors from the user",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": [],
"config": {
"hideScriptError": true
}
}
]
}

Gen label align right — gen-label-align-right.json

Align labels right: Right-aligns the label text of form-fields inside this section (only for the "label left" layout). Does not change the layout type or arrangement — only the label text alignment. Some users find the f

{
"type": "object",
"title": "Inplace — Align labels right",
"description": "Align labels right: Right-aligns the label text of form-fields inside this section (only for the \"label left\" layout). Does not change the layout type or arrangement — only the label text alignment. Some users find the f",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": [],
"config": {
"labelAlignRight": true
}
}
]
}

Gen save on click outside — gen-save-on-click-outside.json

Save on click outside: By default the form is reset (unsaved changes are confirmed before being discarded), by enabling this the form is saved instead.

{
"type": "object",
"title": "Inplace — Save on click outside",
"description": "Save on click outside: By default the form is reset (unsaved changes are confirmed before being discarded), by enabling this the form is saved instead.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"items": [],
"config": {
"saveOnClickOutside": true
}
}
]
}

Labeled row dtl-fluent-labeled-row​

The labeled row layout renders a form-style row with its own label on the left and arbitrary child content on the right. It is intended for wrapping a single widget or a nested inline composition such as user / group values.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-labeled-row"
},
"items": []
}

Layout dtl-fluent-columns​

The 12-column layout is a popular layout design pattern that is used to divide a user interface into 12 equal-width columns. The 12-column layout is a flexible design pattern that can be used to create a wide range of layouts, from simple one-column designs to more complex multi-column layouts. It provides a simple and effective way to divide a user interface into manageable sections, and helps to ensure that the layout is consistent and scalable across different screen sizes and devices. The number 12 is the most easily divisible among reasonably small numbers; it's possible to have 12, 6, 4, 3, 2 or 1 evenly spaced columns. This gives designers tremendous flexibility over a layout.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"items": [],
"config": {
"columns": [
{
"width": 6
},
{
"width": 6
}
]
},
"widget": {
"type": "dtl-fluent-columns"
}
}

Inputs​

Enable sticky header

Key: enableStickyHeader

Name: Enable sticky header

Description: Used only for page forms. If enabled, the header will be sticky. It will be visible even when the user scrolls down the page.

Default: false

Border

Key: bordered

Name: Border

Description: Tick the checkbox if you wish the component wrapper to have a border.

Default: ""

Background

Key: colored

Name: Background

Description: Tick the checkbox if you wish the wrapper of the component to have a background color. Afterwards select the color

Default: ""

Background color

Key: backgroundColor

Name: Background color

Default: ""

Page layout

Key: pageLayout

Name: Page layout

Description: A special layout option. Required if you use the layout as the main layout of the page.

Default: false

Enable internal paddings

Key: innerPageLayout

Name: Enable internal paddings

Description: Enable internal paddings.

Default: true

grid CSS class

Key: gridStyle

Name: grid CSS class

Description: The CSS class used to change or modification of the grid layout.

Default: ""

Fixed column

Key: stickyColumn

Name: Fixed column

Description: When enabled, the column will be fixed – it remains visible during horizontal scrolling.
Ideal for quick access to action buttons or summaries.

Default: ""

Width

Key: width

Name: Width

Description: The column width in 12 column layout. For example 12 means 100%, 6 means 50% and 3 means 25%.

Default: "__expr:width ?? 6"

Offset

Key: offset

Name: Offset

Description: The column offset from the left side in 12 column layout. For example 12 means 100%, 6 means 50% and 3 means 25%.

Default: null

Fixed width

Key: fixed

Name: Fixed width

Description: Tick the checkbox if you wish the column width to be setup according to the content and the column will no longer be flexible.

Default: false

Flexible

Key: flexible

Name: Flexible

Description: Tick the checkbox if you wish the colmn width to be set to the maximum possible width. (according to the available space)

Default: false

Separator

Key: divider

Name: Separator

Description: Tick the checkbox if you wish the column to be used as a graphical separator(without text).

Default: false

Right align

Key: push

Name: Right align

Description: Tick the checkbox if you wish the column to be aligned right.

Default: false

Hidden

Key: hidden

Name: Hidden

Description: Tick the checkbox if you wish the component to be hidden. It can also be controlled with an expression using the expression editor.

Default: false

Optional CSS class

Key: fieldHtmlClass

Name: Optional CSS class

Description: An optional CSS class to modify the style of this component. Examples: text-2xl bg-red-500 flex w-full gap-2 flex-col p-4

Default: null

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-columns/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen enable sticky header — gen-enable-sticky-header.json

Enable sticky header: Used only for page forms. If enabled, the header will be sticky. It will be visible even when the user scrolls down the page.

{
"type": "object",
"title": "Layout — Enable sticky header",
"description": "Enable sticky header: Used only for page forms. If enabled, the header will be sticky. It will be visible even when the user scrolls down the page.",
"properties": {},
"layout": [
{
"type": "layout",
"items": [],
"config": {
"columns": [
{
"width": 6
},
{
"width": 6
}
]
},
"widget": {
"type": "dtl-fluent-columns",
"enableStickyHeader": true
}
}
]
}

Gen inner page layout — gen-inner-page-layout.json

Enable internal paddings: Enable internal paddings.

{
"type": "object",
"title": "Layout — Enable internal paddings",
"description": "Enable internal paddings: Enable internal paddings.",
"properties": {},
"layout": [
{
"type": "layout",
"items": [],
"config": {
"columns": [
{
"width": 6
},
{
"width": 6
}
],
"innerPageLayout": false
},
"widget": {
"type": "dtl-fluent-columns"
}
}
]
}

Gen page layout — gen-page-layout.json

Page layout: A special layout option. Required if you use the layout as the main layout of the page.

{
"type": "object",
"title": "Layout — Page layout",
"description": "Page layout: A special layout option. Required if you use the layout as the main layout of the page.",
"properties": {},
"layout": [
{
"type": "layout",
"items": [],
"config": {
"columns": [
{
"width": 6
},
{
"width": 6
}
],
"pageLayout": true
},
"widget": {
"type": "dtl-fluent-columns"
}
}
]
}

Panel dtl-fluent-panel​

The panel component is a container component that can be used to group and organize other components within a section that has it's own header. It can be manually or programatically collapsed and it's properties can be changed such as the header.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-panel"
},
"items": []
}

Inputs​

Panel title

Key: title

Name: Panel title

Description: The title which will be displayed for this component.

Default: ""

Panel Implicit state

Key: collapsed

Name: Panel Implicit state

Default: false

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-panel/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen collapsed — gen-collapsed.json

Demonstrates config.collapsed = true on dtl-fluent-panel.

{
"type": "object",
"title": "Panel — Panel Implicit state",
"description": "Demonstrates config.collapsed = true on dtl-fluent-panel.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-panel"
},
"items": [],
"config": {
"collapsed": true
}
}
]
}

Section dtl-fluent-section​

The section component is similiar to the panel component(see it's description) with the main difference that it does not have a header.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"items": [],
"widget": {
"type": "dtl-fluent-section"
}
}

Inputs​

Show bottom border of inputs

Key: inputBordersShowing

Name: Show bottom border of inputs

Description: Show bottom border of inputs even if form is in read-only state (only works for inputs with the title position set to "Top")

Default: false

Compact Mode

Key: compactMode

Name: Compact Mode

Description: Compact Mode

Default: false

Clone key

Key: cloneKey

Name: Clone key

Description: The key for copying of content into the clone component

Default: ""


Splitter dtl-fluent-panel-splitter​

The splitter element is used to visually separate and organize form fields into distinct sections or columns. It is represented by a horizontal or vertical line that can be resized by dragging its handle to adjust the amount of space allocated to each section. It is commonly used in forms with multiple columns or sections to provide users with a clear visual separation between different parts of the form, improving its readability and usability. It can also be customized with different styles and colors using CSS classes to match the overall design of the form.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-panel-splitter"
},
"items": [],
"config": {
"first": [],
"second": []
}
}

Inputs​

Layout

Key: layout

Name: Layout

Description: The direction of the layout. Can either be horizontal or vertical.

Default: "horizontal"

range

Key: range

Name: range

Default: 50

Height of splitter container

Key: splitterContainerHeight

Name: Height of splitter container

Description: Enter the value including units: px, em, rem, vh or %

Default: "300px"

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-panel-splitter/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen range — gen-range.json

Demonstrates config.range = 100 on dtl-fluent-panel-splitter.

{
"type": "object",
"title": "Splitter — range",
"description": "Demonstrates config.range = 100 on dtl-fluent-panel-splitter.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-panel-splitter"
},
"items": [],
"config": {
"first": [],
"second": [],
"range": 100
}
}
]
}

SVG Canvas dtl-fluent-svg​

A SVG component is used for displaying scalable vector graphics. It allows for the creation of vector-based graphics that can be scaled up or down without losing quality or clarity. The SVG component is particularly useful for creating interactive and dynamic visualizations, such as charts and graphs, which can be customized and animated based on user interaction or data changes.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-svg"
},
"items": []
}

Inputs​

Data

Key: data

Name: Data

Description: Data — the one object the drawing reads from. The label {{hostname}} shows the field hostname, {{router.name}} reaches into a nested object; Appearance and behavior switches colors and visibility by these fields. JSON object — values may be expressions, e.g. "hostname": "${$value.hostname}". The designer does not evaluate them and shows them as written; live values appear in the form preview. The panel uses the object for path suggestions in Texts, the “Displays” preview and the value type in rules. fx — the whole Data as an expression returning an object, e.g. ${$value.device}. It works only at runtime; the panel cannot reach the values: no path suggestions, no previews, paths in Texts are typed by hand and the value type in a rule is chosen manually. Texts — a label takes its value from Data by its own name. In “Where the value comes from” you point it to another path in Data, or use fx for an expression or fixed text that bypasses Data.

Default: null

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-svg/. Each is a complete validated FluentSchema — copy & adapt for your form.

Network — 01-network.json

{
"type": "object",
"title": "IP DSLAM network — live labels and in-place editing",
"properties": {
"accessHost": {
"type": "string",
"title": "accessHost",
"widget": {
"type": "text",
"hidden": true
}
},
"accessIp": {
"type": "string",
"title": "accessIp",
"widget": {
"type": "text",
"hidden": true
}
},
"dslamHost": {
"type": "string",
"title": "DSLAM hostname",
"widget": {
"type": "text"
}
},
"dslamPort": {
"type": "string",
"title": "dslamPort",
"widget": {
"type": "text",
"hidden": true
}
},
"aggregationHost": {
"type": "string",
"title": "aggregationHost",
"widget": {
"type": "text",
"hidden": true
}
},
"vlan": {
"type": "string",
"title": "VLAN",
"oneOf": [
{
"title": "1450 — Internet",
"const": "1450"
},
{
"title": "2236 — Backup",
"const": "2236"
},
{
"title": "3000 — Management",
"const": "3000"
}
],
"widget": {
"type": "select"
}
},
"regionalHost": {
"type": "string",
"title": "regionalHost",
"widget": {
"type": "text",
"hidden": true
}
},
"primaryHost": {
"type": "string",
"title": "primaryHost",
"widget": {
"type": "text",
"hidden": true
}
},
"primaryPort": {
"type": "string",
"title": "primaryPort",
"widget": {
"type": "text",
"hidden": true
}
},
"backupHost": {
"type": "string",
"title": "backupHost",
"widget": {
"type": "text",
"hidden": true
}
},
"backupPort": {
"type": "string",
"title": "backupPort",
"widget": {
"type": "text",
"hidden": true
}
},
"aggregationPort": {
"type": "string",
"title": "aggregationPort",
"widget": {
"type": "text",
"hidden": true
}
},
"serviceId": {
"type": "string",
"title": "serviceId",
"widget": {
"type": "text",
"hidden": true
}
},
"uplinkPort": {
"type": "string",
"title": "uplinkPort",
"widget": {
"type": "text",
"hidden": true
}
},
"pseudowire": {
"type": "string",
"title": "pseudowire",
"widget": {
"type": "text",
"hidden": true
}
},
"ip": {
"type": "string",
"title": "DSLAM IP",
"pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$",
"widget": {
"type": "text",
"required": true
}
}
},
"layout": [
"accessHost",
"accessIp",
"dslamPort",
"aggregationHost",
"regionalHost",
"primaryHost",
"primaryPort",
"backupHost",
"backupPort",
"aggregationPort",
"serviceId",
"uplinkPort",
"pseudowire",
{
"type": "layout",
"widget": {
"type": "dtl-fluent-svg"
},
"config": {
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" style=\"background: #FFFFFF; background-color: light-dark(#FFFFFF, #121212);\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"1702px\" height=\"713px\" viewBox=\"0 0 1702 713\" content=\"&lt;mxfile host=&quot;127.0.0.1&quot; agent=&quot;CETIN draw.io skill&quot; compressed=&quot;false&quot;&gt;&lt;diagram id=&quot;redraw-dslam-mpls&quot; name=&quot;DSLAM to MPLS&quot;&gt;7Ztbd6I6FMc/DY92cRV9VGsva+yMq86aPp4VIUVOgbAg1no+/dmBcE3o2Bad6ap9qLCzCSH/3w65oRiz8OU6QfHmjrg4UHTVfVGMS0XXNdsawg+z7HOLPeQGL/Fd7lQZVv5/mBtVbt36Lk4bjpSQgPpx0+iQKMIObdhQkpBd0+2RBM27xsjDgmHloEC0Pvgu3XDrSFWrhBvsextaPB9PWCPnyUvINuL3U3TjKvvLk0NU5MX90w1yya5mMuaKMUsIoflR+DLDAavbotry6646UgO0x8mgVghe2gRHtHHfZxRs+bNOm95dWVOfQu3ktY6pH33De3nCz32MhZR6EeSFTOm+qH2KX5irphjTDQ0DfpjShDzhGQlIApaIROA9ffSDoGXabXyKVzFyWG474JO5kYhyynSzOOc3ZHmjwPciOA7wI9x5+owT6gMNE24OfddlvlOh8m6XcH65Wkzu4FeZ68poqIyZzz32fBIhVoNzusFJhGnL4265WPH84Hb4pUYeV+AakxDTZA8umxpsxii/bFcjUyvI5NmYVn7KNdL5KeJx4ZU5V4rDARe9i62UDkJfDoEssQIBHn5HkqfBmsmN+G3fxgSUBYK/0AvCJsvbCcjW7dC8hk5Nfm0ooAQxqusTdTgtU4qY11uEsWhWIZhlCAlovEtb3VQFccugLbRVG9pCq/Rxcf144KYBCmXaStI+kbSqas2no0OknY+vrKvp0aQ1dFFa025Ka6gtbc0etE3KpkjUVpL2ibQd6sOr0fCgsDVBW/u02hpNbUf6EbQN4yCV6dqyfyJN/554lTTFptnUVBMC1uhB1FwB3reF8EwP6cbNWu5d/Tg31GTANM0VLwkOUJbpxo9zB+wKfec2PELRU7JNHH4VchycFvYaVZBtISLvyWX4YVZuFc5IQjfEY43VgpCYG//FlO45T2hLiazLWEeoGzcXpZvyXjhyJ2wYUZUFLFc+UyxLTylKaMsjs9V86qTr/Lx2Y83Wp+Yl2AO0xkHVCa83WvnIwZg62+S5LFtec3AzD/NKz97OAyQgoUGv70pl3c6ZrkxtOFhAN40NQ3hHTQyAXO7npsAfYdkNdTlu+olwa1TOmbf+eFuLzaw9zZKWUHWKfVkb75js2J4iz4MORyZw6XMiCg05hcZJKVyfKeyPwqLrOoixjMQUJ8++g29dTmLRBELSNg786OnUBJpyAs0TEShU15nCPihcR94gTvyw7ErXKIRO8tYlOz/BOXe18xNyZ8m5s87cfXbu2BhtG/+l2A3iXTMw2gDKHT7HS1hrYaiN3gzhbGzY+qwOoXYaCMsbvwVC7c2N3/KBCVQlfgC67FJ4aLSvOcTEj2hay3nJDNXQfDxqjsx11aoDLPhrutUayo/VFvF5ESr+y2d5Q0jUY1YWEUL6OSA+WUB0tMpZPFRpfzocTOON4WCaVq/hICFWnNRa0WTr0G2Cm2VtZVWfUWpPb7sJ2l1knF8IblVoOX7qkIGL2YhBLJcmBEgx6Rm+eGwB/CK7/iLd+dTZ4PSCzbAyhuJ/chNj8glnBxmQtcDIdMPJ/Bkz+XJbo1vSmvRUjeFobMvip2RUjLViPXPBAF+S1GftAaStCaUkVMQFT8qCulwVdTArIgv7LYWRE56Vq+7t6DKks68w8M+q/oak+YhrGLBV1nUCRx47Kj1uY95FefNsrSVO1tp8iqnIpDVVq497mKptzC69xt4Zuz+AXVb3ndTFbAIg6yE3Z60kdGYOx4TTsFtw9rGo23i9vwLn+gznn2gTq8nQTkQni5sBDFdVMeXXYvI9h/c5QNHxwBxaRwBTmBOQwll4XcTyXSX9AApIgpAp//3aVN6vbkTSlnPGGUgLmlfISpvJQrGS56MgOR4fAUlhKCtFErwuXpuzOCPZN5LT+8kKtJt+v65PJ0jY42mdTenyYVC98LlzbQngGB3OcgdIAareE6jdkwg1Tl+ZSThjelRMi5qXUJonHQZp7ntiRg2rl62ibOoJRRGh6OANLJOWe/ceZxB48JvdqF0u4kaozFcsX8cjnGqXsvbaLuWS1cP3KS8mq59gubtdzN9Fki7Zc1zseee5tEYw2rgXkJiQr21O7fT4qkrXd6T3I3T5VUax/7jVZGj9NBlMx9e2qnZ6fFWl7+fXtz++TxZgnf+8md9/n7MQh/8PP+6/9Sb+uCn+aHw08bv2skpTv6ro7/5q5IAWXDPbnxaYPYjrhgOoe+l7WkyqZK0U+/s01VuaqsrhnxC1Fp+s+XA2MmVKr/YR3UCdOGB2cUjYD6JI4bvqVGXCLsCuT4vrUtb3xAFbCoPsVLiaXQPjAT/ysupBe+ayjZwNijzofffEkdX+QKX58ZGt9TDsYc/JXvNpQOh7gKjWL7UOgWucEKiTx6weLx+zZcTfqZuPJVLIkFW1dFBTfoHQ/RWDgAAMAthzv3/iWbPFEYDR2sNefrvA5bJ6k4vNTH5JwX59YEr2EMlG5sclg9PqM9N8/bb6lteY/w8=&lt;/diagram&gt;&lt;/mxfile&gt;\"><defs/><rect fill=\"#FFFFFF\" width=\"100%\" height=\"100%\" x=\"0\" y=\"0\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><g><g data-cell-id=\"0\"><g data-cell-id=\"layer-background\"><g data-cell-id=\"title\"><g transform=\"translate(0.5,0.5)\"><rect x=\"6\" y=\"0\" width=\"1100\" height=\"38\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1098px; height: 1px; padding-top: 19px; margin-left: 8px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #000000; \"><div style=\"display: inline-block; font-size: 24px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">IP DSLAM → Regional Ethernet → MPLS</div></div></div></foreignObject><text x=\"8\" y=\"26\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"24px\" font-weight=\"bold\">IP DSLAM → Regional Ethernet → MPLS</text></switch></g></g></g><g data-cell-id=\"last-mile\"><g><path d=\"M 56 215 C 12 215 1 275 36.2 287 C 1 313.4 40.6 371 69.2 347 C 89 395 155 395 177 347 C 221 347 221 299 193.5 275 C 221 227 177 179 138.5 203 C 111 167 67 167 56 215 Z\" fill=\"#f0fff4\" stroke=\"#22a06b\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(240, 255, 244), rgb(12, 25, 16)); stroke: light-dark(rgb(34, 160, 107), rgb(44, 152, 107));\"/></g></g><g data-cell-id=\"ip-dslam\"><g><path d=\"M 378.5 195 C 284.5 195 261 275 336.2 291 C 261 326.2 345.6 403 406.7 371 C 449 435 590 435 637 371 C 731 371 731 307 672.25 275 C 731 211 637 147 554.75 179 C 496 131 402 131 378.5 195 Z\" fill=\"#e9f5fb\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(233, 245, 251), rgb(19, 30, 35)); stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g></g><g data-cell-id=\"regional\"><g><path d=\"M 888.5 195 C 802.5 195 781 275 849.8 291 C 781 326.2 858.4 403 914.3 371 C 953 435 1082 435 1125 371 C 1211 371 1211 307 1157.25 275 C 1211 211 1125 147 1049.75 179 C 996 131 910 131 888.5 195 Z\" fill=\"#f4f5f7\" stroke=\"#626f86\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(244, 245, 247), rgb(25, 26, 27)); stroke: light-dark(rgb(98, 111, 134), rgb(133, 144, 164));\"/></g></g><g data-cell-id=\"mpls\"><g><path d=\"M 1371 190 C 1283 190 1261 275 1331.4 292 C 1261 329.4 1340.2 411 1397.4 377 C 1437 445 1569 445 1613 377 C 1701 377 1701 309 1646 275 C 1701 207 1613 139 1536 173 C 1481 122 1393 122 1371 190 Z\" fill=\"#e9f5fb\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(233, 245, 251), rgb(19, 30, 35)); stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g></g></g><g data-cell-id=\"layer-connections\"><g data-cell-id=\"dm1\"><g><path d=\"M 133 288.67 L 331 281.33\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 285px; margin-left: 232px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">15/0 · Last mile</div></div></div></foreignObject><text x=\"232\" y=\"289\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">15/0 · Last mile</text></switch></g></g></g><g data-cell-id=\"dm2\"><g><path d=\"M 403 280 L 611 280\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 280px; margin-left: 507px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">{dslamPort} ↔ {aggregationPort}</div></div></div></foreignObject><text x=\"507\" y=\"284\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">{dslamPort} ↔ {aggregationPort}</text></switch></g></g></g><g data-cell-id=\"dm3\"><g><path d=\"M 683 280 L 951 280\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 280px; margin-left: 817px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">{serviceId} · {uplinkPort}</div></div></div></foreignObject><text x=\"817\" y=\"284\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">{serviceId} · {uplinkPort}</text></switch></g></g></g><g data-cell-id=\"dm4\"><g><path d=\"M 1023 275.09 L 1391 224.91\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 250px; margin-left: 1207px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">pseudowire {pseudowire}</div></div></div></foreignObject><text x=\"1207\" y=\"254\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">pseudowire {pseudowire}</text></switch></g></g></g><g data-cell-id=\"dm5\"><g><path d=\"M 1023 286.14 L 1391 348.86\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 318px; margin-left: 1207px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">pseudowire {pseudowire}</div></div></div></foreignObject><text x=\"1207\" y=\"321\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">pseudowire {pseudowire}</text></switch></g></g></g><g data-cell-id=\"dm-pw-primary\"><g><path d=\"M 683 267.76 Q 941 180 1076 172.5 Q 1211 165 1391 210.83\" fill=\"none\" stroke=\"#c9372c\" stroke-width=\"2\" stroke-miterlimit=\"10\" stroke-dasharray=\"6 6\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(201, 55, 44), rgb(255, 138, 129));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 175px; margin-left: 1032px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #C9372C; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#C9372C, #ff8a81); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">PW primary</div></div></div></foreignObject><text x=\"1032\" y=\"179\" fill=\"#C9372C\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">PW primary</text></switch></g></g></g><g data-cell-id=\"dm-pw-backup\"><g><path d=\"M 683 295.92 Q 941 410 1076 415 Q 1211 420 1391 365.83\" fill=\"none\" stroke=\"#c9372c\" stroke-width=\"2\" stroke-miterlimit=\"10\" stroke-dasharray=\"6 6\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(201, 55, 44), rgb(255, 138, 129));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 413px; margin-left: 1029px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #C9372C; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#C9372C, #ff8a81); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">PW backup</div></div></div></foreignObject><text x=\"1029\" y=\"417\" fill=\"#C9372C\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">PW backup</text></switch></g></g></g></g><g data-cell-id=\"1\"><g data-cell-id=\"access\"><g><rect x=\"61\" y=\"265\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 115.28 315 L 115.28 289.73 L 61 289.73 L 61 315 Z M 61 289.73 L 82.86 265 L 133 265 L 114.91 289.73 Z M 115.28 315 L 133 287.63 L 133 265 L 115.28 289.73 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><rect x=\"61\" y=\"265\" width=\"0\" height=\"0\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"2\" pointer-events=\"all\" style=\"stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 92.66 283.41 L 91.53 284.47 L 78.34 284.47 L 76.83 286.57 L 73.07 284.47 L 80.6 281.31 L 79.09 283.41 Z M 103.21 273.94 L 102.08 275.52 L 88.9 275.52 L 87.38 277.1 L 83.62 275 L 91.16 272.36 L 89.64 273.94 Z M 94.92 280.26 L 96.06 279.21 L 109.63 279.21 L 110.76 277.1 L 114.52 279.21 L 107.36 282.37 L 108.49 280.26 Z M 102.08 270.78 L 103.21 269.74 L 116.41 269.74 L 117.91 267.62 L 121.69 270.26 L 114.15 272.9 L 115.65 270.78 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 322px; margin-left: 97px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">{accessHost}<br />{accessIp}</div></div></div></foreignObject><text x=\"97\" y=\"335\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">{accessHost...</text></switch></g></g></g><g data-cell-id=\"dslam-a\"><g><rect x=\"331\" y=\"255\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 385.28 305 L 385.28 279.73 L 331 279.73 L 331 305 Z M 331 279.73 L 352.86 255 L 403 255 L 384.91 279.73 Z M 385.28 305 L 403 277.63 L 403 255 L 385.28 279.73 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><rect x=\"331\" y=\"255\" width=\"0\" height=\"0\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"2\" pointer-events=\"all\" style=\"stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 362.66 273.41 L 361.53 274.47 L 348.34 274.47 L 346.83 276.57 L 343.07 274.47 L 350.6 271.31 L 349.09 273.41 Z M 373.21 263.94 L 372.08 265.52 L 358.9 265.52 L 357.38 267.1 L 353.62 265 L 361.16 262.36 L 359.64 263.94 Z M 364.92 270.26 L 366.06 269.21 L 379.63 269.21 L 380.76 267.1 L 384.52 269.21 L 377.36 272.37 L 378.49 270.26 Z M 372.08 260.78 L 373.21 259.74 L 386.41 259.74 L 387.91 257.62 L 391.69 260.26 L 384.15 262.9 L 385.65 260.78 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 312px; margin-left: 367px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">{dslamHost}<br />port {dslamPort}<br />{dslamIp}</div></div></div></foreignObject><text x=\"367\" y=\"325\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">{dslamHost}...</text></switch></g></g></g><g data-cell-id=\"dslam-b\"><g><rect x=\"611\" y=\"255\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 665.28 305 L 665.28 279.73 L 611 279.73 L 611 305 Z M 611 279.73 L 632.86 255 L 683 255 L 664.91 279.73 Z M 665.28 305 L 683 277.63 L 683 255 L 665.28 279.73 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><rect x=\"611\" y=\"255\" width=\"0\" height=\"0\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"2\" pointer-events=\"all\" style=\"stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 642.66 273.41 L 641.53 274.47 L 628.34 274.47 L 626.83 276.57 L 623.07 274.47 L 630.6 271.31 L 629.09 273.41 Z M 653.21 263.94 L 652.08 265.52 L 638.9 265.52 L 637.38 267.1 L 633.62 265 L 641.16 262.36 L 639.64 263.94 Z M 644.92 270.26 L 646.06 269.21 L 659.63 269.21 L 660.76 267.1 L 664.52 269.21 L 657.36 272.37 L 658.49 270.26 Z M 652.08 260.78 L 653.21 259.74 L 666.41 259.74 L 667.91 257.62 L 671.69 260.26 L 664.15 262.9 L 665.65 260.78 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 312px; margin-left: 647px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">{aggregationHost}<br />ALH-3000<br />VLAN {vlan}</div></div></div></foreignObject><text x=\"647\" y=\"325\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">{aggregatio...</text></switch></g></g></g><g data-cell-id=\"regional-pe\"><g><rect x=\"951\" y=\"255\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 1023 269.51 C 1023 277.5 1006.94 284 986.99 284 C 967.06 284 951 277.5 951 269.51 C 951 290.51 951 290.51 951 290.51 C 951 298.5 967.06 305 986.99 305 C 1006.94 305 1023 298.5 1023 290.51 Z M 986.99 284 C 1006.94 284 1023 277.5 1023 269.51 C 1023 261.5 1006.94 255 986.99 255 C 967.06 255 951 261.5 951 269.51 C 951 277.5 967.06 284 986.99 284 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 978.73 264 L 981.65 268.5 L 970.46 271.01 L 972.89 269 L 955.86 266 L 960.24 262.5 L 976.78 265.5 Z M 994.79 275 L 992.35 270.5 L 1002.57 268.01 L 1001.11 270 L 1017.64 273 L 1013.76 276 L 996.73 273 Z M 988.95 261.5 L 1000.13 258.5 L 1000.62 263 L 997.71 262.5 L 992.35 267.5 L 986.99 266.51 L 992.35 262.01 Z M 984.07 279.5 L 973.38 281.51 L 972.89 276 L 976.29 277.01 L 982.13 271.5 L 987.49 272.51 L 981.15 278.51 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 312px; margin-left: 987px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">RSH<br />PE / aggregation<br />{regionalHost}</div></div></div></foreignObject><text x=\"987\" y=\"325\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">RSH...</text></switch></g></g></g><g data-cell-id=\"bng-primary\"><g><rect x=\"1391\" y=\"195\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 1463 209.51 C 1463 217.5 1446.94 224 1426.99 224 C 1407.06 224 1391 217.5 1391 209.51 C 1391 230.51 1391 230.51 1391 230.51 C 1391 238.5 1407.06 245 1426.99 245 C 1446.94 245 1463 238.5 1463 230.51 Z M 1426.99 224 C 1446.94 224 1463 217.5 1463 209.51 C 1463 201.5 1446.94 195 1426.99 195 C 1407.06 195 1391 201.5 1391 209.51 C 1391 217.5 1407.06 224 1426.99 224 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 1418.73 204 L 1421.65 208.5 L 1410.46 211.01 L 1412.89 209 L 1395.86 206 L 1400.24 202.5 L 1416.78 205.5 Z M 1434.79 215 L 1432.35 210.5 L 1442.57 208.01 L 1441.11 210 L 1457.64 213 L 1453.76 216 L 1436.73 213 Z M 1428.95 201.5 L 1440.13 198.5 L 1440.62 203 L 1437.71 202.5 L 1432.35 207.5 L 1426.99 206.51 L 1432.35 202.01 Z M 1424.07 219.5 L 1413.38 221.51 L 1412.89 216 L 1416.29 217.01 L 1422.13 211.5 L 1427.49 212.51 L 1421.15 218.51 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 252px; margin-left: 1427px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">BRAS/BNG primary<br />{primaryHost}<br />PW-port {primaryPort}</div></div></div></foreignObject><text x=\"1427\" y=\"265\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">BRAS/BNG pr...</text></switch></g></g></g><g data-cell-id=\"bng-backup\"><g><rect x=\"1391\" y=\"330\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 1463 344.51 C 1463 352.5 1446.94 359 1426.99 359 C 1407.06 359 1391 352.5 1391 344.51 C 1391 365.51 1391 365.51 1391 365.51 C 1391 373.5 1407.06 380 1426.99 380 C 1446.94 380 1463 373.5 1463 365.51 Z M 1426.99 359 C 1446.94 359 1463 352.5 1463 344.51 C 1463 336.5 1446.94 330 1426.99 330 C 1407.06 330 1391 336.5 1391 344.51 C 1391 352.5 1407.06 359 1426.99 359 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 1418.73 339 L 1421.65 343.5 L 1410.46 346.01 L 1412.89 344 L 1395.86 341 L 1400.24 337.5 L 1416.78 340.5 Z M 1434.79 350 L 1432.35 345.5 L 1442.57 343.01 L 1441.11 345 L 1457.64 348 L 1453.76 351 L 1436.73 348 Z M 1428.95 336.5 L 1440.13 333.5 L 1440.62 338 L 1437.71 337.5 L 1432.35 342.5 L 1426.99 341.51 L 1432.35 337.01 Z M 1424.07 354.5 L 1413.38 356.51 L 1412.89 351 L 1416.29 352.01 L 1422.13 346.5 L 1427.49 347.51 L 1421.15 353.51 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 387px; margin-left: 1427px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">BRAS/BNG backup<br />{backupHost}<br />PW-port {backupPort}</div></div></div></foreignObject><text x=\"1427\" y=\"400\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">BRAS/BNG ba...</text></switch></g></g></g></g><g data-cell-id=\"layer-annotations\"><g data-cell-id=\"label-last-mile\"><g transform=\"translate(0.5,0.5)\"><rect x=\"31\" y=\"170\" width=\"160\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 184px; margin-left: 32px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">LAST MILE</div></div></div></foreignObject><text x=\"111\" y=\"188\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">LAST MILE</text></switch></g></g></g><g data-cell-id=\"label-ip-dslam\"><g transform=\"translate(0.5,0.5)\"><rect x=\"391\" y=\"130\" width=\"210\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 208px; height: 1px; padding-top: 144px; margin-left: 392px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">IP DSLAM</div></div></div></foreignObject><text x=\"496\" y=\"148\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">IP DSLAM</text></switch></g></g></g><g data-cell-id=\"label-regional\"><g transform=\"translate(0.5,0.5)\"><rect x=\"851\" y=\"130\" width=\"290\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 288px; height: 1px; padding-top: 144px; margin-left: 852px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">REGIONAL ETHERNET NETWORK</div></div></div></foreignObject><text x=\"996\" y=\"148\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">REGIONAL ETHERNET NETWORK</text></switch></g></g></g><g data-cell-id=\"label-mpls\"><g transform=\"translate(0.5,0.5)\"><rect x=\"1401\" y=\"120\" width=\"160\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 134px; margin-left: 1402px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">MPLS</div></div></div></foreignObject><text x=\"1481\" y=\"138\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">MPLS</text></switch></g></g></g><g data-cell-id=\"dm-note\"><g transform=\"translate(0.5,0.5)\"><rect x=\"6\" y=\"685\" width=\"520\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 518px; height: 1px; padding-top: 699px; margin-left: 8px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #5E6C84; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#5E6C84, #8692a6); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; \">Synthetic demo data • edit values below; the drawing stays unchanged</div></div></div></foreignObject><text x=\"8\" y=\"703\" fill=\"#5E6C84\" font-family=\"Helvetica\" font-size=\"12px\">Synthetic demo data • edit values below; the drawing stays unchanged</text></switch></g></g></g><g data-cell-id=\"edit-ip-slot\"><g transform=\"translate(0.5,0.5)\"><rect x=\"281\" y=\"485\" width=\"340\" height=\"170\" rx=\"25.5\" ry=\"25.5\" fill=\"#f4f5f7\" stroke=\"#626f86\" pointer-events=\"all\" style=\"fill: light-dark(rgb(244, 245, 247), rgb(25, 26, 27)); stroke: light-dark(rgb(98, 111, 134), rgb(133, 144, 164));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 342px; height: 170px; padding-top: 485px; margin-left: 281px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; width: 340px; height: 170px; overflow: hidden; color: #000000; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; width: 100%; height: 100%; white-space: normal; word-wrap: normal; \">{editIp}</div></div></div></foreignObject><text x=\"281\" y=\"497\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"12px\">{editIp}</text></switch></g></g></g><g data-cell-id=\"edit-vlan-slot\"><g transform=\"translate(0.5,0.5)\"><rect x=\"801\" y=\"485\" width=\"340\" height=\"170\" rx=\"25.5\" ry=\"25.5\" fill=\"#f4f5f7\" stroke=\"#626f86\" pointer-events=\"all\" style=\"fill: light-dark(rgb(244, 245, 247), rgb(25, 26, 27)); stroke: light-dark(rgb(98, 111, 134), rgb(133, 144, 164));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 342px; height: 170px; padding-top: 485px; margin-left: 801px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; width: 340px; height: 170px; overflow: hidden; color: #000000; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; width: 100%; height: 100%; white-space: normal; word-wrap: normal; \">{editVlan}</div></div></div></foreignObject><text x=\"801\" y=\"497\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"12px\">{editVlan}</text></switch></g></g></g></g></g></g><switch><g requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"/><a transform=\"translate(0,-5)\" xlink:href=\"https://www.drawio.com/doc/faq/svg-export-text-problems\" target=\"_blank\"><text text-anchor=\"middle\" font-size=\"10px\" x=\"50%\" y=\"100%\">Text is not SVG - cannot display</text></a></switch></svg>",
"textBindings": [
{
"name": "accessHost",
"value": "${$value.accessHost}",
"maxLength": 22,
"fallback": "—"
},
{
"name": "accessIp",
"value": "${$value.accessIp}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "dslamHost",
"value": "${$value.dslamHost}",
"maxLength": 22,
"fallback": "—"
},
{
"name": "dslamPort",
"value": "${$value.dslamPort}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "aggregationHost",
"value": "${$value.aggregationHost}",
"maxLength": 22,
"fallback": "—"
},
{
"name": "vlan",
"value": "${$value.vlan}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "regionalHost",
"value": "${$value.regionalHost}",
"maxLength": 22,
"fallback": "—"
},
{
"name": "primaryHost",
"value": "${$value.primaryHost}",
"maxLength": 22,
"fallback": "—"
},
{
"name": "primaryPort",
"value": "${$value.primaryPort}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "backupHost",
"value": "${$value.backupHost}",
"maxLength": 22,
"fallback": "—"
},
{
"name": "backupPort",
"value": "${$value.backupPort}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "aggregationPort",
"value": "${$value.aggregationPort}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "serviceId",
"value": "${$value.serviceId}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "uplinkPort",
"value": "${$value.uplinkPort}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "pseudowire",
"value": "${$value.pseudowire}",
"maxLength": 26,
"fallback": "—"
},
{
"name": "dslamIp",
"value": "${$value.ip}",
"maxLength": 39,
"fallback": "—"
}
],
"placeholders": [
{
"name": "{editIp}",
"content": [
0
]
},
{
"name": "{editVlan}",
"content": [
1
]
}
]
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"dslamHost",
"ip"
]
},
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"vlan"
]
}
]
}
]
}

Equipment — 02-equipment.json

{
"type": "object",
"title": "Equipment overview — generic SVG dashboard",
"properties": {
"temperature": {
"type": "number",
"widget": {
"type": "number",
"hidden": true
}
},
"status": {
"type": "string",
"widget": {
"type": "text",
"hidden": true
}
},
"deviceName": {
"type": "string",
"title": "Device name / Název zařízení",
"widget": {
"type": "text",
"required": true
}
}
},
"layout": [
"temperature",
"status",
{
"type": "layout",
"widget": {
"type": "dtl-fluent-svg"
},
"config": {
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" width=\"760\" height=\"400\" viewBox=\"0 0 760 400\"><rect x=\"1\" y=\"1\" width=\"758\" height=\"398\" rx=\"16\" fill=\"#f8fafc\" stroke=\"#64748b\"/><text x=\"32\" y=\"42\" font-family=\"sans-serif\" font-size=\"22\" fill=\"#0f172a\">Equipment overview / Přehled zařízení</text><rect x=\"32\" y=\"70\" width=\"336\" height=\"120\" rx=\"8\" fill=\"#ffffff\" stroke=\"#cbd5e1\"/><rect x=\"392\" y=\"70\" width=\"336\" height=\"120\" rx=\"8\" fill=\"#ffffff\" stroke=\"#cbd5e1\"/><g font-family=\"sans-serif\" fill=\"#334155\"><text x=\"52\" y=\"98\" font-size=\"14\">Temperature / Teplota</text><text x=\"52\" y=\"153\" font-size=\"36\">{temperature} °C</text><text x=\"412\" y=\"98\" font-size=\"14\">Status / Stav</text><text x=\"412\" y=\"148\" font-size=\"24\">{status}</text><text x=\"32\" y=\"222\" font-size=\"17\">{deviceName}</text></g><rect x=\"32\" y=\"244\" width=\"696\" height=\"130\" rx=\"8\" fill=\"#ffffff\" stroke=\"#cbd5e1\"/><foreignObject x=\"44\" y=\"252\" width=\"672\" height=\"114\"><xhtml:div style=\"width:100%;height:100%;font-family:sans-serif;text-align:left;\">{editDevice}</xhtml:div></foreignObject></svg>",
"textBindings": [
{
"name": "temperature",
"value": "${$value.temperature}",
"maxLength": 6,
"fallback": "—"
},
{
"name": "status",
"value": "${$value.status}",
"maxLength": 24,
"fallback": "—"
},
{
"name": "deviceName",
"value": "${$value.deviceName}",
"maxLength": 64,
"fallback": "—"
}
],
"placeholders": [
{
"name": "{editDevice}",
"content": [
0
]
}
]
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"deviceName"
]
}
]
}
]
}

Canvas network — 03-canvas-network.json

Synthetic documentation-range addresses. Demo-only defaults; never bound to real ticket values.

{
"type": "object",
"title": "SVG Canvas — síť / network",
"description": "Synthetic documentation-range addresses. Demo-only defaults; never bound to real ticket values.",
"properties": {
"canvasDemoHostname": {
"type": "string",
"title": "Hostname — ukázka",
"localizationData": {
"cs": {
"title": "Hostname — ukázka"
},
"en": {
"title": "Hostname — demo"
}
},
"default": "PH32-DSLAM-51",
"widget": {
"type": "text",
"required": true
}
},
"canvasDemoIp": {
"type": "string",
"title": "IP adresa — ukázka",
"pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$",
"widget": {
"type": "text",
"required": true
},
"localizationData": {
"cs": {
"title": "IP adresa — ukázka"
},
"en": {
"title": "IP address — demo"
}
},
"default": "192.0.2.51"
},
"canvasDemoVlan": {
"type": "string",
"title": "VLAN",
"oneOf": [
{
"title": "1450 — Internet",
"const": "1450"
},
{
"title": "2236 — Backup",
"const": "2236"
},
{
"title": "3000 — Management",
"const": "3000"
}
],
"widget": {
"type": "select"
},
"default": "1450"
},
"canvasDemoStatus": {
"type": "string",
"title": "Stav DSLAM a uplinku",
"localizationData": {
"cs": {
"title": "Stav DSLAM a uplinku"
},
"en": {
"title": "DSLAM and uplink status"
}
},
"default": "up",
"oneOf": [
{
"const": "up",
"title": "V provozu / Online"
},
{
"const": "warning",
"title": "Varování / Warning"
},
{
"const": "down",
"title": "Výpadek / Offline"
},
{
"const": "unknown",
"title": "Neznámý / Unknown"
}
],
"widget": {
"type": "select"
}
},
"canvasDemoBackup": {
"type": "boolean",
"title": "Zobrazit záložní větev",
"localizationData": {
"cs": {
"title": "Zobrazit záložní větev"
},
"en": {
"title": "Show backup branch"
}
},
"default": true,
"widget": {
"type": "checkbox"
}
}
},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"config": {
"header": "SVG Canvas · IP DSLAM → MPLS"
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-columns"
},
"config": {
"columns": [
{
"width": 6,
"content": [
0
]
},
{
"width": 6,
"content": [
1
]
}
]
},
"items": [
"canvasDemoStatus",
"canvasDemoBackup"
]
},
{
"type": "layout",
"widget": {
"type": "dtl-fluent-svg"
},
"config": {
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" style=\"background: #FFFFFF; background-color: light-dark(#FFFFFF, #121212);\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"1702px\" height=\"713px\" viewBox=\"0 0 1702 713\" content=\"&lt;mxfile host=&quot;127.0.0.1&quot; agent=&quot;CETIN draw.io skill&quot; compressed=&quot;false&quot;&gt;&lt;diagram id=&quot;redraw-dslam-mpls&quot; name=&quot;DSLAM to MPLS&quot;&gt;7Ztbd6I6FMc/DY92cRV9VGsva+yMq86aPp4VIUVOgbAg1no+/dmBcE3o2Bad6ap9qLCzCSH/3w65oRiz8OU6QfHmjrg4UHTVfVGMS0XXNdsawg+z7HOLPeQGL/Fd7lQZVv5/mBtVbt36Lk4bjpSQgPpx0+iQKMIObdhQkpBd0+2RBM27xsjDgmHloEC0Pvgu3XDrSFWrhBvsextaPB9PWCPnyUvINuL3U3TjKvvLk0NU5MX90w1yya5mMuaKMUsIoflR+DLDAavbotry6646UgO0x8mgVghe2gRHtHHfZxRs+bNOm95dWVOfQu3ktY6pH33De3nCz32MhZR6EeSFTOm+qH2KX5irphjTDQ0DfpjShDzhGQlIApaIROA9ffSDoGXabXyKVzFyWG474JO5kYhyynSzOOc3ZHmjwPciOA7wI9x5+owT6gMNE24OfddlvlOh8m6XcH65Wkzu4FeZ68poqIyZzz32fBIhVoNzusFJhGnL4265WPH84Hb4pUYeV+AakxDTZA8umxpsxii/bFcjUyvI5NmYVn7KNdL5KeJx4ZU5V4rDARe9i62UDkJfDoEssQIBHn5HkqfBmsmN+G3fxgSUBYK/0AvCJsvbCcjW7dC8hk5Nfm0ooAQxqusTdTgtU4qY11uEsWhWIZhlCAlovEtb3VQFccugLbRVG9pCq/Rxcf144KYBCmXaStI+kbSqas2no0OknY+vrKvp0aQ1dFFa025Ka6gtbc0etE3KpkjUVpL2ibQd6sOr0fCgsDVBW/u02hpNbUf6EbQN4yCV6dqyfyJN/554lTTFptnUVBMC1uhB1FwB3reF8EwP6cbNWu5d/Tg31GTANM0VLwkOUJbpxo9zB+wKfec2PELRU7JNHH4VchycFvYaVZBtISLvyWX4YVZuFc5IQjfEY43VgpCYG//FlO45T2hLiazLWEeoGzcXpZvyXjhyJ2wYUZUFLFc+UyxLTylKaMsjs9V86qTr/Lx2Y83Wp+Yl2AO0xkHVCa83WvnIwZg62+S5LFtec3AzD/NKz97OAyQgoUGv70pl3c6ZrkxtOFhAN40NQ3hHTQyAXO7npsAfYdkNdTlu+olwa1TOmbf+eFuLzaw9zZKWUHWKfVkb75js2J4iz4MORyZw6XMiCg05hcZJKVyfKeyPwqLrOoixjMQUJ8++g29dTmLRBELSNg786OnUBJpyAs0TEShU15nCPihcR94gTvyw7ErXKIRO8tYlOz/BOXe18xNyZ8m5s87cfXbu2BhtG/+l2A3iXTMw2gDKHT7HS1hrYaiN3gzhbGzY+qwOoXYaCMsbvwVC7c2N3/KBCVQlfgC67FJ4aLSvOcTEj2hay3nJDNXQfDxqjsx11aoDLPhrutUayo/VFvF5ESr+y2d5Q0jUY1YWEUL6OSA+WUB0tMpZPFRpfzocTOON4WCaVq/hICFWnNRa0WTr0G2Cm2VtZVWfUWpPb7sJ2l1knF8IblVoOX7qkIGL2YhBLJcmBEgx6Rm+eGwB/CK7/iLd+dTZ4PSCzbAyhuJ/chNj8glnBxmQtcDIdMPJ/Bkz+XJbo1vSmvRUjeFobMvip2RUjLViPXPBAF+S1GftAaStCaUkVMQFT8qCulwVdTArIgv7LYWRE56Vq+7t6DKks68w8M+q/oak+YhrGLBV1nUCRx47Kj1uY95FefNsrSVO1tp8iqnIpDVVq497mKptzC69xt4Zuz+AXVb3ndTFbAIg6yE3Z60kdGYOx4TTsFtw9rGo23i9vwLn+gznn2gTq8nQTkQni5sBDFdVMeXXYvI9h/c5QNHxwBxaRwBTmBOQwll4XcTyXSX9AApIgpAp//3aVN6vbkTSlnPGGUgLmlfISpvJQrGS56MgOR4fAUlhKCtFErwuXpuzOCPZN5LT+8kKtJt+v65PJ0jY42mdTenyYVC98LlzbQngGB3OcgdIAareE6jdkwg1Tl+ZSThjelRMi5qXUJonHQZp7ntiRg2rl62ibOoJRRGh6OANLJOWe/ceZxB48JvdqF0u4kaozFcsX8cjnGqXsvbaLuWS1cP3KS8mq59gubtdzN9Fki7Zc1zseee5tEYw2rgXkJiQr21O7fT4qkrXd6T3I3T5VUax/7jVZGj9NBlMx9e2qnZ6fFWl7+fXtz++TxZgnf+8md9/n7MQh/8PP+6/9Sb+uCn+aHw08bv2skpTv6ro7/5q5IAWXDPbnxaYPYjrhgOoe+l7WkyqZK0U+/s01VuaqsrhnxC1Fp+s+XA2MmVKr/YR3UCdOGB2cUjYD6JI4bvqVGXCLsCuT4vrUtb3xAFbCoPsVLiaXQPjAT/ysupBe+ayjZwNijzofffEkdX+QKX58ZGt9TDsYc/JXvNpQOh7gKjWL7UOgWucEKiTx6weLx+zZcTfqZuPJVLIkFW1dFBTfoHQ/RWDgAAMAthzv3/iWbPFEYDR2sNefrvA5bJ6k4vNTH5JwX59YEr2EMlG5sclg9PqM9N8/bb6lteY/w8=&lt;/diagram&gt;&lt;/mxfile&gt;\"><defs/><rect fill=\"#FFFFFF\" width=\"100%\" height=\"100%\" x=\"0\" y=\"0\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><g><g data-cell-id=\"0\"><g data-cell-id=\"layer-background\"><g data-cell-id=\"title\"><g transform=\"translate(0.5,0.5)\"><rect x=\"6\" y=\"0\" width=\"1100\" height=\"38\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1098px; height: 1px; padding-top: 19px; margin-left: 8px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #000000; \"><div style=\"display: inline-block; font-size: 24px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">IP DSLAM → Regional Ethernet → MPLS</div></div></div></foreignObject><text x=\"8\" y=\"26\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"24px\" font-weight=\"bold\">IP DSLAM → Regional Ethernet → MPLS</text></switch></g></g></g><g data-cell-id=\"last-mile\"><g><path d=\"M 56 215 C 12 215 1 275 36.2 287 C 1 313.4 40.6 371 69.2 347 C 89 395 155 395 177 347 C 221 347 221 299 193.5 275 C 221 227 177 179 138.5 203 C 111 167 67 167 56 215 Z\" fill=\"#f0fff4\" stroke=\"#22a06b\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(240, 255, 244), rgb(12, 25, 16)); stroke: light-dark(rgb(34, 160, 107), rgb(44, 152, 107));\"/></g></g><g data-cell-id=\"ip-dslam\"><g><path d=\"M 378.5 195 C 284.5 195 261 275 336.2 291 C 261 326.2 345.6 403 406.7 371 C 449 435 590 435 637 371 C 731 371 731 307 672.25 275 C 731 211 637 147 554.75 179 C 496 131 402 131 378.5 195 Z\" fill=\"#e9f5fb\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(233, 245, 251), rgb(19, 30, 35)); stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g></g><g data-cell-id=\"regional\"><g><path d=\"M 888.5 195 C 802.5 195 781 275 849.8 291 C 781 326.2 858.4 403 914.3 371 C 953 435 1082 435 1125 371 C 1211 371 1211 307 1157.25 275 C 1211 211 1125 147 1049.75 179 C 996 131 910 131 888.5 195 Z\" fill=\"#f4f5f7\" stroke=\"#626f86\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(244, 245, 247), rgb(25, 26, 27)); stroke: light-dark(rgb(98, 111, 134), rgb(133, 144, 164));\"/></g></g><g data-cell-id=\"mpls\"><g><path d=\"M 1371 190 C 1283 190 1261 275 1331.4 292 C 1261 329.4 1340.2 411 1397.4 377 C 1437 445 1569 445 1613 377 C 1701 377 1701 309 1646 275 C 1701 207 1613 139 1536 173 C 1481 122 1393 122 1371 190 Z\" fill=\"#e9f5fb\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(233, 245, 251), rgb(19, 30, 35)); stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g></g></g><g data-cell-id=\"layer-connections\"><g data-cell-id=\"dm1\"><g><path d=\"M 133 288.67 L 331 281.33\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 285px; margin-left: 232px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">15/0 · Last mile</div></div></div></foreignObject><text x=\"232\" y=\"289\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">15/0 · Last mile</text></switch></g></g></g><g data-cell-id=\"dm2\"><g><path d=\"M 403 280 L 611 280\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 280px; margin-left: 507px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">{{dslamPort}} ↔ {{aggregationPort}}</div></div></div></foreignObject><text x=\"507\" y=\"284\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">{{dslamPort}} ↔ {{aggregationPort}}</text></switch></g></g></g><g data-cell-id=\"dm3\"><g><path d=\"M 683 280 L 951 280\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 280px; margin-left: 817px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">{{serviceId}} · {{uplink.port}}</div></div></div></foreignObject><text x=\"817\" y=\"284\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">{{serviceId}} · {{uplink.port}}</text></switch></g></g></g><g data-cell-id=\"dm4\"><g><path d=\"M 1023 275.09 L 1391 224.91\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 250px; margin-left: 1207px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">pseudowire {{pseudowire}}</div></div></div></foreignObject><text x=\"1207\" y=\"254\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">pseudowire {{pseudowire}}</text></switch></g></g></g><g data-cell-id=\"dm5\"><g><path d=\"M 1023 286.14 L 1391 348.86\" fill=\"none\" stroke=\"#005eb8\" stroke-width=\"2\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(0, 94, 184), rgb(98, 179, 255));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 318px; margin-left: 1207px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #172B4D; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#172B4D, #bacbe8); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">pseudowire {{pseudowire}}</div></div></div></foreignObject><text x=\"1207\" y=\"321\" fill=\"#172B4D\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">pseudowire {{pseudowire}}</text></switch></g></g></g><g data-cell-id=\"dm-pw-primary\"><g><path d=\"M 683 267.76 Q 941 180 1076 172.5 Q 1211 165 1391 210.83\" fill=\"none\" stroke=\"#c9372c\" stroke-width=\"2\" stroke-miterlimit=\"10\" stroke-dasharray=\"6 6\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(201, 55, 44), rgb(255, 138, 129));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 175px; margin-left: 1032px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #C9372C; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#C9372C, #ff8a81); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">PW primary</div></div></div></foreignObject><text x=\"1032\" y=\"179\" fill=\"#C9372C\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">PW primary</text></switch></g></g></g><g data-cell-id=\"dm-pw-backup\"><g><path d=\"M 683 295.92 Q 941 410 1076 415 Q 1211 420 1391 365.83\" fill=\"none\" stroke=\"#c9372c\" stroke-width=\"2\" stroke-miterlimit=\"10\" stroke-dasharray=\"6 6\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(201, 55, 44), rgb(255, 138, 129));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 413px; margin-left: 1029px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #C9372C; background-color: #FFFFFF; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#C9372C, #ff8a81); line-height: 1.2; pointer-events: all; background-color: light-dark(#FFFFFF, #121212); white-space: nowrap; \">PW backup</div></div></div></foreignObject><text x=\"1029\" y=\"417\" fill=\"#C9372C\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\">PW backup</text></switch></g></g></g></g><g data-cell-id=\"1\"><g data-cell-id=\"access\"><g><rect x=\"61\" y=\"265\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 115.28 315 L 115.28 289.73 L 61 289.73 L 61 315 Z M 61 289.73 L 82.86 265 L 133 265 L 114.91 289.73 Z M 115.28 315 L 133 287.63 L 133 265 L 115.28 289.73 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><rect x=\"61\" y=\"265\" width=\"0\" height=\"0\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"2\" pointer-events=\"all\" style=\"stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 92.66 283.41 L 91.53 284.47 L 78.34 284.47 L 76.83 286.57 L 73.07 284.47 L 80.6 281.31 L 79.09 283.41 Z M 103.21 273.94 L 102.08 275.52 L 88.9 275.52 L 87.38 277.1 L 83.62 275 L 91.16 272.36 L 89.64 273.94 Z M 94.92 280.26 L 96.06 279.21 L 109.63 279.21 L 110.76 277.1 L 114.52 279.21 L 107.36 282.37 L 108.49 280.26 Z M 102.08 270.78 L 103.21 269.74 L 116.41 269.74 L 117.91 267.62 L 121.69 270.26 L 114.15 272.9 L 115.65 270.78 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 322px; margin-left: 97px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">{{accessHost}}<br />{{accessIp}}</div></div></div></foreignObject><text x=\"97\" y=\"335\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">{accessHost...</text></switch></g></g></g><g data-cell-id=\"dslam-a\"><g><rect x=\"331\" y=\"255\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 385.28 305 L 385.28 279.73 L 331 279.73 L 331 305 Z M 331 279.73 L 352.86 255 L 403 255 L 384.91 279.73 Z M 385.28 305 L 403 277.63 L 403 255 L 385.28 279.73 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><rect x=\"331\" y=\"255\" width=\"0\" height=\"0\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"2\" pointer-events=\"all\" style=\"stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 362.66 273.41 L 361.53 274.47 L 348.34 274.47 L 346.83 276.57 L 343.07 274.47 L 350.6 271.31 L 349.09 273.41 Z M 373.21 263.94 L 372.08 265.52 L 358.9 265.52 L 357.38 267.1 L 353.62 265 L 361.16 262.36 L 359.64 263.94 Z M 364.92 270.26 L 366.06 269.21 L 379.63 269.21 L 380.76 267.1 L 384.52 269.21 L 377.36 272.37 L 378.49 270.26 Z M 372.08 260.78 L 373.21 259.74 L 386.41 259.74 L 387.91 257.62 L 391.69 260.26 L 384.15 262.9 L 385.65 260.78 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 312px; margin-left: 367px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">{{hostname}}<br />port {{dslamPort}}<br />{{ipAddress}}</div></div></div></foreignObject><text x=\"367\" y=\"325\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">{{hostname}}...</text></switch></g></g></g><g data-cell-id=\"dslam-b\"><g><rect x=\"611\" y=\"255\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 665.28 305 L 665.28 279.73 L 611 279.73 L 611 305 Z M 611 279.73 L 632.86 255 L 683 255 L 664.91 279.73 Z M 665.28 305 L 683 277.63 L 683 255 L 665.28 279.73 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><rect x=\"611\" y=\"255\" width=\"0\" height=\"0\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"2\" pointer-events=\"all\" style=\"stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 642.66 273.41 L 641.53 274.47 L 628.34 274.47 L 626.83 276.57 L 623.07 274.47 L 630.6 271.31 L 629.09 273.41 Z M 653.21 263.94 L 652.08 265.52 L 638.9 265.52 L 637.38 267.1 L 633.62 265 L 641.16 262.36 L 639.64 263.94 Z M 644.92 270.26 L 646.06 269.21 L 659.63 269.21 L 660.76 267.1 L 664.52 269.21 L 657.36 272.37 L 658.49 270.26 Z M 652.08 260.78 L 653.21 259.74 L 666.41 259.74 L 667.91 257.62 L 671.69 260.26 L 664.15 262.9 L 665.65 260.78 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 312px; margin-left: 647px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">{{aggregationHost}}<br />ALH-3000<br />VLAN {{vlan}}</div></div></div></foreignObject><text x=\"647\" y=\"325\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">{aggregatio...</text></switch></g></g></g><g data-cell-id=\"regional-pe\"><g><rect x=\"951\" y=\"255\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 1023 269.51 C 1023 277.5 1006.94 284 986.99 284 C 967.06 284 951 277.5 951 269.51 C 951 290.51 951 290.51 951 290.51 C 951 298.5 967.06 305 986.99 305 C 1006.94 305 1023 298.5 1023 290.51 Z M 986.99 284 C 1006.94 284 1023 277.5 1023 269.51 C 1023 261.5 1006.94 255 986.99 255 C 967.06 255 951 261.5 951 269.51 C 951 277.5 967.06 284 986.99 284 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 978.73 264 L 981.65 268.5 L 970.46 271.01 L 972.89 269 L 955.86 266 L 960.24 262.5 L 976.78 265.5 Z M 994.79 275 L 992.35 270.5 L 1002.57 268.01 L 1001.11 270 L 1017.64 273 L 1013.76 276 L 996.73 273 Z M 988.95 261.5 L 1000.13 258.5 L 1000.62 263 L 997.71 262.5 L 992.35 267.5 L 986.99 266.51 L 992.35 262.01 Z M 984.07 279.5 L 973.38 281.51 L 972.89 276 L 976.29 277.01 L 982.13 271.5 L 987.49 272.51 L 981.15 278.51 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 312px; margin-left: 987px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">RSH<br />PE / aggregation<br />{{regionalHost}}</div></div></div></foreignObject><text x=\"987\" y=\"325\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">RSH...</text></switch></g></g></g><g data-cell-id=\"bng-primary\"><g><rect x=\"1391\" y=\"195\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 1463 209.51 C 1463 217.5 1446.94 224 1426.99 224 C 1407.06 224 1391 217.5 1391 209.51 C 1391 230.51 1391 230.51 1391 230.51 C 1391 238.5 1407.06 245 1426.99 245 C 1446.94 245 1463 238.5 1463 230.51 Z M 1426.99 224 C 1446.94 224 1463 217.5 1463 209.51 C 1463 201.5 1446.94 195 1426.99 195 C 1407.06 195 1391 201.5 1391 209.51 C 1391 217.5 1407.06 224 1426.99 224 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 1418.73 204 L 1421.65 208.5 L 1410.46 211.01 L 1412.89 209 L 1395.86 206 L 1400.24 202.5 L 1416.78 205.5 Z M 1434.79 215 L 1432.35 210.5 L 1442.57 208.01 L 1441.11 210 L 1457.64 213 L 1453.76 216 L 1436.73 213 Z M 1428.95 201.5 L 1440.13 198.5 L 1440.62 203 L 1437.71 202.5 L 1432.35 207.5 L 1426.99 206.51 L 1432.35 202.01 Z M 1424.07 219.5 L 1413.38 221.51 L 1412.89 216 L 1416.29 217.01 L 1422.13 211.5 L 1427.49 212.51 L 1421.15 218.51 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 252px; margin-left: 1427px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">BRAS/BNG primary<br />{{primaryHost}}<br />PW-port {{primaryPort}}</div></div></div></foreignObject><text x=\"1427\" y=\"265\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">BRAS/BNG pr...</text></switch></g></g></g><g data-cell-id=\"bng-backup\"><g><rect x=\"1391\" y=\"330\" width=\"72\" height=\"50\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/><path d=\"M 1463 344.51 C 1463 352.5 1446.94 359 1426.99 359 C 1407.06 359 1391 352.5 1391 344.51 C 1391 365.51 1391 365.51 1391 365.51 C 1391 373.5 1407.06 380 1426.99 380 C 1446.94 380 1463 373.5 1463 365.51 Z M 1426.99 359 C 1446.94 359 1463 352.5 1463 344.51 C 1463 336.5 1446.94 330 1426.99 330 C 1407.06 330 1391 336.5 1391 344.51 C 1391 352.5 1407.06 359 1426.99 359 Z\" fill=\"#036897\" stroke=\"#ffffff\" stroke-width=\"2\" stroke-linejoin=\"round\" stroke-miterlimit=\"10\" pointer-events=\"all\" style=\"fill: light-dark(rgb(3, 104, 151), rgb(92, 179, 220)); stroke: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/><path d=\"M 1418.73 339 L 1421.65 343.5 L 1410.46 346.01 L 1412.89 344 L 1395.86 341 L 1400.24 337.5 L 1416.78 340.5 Z M 1434.79 350 L 1432.35 345.5 L 1442.57 343.01 L 1441.11 345 L 1457.64 348 L 1453.76 351 L 1436.73 348 Z M 1428.95 336.5 L 1440.13 333.5 L 1440.62 338 L 1437.71 337.5 L 1432.35 342.5 L 1426.99 341.51 L 1432.35 337.01 Z M 1424.07 354.5 L 1413.38 356.51 L 1412.89 351 L 1416.29 352.01 L 1422.13 346.5 L 1427.49 347.51 L 1421.15 353.51 Z\" fill=\"#ffffff\" stroke=\"none\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 387px; margin-left: 1427px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: nowrap; \">BRAS/BNG backup<br />{{backupHost}}<br />PW-port {{backupPort}}</div></div></div></foreignObject><text x=\"1427\" y=\"400\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\">BRAS/BNG ba...</text></switch></g></g></g></g><g data-cell-id=\"layer-annotations\"><g data-cell-id=\"label-last-mile\"><g transform=\"translate(0.5,0.5)\"><rect x=\"31\" y=\"170\" width=\"160\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 184px; margin-left: 32px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">LAST MILE</div></div></div></foreignObject><text x=\"111\" y=\"188\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">LAST MILE</text></switch></g></g></g><g data-cell-id=\"label-ip-dslam\"><g transform=\"translate(0.5,0.5)\"><rect x=\"391\" y=\"130\" width=\"210\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 208px; height: 1px; padding-top: 144px; margin-left: 392px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">IP DSLAM</div></div></div></foreignObject><text x=\"496\" y=\"148\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">IP DSLAM</text></switch></g></g></g><g data-cell-id=\"label-regional\"><g transform=\"translate(0.5,0.5)\"><rect x=\"851\" y=\"130\" width=\"290\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 288px; height: 1px; padding-top: 144px; margin-left: 852px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">REGIONAL ETHERNET NETWORK</div></div></div></foreignObject><text x=\"996\" y=\"148\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">REGIONAL ETHERNET NETWORK</text></switch></g></g></g><g data-cell-id=\"label-mpls\"><g transform=\"translate(0.5,0.5)\"><rect x=\"1401\" y=\"120\" width=\"160\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 134px; margin-left: 1402px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #000000; \"><div style=\"display: inline-block; font-size: 14px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; \">MPLS</div></div></div></foreignObject><text x=\"1481\" y=\"138\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"14px\" text-anchor=\"middle\" font-weight=\"bold\">MPLS</text></switch></g></g></g><g data-cell-id=\"dm-note\"><g transform=\"translate(0.5,0.5)\"><rect x=\"6\" y=\"685\" width=\"520\" height=\"28\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 518px; height: 1px; padding-top: 699px; margin-left: 8px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #5E6C84; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#5E6C84, #8692a6); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; \">Synthetic demo data • edit values below; the drawing stays unchanged</div></div></div></foreignObject><text x=\"8\" y=\"703\" fill=\"#5E6C84\" font-family=\"Helvetica\" font-size=\"12px\">Synthetic demo data • edit values below; the drawing stays unchanged</text></switch></g></g></g><g data-cell-id=\"edit-ip-slot\"><g transform=\"translate(0.5,0.5)\"><rect x=\"281\" y=\"485\" width=\"340\" height=\"170\" rx=\"25.5\" ry=\"25.5\" fill=\"#f4f5f7\" stroke=\"#626f86\" pointer-events=\"all\" style=\"fill: light-dark(rgb(244, 245, 247), rgb(25, 26, 27)); stroke: light-dark(rgb(98, 111, 134), rgb(133, 144, 164));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 342px; height: 170px; padding-top: 485px; margin-left: 281px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; width: 340px; height: 170px; overflow: hidden; color: #000000; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; width: 100%; height: 100%; white-space: normal; word-wrap: normal; \">{editIp}</div></div></div></foreignObject><text x=\"281\" y=\"497\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"12px\">{editIp}</text></switch></g></g></g><g data-cell-id=\"edit-vlan-slot\"><g transform=\"translate(0.5,0.5)\"><rect x=\"801\" y=\"485\" width=\"340\" height=\"170\" rx=\"25.5\" ry=\"25.5\" fill=\"#f4f5f7\" stroke=\"#626f86\" pointer-events=\"all\" style=\"fill: light-dark(rgb(244, 245, 247), rgb(25, 26, 27)); stroke: light-dark(rgb(98, 111, 134), rgb(133, 144, 164));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 342px; height: 170px; padding-top: 485px; margin-left: 801px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; width: 340px; height: 170px; overflow: hidden; color: #000000; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; width: 100%; height: 100%; white-space: normal; word-wrap: normal; \">{editVlan}</div></div></div></foreignObject><text x=\"801\" y=\"497\" fill=\"light-dark(#000000, #ffffff)\" font-family=\"Helvetica\" font-size=\"12px\">{editVlan}</text></switch></g></g></g></g></g></g><switch><g requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"/><a transform=\"translate(0,-5)\" xlink:href=\"https://www.drawio.com/doc/faq/svg-export-text-problems\" target=\"_blank\"><text text-anchor=\"middle\" font-size=\"10px\" x=\"50%\" y=\"100%\">Text is not SVG - cannot display</text></a></switch></svg>",
"data": {
"accessHost": "DSLAM-A64",
"accessIp": "192.0.2.10",
"dslamPort": "1/5/0",
"aggregationHost": "PH26L-63",
"vlan": "${$value.canvasDemoVlan}",
"regionalHost": "PA77R-01",
"primaryHost": "PA77B-01",
"primaryPort": "1450",
"backupHost": "PA77B-02",
"backupPort": "2236",
"aggregationPort": "0/17/0",
"serviceId": "1474408",
"pseudowire": "2110434",
"hostname": "${$value.canvasDemoHostname}",
"ipAddress": "${$value.canvasDemoIp}",
"uplink": {
"port": "TenGigE 2/2/1"
},
"status": "${$value.canvasDemoStatus}",
"hasBackup": "${$value.canvasDemoBackup}"
},
"textBindings": [
{
"name": "hostname",
"maxLength": 22,
"fallback": "—"
},
{
"name": "ipAddress",
"maxLength": 39,
"fallback": "—"
}
],
"propertyBindings": [
{
"target": "dslam-a",
"property": "fill",
"path": "status",
"rules": [
{
"equals": "up",
"value": "#dcfce7"
},
{
"equals": "warning",
"value": "#fef3c7"
},
{
"equals": "down",
"value": "#fee2e2"
}
]
},
{
"target": "dm3",
"property": "stroke",
"path": "status",
"rules": [
{
"equals": "up",
"value": "#15803d"
},
{
"equals": "warning",
"value": "#b45309"
},
{
"equals": "down",
"value": "#b91c1c"
}
]
},
{
"target": "dm3",
"property": "stroke-width",
"value": 3
},
{
"target": "dm3",
"property": "stroke-dasharray",
"path": "status",
"rules": [
{
"equals": "down",
"value": "8 5"
}
],
"fallback": "none"
},
{
"target": "bng-backup",
"property": "visibility",
"path": "hasBackup"
},
{
"target": "dm5",
"property": "visibility",
"path": "hasBackup"
}
],
"placeholders": [
{
"name": "{editIp}",
"content": [
0
]
},
{
"name": "{editVlan}",
"content": [
1
]
}
]
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"canvasDemoHostname",
"canvasDemoIp"
]
},
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"canvasDemoVlan"
]
}
]
}
],
"localizationData": {
"cs": {
"config": {
"header": "SVG Canvas · IP DSLAM → MPLS"
}
},
"en": {
"config": {
"header": "SVG Canvas · IP DSLAM → MPLS"
}
}
}
}
]
}

Canvas equipment — 04-canvas-equipment.json

{
"type": "object",
"title": "SVG Canvas — provozní panel / operations panel",
"properties": {
"canvasDemoTemperature": {
"type": "number",
"title": "Teplota (°C)",
"localizationData": {
"cs": {
"title": "Teplota (°C)"
},
"en": {
"title": "Temperature (°C)"
}
},
"default": 24.6,
"config": {
"fractionDigits": 1,
"step": 0.1
},
"widget": {
"type": "number"
}
},
"canvasDemoEquipmentStatus": {
"type": "string",
"title": "Stav zařízení",
"localizationData": {
"cs": {
"title": "Stav zařízení"
},
"en": {
"title": "Equipment status"
}
},
"default": "up",
"oneOf": [
{
"const": "up",
"title": "V provozu / Online"
},
{
"const": "warning",
"title": "Varování / Warning"
},
{
"const": "down",
"title": "Výpadek / Offline"
},
{
"const": "unknown",
"title": "Neznámý / Unknown"
}
],
"widget": {
"type": "select"
}
},
"canvasDemoOperator": {
"type": "string",
"title": "Správce zařízení",
"localizationData": {
"cs": {
"title": "Správce zařízení"
},
"en": {
"title": "Equipment operator"
}
},
"default": "NOC Praha",
"widget": {
"type": "text",
"required": true
}
}
},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"config": {
"header": "SVG Canvas · Provozní panel bez Draw.io"
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-columns"
},
"config": {
"columns": [
{
"width": 6,
"content": [
0
]
},
{
"width": 6,
"content": [
1
]
}
]
},
"items": [
"canvasDemoTemperature",
"canvasDemoEquipmentStatus"
]
},
{
"type": "layout",
"widget": {
"type": "dtl-fluent-svg"
},
"config": {
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" width=\"920\" height=\"410\" viewBox=\"0 0 920 410\">\n<rect x=\"1\" y=\"1\" width=\"918\" height=\"408\" rx=\"18\" fill=\"#f8fafc\" stroke=\"#cbd5e1\"/>\n<g font-family=\"Arial, sans-serif\" fill=\"#0f172a\">\n<text x=\"28\" y=\"38\" font-size=\"14\" fill=\"#64748b\">PROVOZNÍ PŘEHLED / OPERATIONS</text>\n<text x=\"28\" y=\"72\" font-size=\"25\" font-weight=\"bold\">{{site.name}}</text>\n<rect x=\"28\" y=\"98\" width=\"270\" height=\"122\" rx=\"12\" fill=\"#ffffff\" stroke=\"#cbd5e1\"/>\n<text x=\"48\" y=\"128\" font-size=\"14\" fill=\"#475569\">TEPLOTA / TEMPERATURE</text>\n<text x=\"48\" y=\"185\" font-size=\"36\">{{temperature}} °C</text>\n<rect data-canvas-id=\"status-card\" x=\"324\" y=\"98\" width=\"270\" height=\"122\" rx=\"12\" fill=\"#e2e8f0\" stroke=\"#cbd5e1\"/>\n<text x=\"344\" y=\"128\" font-size=\"14\" fill=\"#475569\">STAV / STATUS</text>\n<text x=\"344\" y=\"181\" font-size=\"25\">{{status}}</text>\n<rect x=\"620\" y=\"98\" width=\"272\" height=\"122\" rx=\"12\" fill=\"#ffffff\" stroke=\"#cbd5e1\"/>\n<text x=\"640\" y=\"128\" font-size=\"14\" fill=\"#475569\">ALARMY / ALARMS</text>\n<text x=\"640\" y=\"185\" font-size=\"36\">{{alarmCount}}</text>\n<text x=\"28\" y=\"252\" font-size=\"13\" fill=\"#64748b\">SPRÁVCE / OPERATOR — KLIKNUTÍM UPRAVÍTE / CLICK TO EDIT</text>\n<rect x=\"28\" y=\"266\" width=\"864\" height=\"112\" rx=\"12\" fill=\"#ffffff\" stroke=\"#cbd5e1\"/>\n<foreignObject x=\"44\" y=\"274\" width=\"832\" height=\"94\"><xhtml:div style=\"width:100%;height:100%;font-family:Arial;text-align:left;\">{editOperator}</xhtml:div></foreignObject>\n</g></svg>",
"data": {
"site": {
"name": "Datové centrum Praha · Rack A12"
},
"temperature": "${$value.canvasDemoTemperature}",
"status": "${$value.canvasDemoEquipmentStatus}",
"alarmCount": 0
},
"textBindings": [
{
"name": "site.name",
"maxLength": 48
}
],
"propertyBindings": [
{
"target": "status-card",
"property": "fill",
"path": "status",
"rules": [
{
"equals": "up",
"value": "#dcfce7"
},
{
"equals": "warning",
"value": "#fef3c7"
},
{
"equals": "down",
"value": "#fee2e2"
}
]
}
],
"placeholders": [
{
"name": "{editOperator}",
"content": [
0
]
}
]
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"canvasDemoOperator"
]
}
]
}
],
"localizationData": {
"cs": {
"config": {
"header": "SVG Canvas · Provozní panel bez Draw.io"
}
},
"en": {
"config": {
"header": "SVG Canvas · Operations panel without Draw.io"
}
}
}
}
]
}

Canvas demo — 05-canvas-demo.json

Ukázka SVG Canvas: popisky z dat ({{hostname}}, {{router.name}}), zkrácení dlouhého textu, barva a přerušování spoje podle stavu, skrytí záložní větve a IP adresa editovatelná přímo v diagramu. Vložte do zdroje formuláře v návrháři; návrhář zobrazuje výrazy z dat nevyhodnocené, živé hodnoty ukazuje záložka Náhled formuláře. Kresba nese zdroj Draw.io, takže ji tlačítko Upravit v Draw.io otevře k úpravám.

{
"type": "object",
"title": "SVG Canvas – demo",
"description": "Ukázka SVG Canvas: popisky z dat ({{hostname}}, {{router.name}}), zkrácení dlouhého textu, barva a přerušování spoje podle stavu, skrytí záložní větve a IP adresa editovatelná přímo v diagramu. Vložte do zdroje formuláře v návrháři; návrhář zobrazuje výrazy z dat nevyhodnocené, živé hodnoty ukazuje záložka Náhled formuláře. Kresba nese zdroj Draw.io, takže ji tlačítko Upravit v Draw.io otevře k úpravám.",
"properties": {
"hostname": {
"type": "string",
"title": "Hostname DSLAM",
"default": "PH32-DSLAM-51",
"widget": {
"type": "text"
}
},
"linkState": {
"type": "string",
"title": "Stav spoje",
"default": "up",
"oneOf": [
{
"const": "up",
"title": "up – v provozu"
},
{
"const": "warning",
"title": "warning – varování"
},
{
"const": "down",
"title": "down – výpadek"
}
],
"widget": {
"type": "select"
}
},
"showBackup": {
"type": "boolean",
"title": "Zobrazit záložní větev",
"default": true,
"widget": {
"type": "checkbox"
}
},
"ipAddress": {
"type": "string",
"title": "IP adresa",
"default": "192.0.2.51",
"pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$",
"widget": {
"type": "text",
"required": true
}
}
},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-card"
},
"config": {
"header": "SVG Canvas – demo"
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-columns"
},
"config": {
"columns": [
{
"width": 4,
"content": [
0
]
},
{
"width": 4,
"content": [
1
]
},
{
"width": 4,
"content": [
2
]
}
]
},
"items": [
"hostname",
"linkState",
"showBackup"
]
},
{
"type": "layout",
"widget": {
"type": "dtl-fluent-svg"
},
"config": {
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" style=\"background: transparent; background-color: transparent; color-scheme: light dark;\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"762px\" height=\"322px\" viewBox=\"0 0 762 322\" content=\"&lt;mxfile host=&quot;embed.diagrams.net&quot; agent=&quot;tsm-ui docs&quot; compressed=&quot;false&quot;&gt;&lt;diagram id=&quot;svg-canvas-demo&quot; name=&quot;SVG Canvas demo&quot;&gt;1VnbcqM4EP0aHjMFCAN+9CUzO1U7Van1Vu3so2wEaCwjVgjfvn7VSNwMmzh2JtlJuRzUuvfpPt2NLbTYHb8InKffeESY5drR0UJLy3WnyFffIDhpgWcbQSJopEVOK1jRMzFC20hLGpGiN1ByziTN+8INzzKykT0ZFoIf+sNizvq75jghA8Fqg9lQ+heNZKqlgW+38t8ITVKzM3JNxw7XY42gSHHEDx0RerTQQnAu9dPuuCAMVFerRc/7/B+9zbkEyeQ1E2KBd2Q4yaxTyFN9Y8HLLCIwy7HQ/JBSSVY53kDvQUGsZKncMdMdU8YWnHFRzUVxGON4o+SFFHxLOj2+F3jhWvVgsTEo+6qld99jVprdjYAISY6dE5o7fSF8R6Q4qSHpmNYPIxBhYwFJM7fVknowihpXmqSSXaU0dVrZ1wxmNMnUMyMx9MCNqDKrmRHvaBTB5HnMM2kU4vim3dGbHTuBiwcazXhGLtRvRAONPvGcFltQ2Rn8EEv1bS1cax6ohzUWewxXyfkPArfkcCq4Gt6X3YEkohKMQA2xFhNrOrUWyJotdxw2g3UpTpSFlTfh53pD+BxjCsf+EEMjjn8/uMrQJRE/2yWIS8LYHnMJL5hM/OkzkLeuopQx6is+k2Z+78D+PyWvOx6KaomZGuCg/FitU/dXvFnv2woRQp4zmXRFfgL//zAa09sq/eqddWctXouB5KrD+YPDmVUC+GiwPmVAYsESPu0p1i8f4WoVuVeqyPDZ86ctlKEMTtvX2Q3eMh2SnRPYPW/x7L63OG/AhVHB8O7jAsiL3nLJsJLDVoXamWbJn9BYhj2nCv8XPrVc/T779iEulfJCvuRPN5ing4b22Rjk8SJgn/omfY990vwhpaC794rWztAYmyzn5mj99QnUEAlSQFi2Hl0rtK0pUs9lLvBejkfgc6QhvyX2jqBlh3206iS+ppPJG8AFCcWDwqxg/CrMXsUqXCkhZlW6DUp/GeAeWai2PUJN1d8YNW3W0YQ4/YBtj5JLMIdrf80rf7sl0Q1fD1bg3g9WmTOabfU6JBpUTEPceCk2LXBNmtXBk2TRDOqz1hc6+GkV1wWXN6b0qYfRGigczrMy65qVyJHK72YpeP4bEP00Ma3l0QBcNU51I1M6+d5tdGZBs51Wtep5+mISi4TIQaC8KGyG4ArCsKT7vkLvR+pB5e/yzsJlo2Yp3K4kQ/dnkCFUITqU6YgFV1tVNzMh65bwNHShJj2qaw3nIn1ywzcDhua/PCoqRHUwofksgnBVvDMm/hvQ2hpvtmX+8JHchp7ltggXaRPzoPGEpdoQ8FYsb3sX9MeFTHnCM8weW+m8HznHuTF4L3I0Ks94RN6aIqupSu/41BmQc5UTFp2Vn3iVJDZ2FfTtyjV21VqQXrG1p+ZorzGx9r4f/qah5gY05AZTo3QTGXc0kTlXuafDOGSi88dMp6JqjKlmbuCAyUhVi/oc4NsXWKHgfg5gJFHueh8pf3jVcCaMaBAcIGaQqXrB6ry/4wJnGiy+vxh4wCKDrLcz2lp4VrgkYt9Z1VQdRJTwMHP4Hl9uGfFD1l2mqTBVF2F6WmMq6ibVeaBQ9aCGyfC2GvIZ1A5zzluhN5D1pAVU17ASsuawRvXOEl4/mt8Ebnz9OPL2+PnXj274+oxANdu3/ZpJ2l9M0OO/&lt;/diagram&gt;&lt;/mxfile&gt;\"><defs/><g><g data-cell-id=\"0\"><g data-cell-id=\"1\"><g data-cell-id=\"frame\"><g transform=\"translate(0.5,0.5)\"><rect x=\"0\" y=\"0\" width=\"760\" height=\"320\" rx=\"19.2\" ry=\"19.2\" fill=\"#f8fafc\" stroke=\"#64748b\" pointer-events=\"all\" style=\"fill: light-dark(rgb(248, 250, 252), rgb(21, 23, 25)); stroke: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));\"/></g></g><g data-cell-id=\"title\"><g><rect x=\"24\" y=\"16\" width=\"712\" height=\"24\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 28px; margin-left: 26px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #0f172a; \"><div style=\"display: inline-block; font-size: 16px; font-family: Helvetica; color: light-dark(#0f172a, #d3daea); line-height: 1.2; pointer-events: all; white-space: nowrap; \">Popisky z dat · barva spoje podle stavu · editace přímo v diagramu</div></div></div></foreignObject><text x=\"26\" y=\"33\" fill=\"#0f172a\" font-family=\"Helvetica\" font-size=\"16px\" style=\"fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));\">Popisky z dat · barva spoje podle stavu · editace přímo v diagramu</text></switch></g></g></g><g data-cell-id=\"router\"><g transform=\"translate(0.5,0.5)\"><rect x=\"40\" y=\"110\" width=\"170\" height=\"90\" rx=\"10.8\" ry=\"10.8\" fill=\"#e2e8f0\" stroke=\"#475569\" pointer-events=\"all\" style=\"fill: light-dark(rgb(226, 232, 240), rgb(34, 39, 46)); stroke: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 155px; margin-left: 41px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #0f172a; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#0f172a, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; \"><span style=\"font-size: 13px; color: light-dark(rgb(51, 65, 85), rgb(172, 184, 201));\">Router</span><br /><b style=\"font-size: 16px;\">{{router.name}}</b><br /><span style=\"font-size: 12px; color: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));\">{{router.site}}</span></div></div></div></foreignObject><text x=\"125\" y=\"145\" fill=\"#0f172a\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\" style=\"fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));\"><tspan x=\"125\" y=\"145\">Router</tspan><tspan x=\"125\" y=\"159\">{{router.name}}</tspan><tspan x=\"125\" y=\"173\">{{router.site}}</tspan></text></switch></g></g></g><g data-cell-id=\"dslam\"><g transform=\"translate(0.5,0.5)\"><rect x=\"320\" y=\"90\" width=\"240\" height=\"130\" rx=\"10.4\" ry=\"10.4\" fill=\"#f8fafc\" stroke=\"#475569\" pointer-events=\"all\" style=\"fill: light-dark(rgb(248, 250, 252), rgb(21, 23, 25)); stroke: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 238px; height: 1px; padding-top: 105px; margin-left: 321px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #0f172a; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#0f172a, #d3daea); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; \"><span style=\"font-size: 13px; color: light-dark(rgb(51, 65, 85), rgb(172, 184, 201));\">DSLAM</span><br /><b style=\"font-size: 16px;\">{{hostname}}</b></div></div></div></foreignObject><text x=\"440\" y=\"117\" fill=\"#0f172a\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\" style=\"fill: light-dark(rgb(15, 23, 42), rgb(211, 218, 234));\"><tspan x=\"440\" y=\"117\">DSLAM</tspan><tspan x=\"440\" y=\"131\">{{hostname}}</tspan></text></switch></g></g></g><g data-cell-id=\"ip-hint\"><g><rect x=\"336\" y=\"150\" width=\"208\" height=\"20\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 160px; margin-left: 338px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #64748b; \"><div style=\"display: inline-block; font-size: 11px; font-family: Helvetica; color: light-dark(#64748b, #7e8c9f); line-height: 1.2; pointer-events: all; white-space: nowrap; \">IP adresa – upravte přímo zde:</div></div></div></foreignObject><text x=\"338\" y=\"163\" fill=\"#64748b\" font-family=\"Helvetica\" font-size=\"11px\" style=\"fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));\">IP adresa – upravte přímo zde:</text></switch></g></g></g><g data-cell-id=\"edit-ip-slot\"><g transform=\"translate(0.5,0.5)\"><rect x=\"336\" y=\"172\" width=\"208\" height=\"38\" rx=\"3.8\" ry=\"3.8\" fill=\"#ffffff\" stroke=\"#cbd5e1\" pointer-events=\"all\" style=\"fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18)); stroke: light-dark(rgb(203, 213, 225), rgb(47, 56, 66));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe flex-start; justify-content: unsafe flex-start; width: 210px; height: 38px; padding-top: 172px; margin-left: 336px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; width: 208px; height: 38px; overflow: hidden; color: #000000; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; width: 100%; height: 100%; white-space: normal; word-wrap: normal; \">{editIp}</div></div></div></foreignObject><text x=\"336\" y=\"184\" fill=\"#000000\" font-family=\"Helvetica\" font-size=\"12px\" style=\"fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));\">{editIp}</text></switch></g></g></g><g data-cell-id=\"uplink\"><g><path d=\"M 210 155 L 320 155\" fill=\"none\" stroke=\"#94a3b8\" stroke-width=\"4\" stroke-miterlimit=\"10\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(148, 163, 184), rgb(87, 100, 118));\"/></g></g><g data-cell-id=\"uplink-state\"><g><rect x=\"210\" y=\"128\" width=\"110\" height=\"18\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 137px; margin-left: 265px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #64748b; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#64748b, #7e8c9f); line-height: 1.2; pointer-events: all; white-space: nowrap; \">stav: {{linkState}}</div></div></div></foreignObject><text x=\"265\" y=\"141\" fill=\"#64748b\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\" style=\"fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));\">stav: {{linkState}}</text></switch></g></g></g><g data-cell-id=\"uplink-ip\"><g><rect x=\"210\" y=\"162\" width=\"110\" height=\"18\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 171px; margin-left: 265px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #64748b; \"><div style=\"display: inline-block; font-size: 12px; font-family: Helvetica; color: light-dark(#64748b, #7e8c9f); line-height: 1.2; pointer-events: all; white-space: nowrap; \">IP: {{ipAddress}}</div></div></div></foreignObject><text x=\"265\" y=\"175\" fill=\"#64748b\" font-family=\"Helvetica\" font-size=\"12px\" text-anchor=\"middle\" style=\"fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));\">IP: {{ipAddress}}</text></switch></g></g></g><g data-cell-id=\"backup-link\"><g transform=\"translate(0.5,0.5)\"><path d=\"M 210 177.5 L 260 177.5 Q 270 177.5 270 187.5 L 270 252 Q 270 262 280 262 L 600 262\" fill=\"none\" stroke=\"#94a3b8\" stroke-width=\"3\" stroke-miterlimit=\"10\" stroke-dasharray=\"18 12\" pointer-events=\"stroke\" style=\"stroke: light-dark(rgb(148, 163, 184), rgb(87, 100, 118));\"/></g></g><g data-cell-id=\"backup-node\"><g transform=\"translate(0.5,0.5)\"><rect x=\"600\" y=\"237\" width=\"130\" height=\"50\" rx=\"10\" ry=\"10\" fill=\"#e2e8f0\" stroke=\"#475569\" pointer-events=\"all\" style=\"fill: light-dark(rgb(226, 232, 240), rgb(34, 39, 46)); stroke: light-dark(rgb(71, 85, 105), rgb(155, 167, 184));\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 262px; margin-left: 601px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: center; color: #334155; \"><div style=\"display: inline-block; font-size: 13px; font-family: Helvetica; color: light-dark(#334155, #acb8c9); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; \">záložní DSLAM</div></div></div></foreignObject><text x=\"665\" y=\"266\" fill=\"#334155\" font-family=\"Helvetica\" font-size=\"13px\" text-anchor=\"middle\" style=\"fill: light-dark(rgb(51, 65, 85), rgb(172, 184, 201));\">záložní DSLAM</text></switch></g></g></g><g data-cell-id=\"legend\"><g><rect x=\"24\" y=\"288\" width=\"712\" height=\"20\" fill=\"none\" stroke=\"none\" pointer-events=\"all\"/></g><g><g><switch><foreignObject style=\"overflow: visible; text-align: left;\" pointer-events=\"none\" width=\"100%\" height=\"100%\" requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"><div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 298px; margin-left: 26px;\"><div style=\"box-sizing: border-box; font-size: 0; text-align: left; color: #64748b; \"><div style=\"display: inline-block; font-size: 11px; font-family: Helvetica; color: light-dark(#64748b, #7e8c9f); line-height: 1.2; pointer-events: all; white-space: nowrap; \">zelená = up · oranžová = warning · červená přerušovaná = down · hostname delší než 14 znaků se zkrátí, celý je v tooltipu</div></div></div></foreignObject><text x=\"26\" y=\"301\" fill=\"#64748b\" font-family=\"Helvetica\" font-size=\"11px\" style=\"fill: light-dark(rgb(100, 116, 139), rgb(126, 140, 159));\">zelená = up · oranžová = warning · červená přerušovaná = down · hostname delší než 14 znaků se zkrátí, celý je v tooltipu</text></switch></g></g></g></g></g></g><switch><g requiredFeatures=\"http://www.w3.org/TR/SVG11/feature#Extensibility\"/><a transform=\"translate(0,-5)\" xlink:href=\"https://www.drawio.com/doc/faq/svg-export-text-problems\" target=\"_blank\"><text text-anchor=\"middle\" font-size=\"10px\" x=\"50%\" y=\"100%\">Text is not SVG - cannot display</text></a></switch></svg>",
"data": {
"hostname": "${$value.hostname}",
"ipAddress": "${$value.ipAddress}",
"linkState": "${$value.linkState}",
"showBackup": "${$value.showBackup}",
"router": {
"name": "PA77R-01",
"site": "Praha, Žižkov"
}
},
"textBindings": [
{
"name": "hostname",
"maxLength": 14,
"fallback": "—"
},
{
"name": "ipAddress",
"fallback": "—"
}
],
"propertyBindings": [
{
"target": "uplink",
"property": "stroke",
"path": "linkState",
"rules": [
{
"equals": "up",
"value": "#15803d"
},
{
"equals": "warning",
"value": "#b45309"
},
{
"equals": "down",
"value": "#b91c1c"
}
],
"fallback": "#94a3b8"
},
{
"target": "uplink",
"property": "stroke-dasharray",
"path": "linkState",
"rules": [
{
"equals": "down",
"value": "8 5"
}
],
"fallback": "none"
},
{
"target": "dslam",
"property": "fill",
"path": "linkState",
"rules": [
{
"equals": "up",
"value": "#dcfce7"
},
{
"equals": "warning",
"value": "#fef3c7"
},
{
"equals": "down",
"value": "#fee2e2"
}
],
"fallback": "#f8fafc"
},
{
"target": "backup-link",
"property": "visibility",
"path": "showBackup"
},
{
"target": "backup-node",
"property": "visibility",
"path": "showBackup"
}
],
"placeholders": [
{
"name": "{editIp}",
"content": [
0
]
}
]
},
"items": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-inplace"
},
"config": {
"disableCountIsSingleChild": true,
"disableAutofocus": true
},
"items": [
"ipAddress"
]
}
]
}
]
}
]
}

Notes​

SVG Canvas: automatic JSON labels, typed dynamic properties, and bounded Fluent Forms editing slots; Draw.io IP DSLAM/MPLS and generic equipment examples.

Complexity: advanced

Tags: svg, drawio, network, inplace, equipment, canvas, automatic-bindings, status-colors

Legacy fixtures 01/02 take form values from apps/datalite-e2e/tests/config-form/svg-network-values.json (or -long) and svg-equipment-values.json. Canvas fixtures 03/04 intentionally include synthetic demo-only defaults on isolated canvasDemo fields; 05 is the smallest complete Canvas form (labels, truncation, status colors, hidden branch, in-place edit) and doubles as the paste-in demo. config.data supplies one object; {{path}} labels resolve automatically, textBindings hold optional overrides, propertyBindings control safe appearance attributes. Sources are in assets/. No backend writes are configured. Components use placeholders[].content indexes. Authoring contract: references/svg-canvas.md in the json-schema-forms skill; runtime and designer details in the fluent-svg and fluent-svg-editor README files.


Tabs dtl-fluent-tab​

The tabs component allows for organizing content into separate tabs or pages. Each tab typically has a label or title, and when a user clicks on a tab, the content associated with that tab is displayed. The tab component is useful for breaking up large amounts of content into smaller, more manageable chunks, and it provides a way for users to easily navigate between different sections of the content.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-tab"
},
"items": [],
"config": {
"tabs": [
{
"header": "Tab 1",
"content": []
},
{
"header": "Tab 2",
"content": []
}
]
}
}

Inputs​

Disable lazy loading

Key: disableLazy

Name: Disable lazy loading

Description: Disables lazy loading of tab content. Content is rendered immediately instead of after tab selection.

Default: false

Enable scrollable tabs

Key: scrollable

Name: Enable scrollable tabs

Description: Allows tab headers to scroll when they overflow the available width.

Default: true

Key for tabs remembering cache

Key: storedTabsActiveIndex

Name: Key for tabs remembering cache

Description: A unique identifier that the application uses to store and retrieve the cached tab data.

Default: null

Tab name

Key: header

Name: Tab name

Description: The title for this tab.

Default: "__expr:this.translocoService.translate(translation.fluentTabEditor.newTab)"

Tab code

Key: id

Name: Tab code

Description: Stable tab code for effects — the activeTabChanged event sends it as previousId/activeId. Unlike indexes, it does not change when tabs are hidden or reordered. Must be unique within the component.

Default: null

Privilege

Key: priv

Name: Privilege

Description: The privilege for displaying component.

Default: null

Hidden

Key: hidden

Name: Hidden

Description: Tick the checkbox if you wish the component to be hidden. It can also be controlled with an expression using the expression editor.

Default: false

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-tab/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen disable lazy — gen-disable-lazy.json

Disable lazy loading: Disables lazy loading of tab content. Content is rendered immediately instead of after tab selection.

{
"type": "object",
"title": "Tabs — Disable lazy loading",
"description": "Disable lazy loading: Disables lazy loading of tab content. Content is rendered immediately instead of after tab selection.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-tab"
},
"items": [],
"config": {
"tabs": [
{
"header": "Tab 1",
"content": []
},
{
"header": "Tab 2",
"content": []
}
],
"disableLazy": true
}
}
]
}

Gen scrollable — gen-scrollable.json

Enable scrollable tabs: Allows tab headers to scroll when they overflow the available width.

{
"type": "object",
"title": "Tabs — Enable scrollable tabs",
"description": "Enable scrollable tabs: Allows tab headers to scroll when they overflow the available width.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-tab"
},
"items": [],
"config": {
"tabs": [
{
"header": "Tab 1",
"content": []
},
{
"header": "Tab 2",
"content": []
}
],
"scrollable": false
}
}
]
}

Text hint tsm-text-hint​

The Text hint component is used to embed text inside a form using an Rich text editor serving as a hint or documentation to the user. An icon can be placed infront of the text symbolizing the type of the hint - ex. informational or warning.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "tsm-text-hint"
},
"items": []
}

Inputs​

Content

Key: content

Name: Content

Description: The content which will be displayed in the component. It is inputted using the editor.

Default: null

Severity

Key: severity

Name: Severity

Description: Severity defines the color of the text and places the corresponding icon infront of the text unless an Optional icon in specified, in which case that one is used

Default: null

Optional icon

Key: customIconCssClass

Name: Optional icon

Description: This is the full icon class string to show the icon. Example: p-icon-check

Default: ""

Additional CSS class

Key: customTextCssClass

Name: Additional CSS class

Description: You can use an additional CSS class to customize the appearance of the component. Examples: text-2xl bg-red-500 flex w-full gap-2 flex-col p-4

Default: ""

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/tsm-text-hint/. Each is a complete validated FluentSchema — copy & adapt for your form.

Gen custom icon css class — gen-custom-icon-css-class.json

Optional icon: This is the full icon class string to show the icon. Example: p-icon-check

{
"type": "object",
"title": "Text hint — Optional icon",
"description": "Optional icon: This is the full icon class string to show the icon. Example: p-icon-check",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "tsm-text-hint"
},
"items": [],
"config": {
"customIconCssClass": "p-icon-search"
}
}
]
}

Gen custom text css class — gen-custom-text-css-class.json

Additional CSS class: You can use an additional CSS class to customize the appearance of the component. Examples: text-2xl bg-red-500 flex w-full gap-2 flex-col p-4

{
"type": "object",
"title": "Text hint — Additional CSS class",
"description": "Additional CSS class: You can use an additional CSS class to customize the appearance of the component. Examples: text-2xl bg-red-500 flex w-full gap-2 flex-col p-4",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "tsm-text-hint"
},
"items": [],
"config": {
"customTextCssClass": "tsm-custom-class"
}
}
]
}

Tlačítkozrušení cetin-cancel-button​

Tlačítkozrušení

Widget Or Layout: unknown

Value:

{
"widget": {
"type": "cetin-cancel-button"
},
"type": "layout"
}

Toolbar dtl-fluent-toolbar​

Toolbar

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-toolbar"
},
"items": []
}

tSM Control tsm-control​

tSM Control - used for positioning static form-field components.

Widget Or Layout: unknown

Value:

{
"type": "tsm-control",
"id": "",
"widget": {
"type": "tsm-control"
}
}

Inputs​

Inputs

Key: inputs

Name: Inputs

Default: {}

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/tsm-control/. Each is a complete validated FluentSchema — copy & adapt for your form.

Task status validation — 01-task-status-validation.json

{
"type": "object",
"properties": {},
"layout": [
{
"type": "tsm-control",
"id": "Task.Toolbar.SelectTaskStatus",
"widget": {
"type": "tsm-control"
},
"config": {
"inputs": {
"disableValidations": true
}
}
}
]
}

Wizard dtl-fluent-steps​

The steps component functions as a versatile wizard that guides users through a multi-step process. It organizes the steps with clear labels, allowing users to easily navigate through the process. With its intuitive interface, users can track their progress, move forward or backward, and complete complex tasks in a manageable manner. The component adjusts dynamically to accommodate varying numbers of steps, ensuring a seamless user experience.

Widget Or Layout: unknown

Value:

{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true
}
}

Inputs​

Button "Back"

Key: backButton

Name: Button "Back"

Description: Button "Back"

Default: false

Button "Next"

Key: nextButton

Name: Button "Next"

Description: Button "Next"

Default: false

Align "Next" button right

Key: dockNextButtonRight

Name: Align "Next" button right

Description: Align "Next" button right

Default: false

Show "Next" button first

Key: flipButtons

Name: Show "Next" button first

Description: Show "Next" button first

Default: false

Bottom navigation bar (Back | Step X of Y | Next)

Key: stepBar

Name: Bottom navigation bar (Back \| Step X of Y \| Next)

Description: Shows a bottom bar with Back/Next buttons and a "Step X of Y" counter. Replaces the original button layout.

Default: false

Stick the bar to the bottom edge

Key: stepBarSticky

Name: Stick the bar to the bottom edge

Description: The bar stays visible at the bottom edge for long step content.

Default: false

Disable lazy loading

Key: disableLazy

Name: Disable lazy loading

Description: Disables lazy loading of step content. All steps are rendered immediately (inactive ones are hidden), so the state and validation of other steps are accurate before they are first displayed. Slower on large forms.

Default: false

Show step states (header indicators)

Key: showStepStates

Name: Show step states (header indicators)

Description: Shows a state indicator on step headers: missing required fields, errors, completed steps, and dimmed not-yet-visited steps.

Default: false

Hide the unviewed steps notice

Key: hideRequiredStepsNotice

Name: Hide the unviewed steps notice

Description: The notice listing not-yet-viewed required steps is not shown above the steps. Saving stays blocked.

Default: false

Hide wizard step numbers

Key: stepsNumberHidden

Name: Hide wizard step numbers

Description: Hide wizard step numbers

Default: false

Disable step validations

Key: disableStepValidations

Name: Disable step validations

Description: Disable step validations

Default: false

Navigation mode

Key: navigationMode

Name: Navigation mode

Description: Free movement allows clicking any step. Sequential mode only allows moving forward to the immediately following step; already visited steps stay accessible.

Default: null

Default step

Key: activeIndex

Name: Default step

Description: The step opened after the form loads. With an expression, the active step can be driven by a form value.

Default: 0

Step name

Key: header

Name: Step name

Description: The title for this step.

Default: "__expr:this.translocoService.translate(translation.fluentStepsEditor.newStep)"

Step code

Key: id

Name: Step code

Description: Stable step code for effects — the activeStepChanged event sends it as previousId/activeId. Unlike indexes, it does not change when steps are hidden or reordered. Must be unique within the component.

Default: null

Privilege

Key: priv

Name: Privilege

Description: The privilege for displaying component.

Default: null

Hidden

Key: hidden

Name: Hidden

Description: Tick the checkbox if you wish the component to be hidden. It can also be controlled with an expression using the expression editor.

Default: false

Required to view before saving

Key: requiredView

Name: Required to view before saving

Description: The entity cannot be saved until the user opens this step. It can also be controlled with an expression using the expression editor.

Default: false

Custom "Next" button label

Key: nextLabel

Name: Custom "Next" button label

Description: Overrides the default "Next" button label on this step.

Default: null

Custom "Back" button label

Key: backLabel

Name: Custom "Back" button label

Description: Overrides the default "Back" button label on this step.

Default: null

Examples​

Curated configurations from libs/framework/fluent-forms/__fixtures__/widgets/dtl-fluent-steps/. Each is a complete validated FluentSchema — copy & adapt for your form.

Guided wizard — 01-guided-wizard.json

{
"type": "object",
"title": "Guided wizard — sequential mode with step states",
"properties": {
"customerName": {
"type": "string",
"title": "Customer name",
"widget": {
"type": "text",
"required": true
}
},
"customerEmail": {
"type": "string",
"title": "Customer email",
"widget": {
"type": "text"
}
},
"serviceCode": {
"type": "string",
"title": "Service code",
"widget": {
"type": "text",
"required": true
}
},
"note": {
"type": "string",
"title": "Note",
"widget": {
"type": "text"
}
}
},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"config": {
"steps": [
{
"header": "Customer",
"content": [
0,
1
],
"requiredView": true,
"nextLabel": "Continue to services"
},
{
"header": "Services",
"content": [
2
],
"requiredView": true
},
{
"header": "Summary",
"content": [
3
]
}
],
"navigationMode": "sequential",
"showStepStates": true,
"nextButton": true,
"backButton": true,
"stepBar": true,
"stepBarSticky": true,
"activeIndex": 0
},
"items": [
"customerName",
"customerEmail",
"serviceCode",
"note"
]
}
]
}

Gen back button — gen-back-button.json

Button "Back": Button "Back"

{
"type": "object",
"title": "Wizard — Button \"Back\"",
"description": "Button \"Back\": Button \"Back\"",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true
}
}
]
}

Gen dock next button right — gen-dock-next-button-right.json

Align "Next" button right: Align "Next" button right

{
"type": "object",
"title": "Wizard — Align \"Next\" button right",
"description": "Align \"Next\" button right: Align \"Next\" button right",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true,
"dockNextButtonRight": true
}
}
]
}

Gen flip buttons — gen-flip-buttons.json

Show "Next" button first: Show "Next" button first

{
"type": "object",
"title": "Wizard — Show \"Next\" button first",
"description": "Show \"Next\" button first: Show \"Next\" button first",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true,
"flipButtons": true
}
}
]
}

Gen next button — gen-next-button.json

Button "Next": Button "Next"

{
"type": "object",
"title": "Wizard — Button \"Next\"",
"description": "Button \"Next\": Button \"Next\"",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true
}
}
]
}

Gen step bar sticky — gen-step-bar-sticky.json

Stick the bar to the bottom edge: The bar stays visible at the bottom edge for long step content.

{
"type": "object",
"title": "Wizard — Stick the bar to the bottom edge",
"description": "Stick the bar to the bottom edge: The bar stays visible at the bottom edge for long step content.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true,
"stepBarSticky": true
}
}
]
}

Gen step bar — gen-step-bar.json

Bottom navigation bar (Back | Step X of Y | Next): Shows a bottom bar with Back/Next buttons and a "Step X of Y" counter. Replaces the original button layout.

{
"type": "object",
"title": "Wizard — Bottom navigation bar (Back | Step X of Y | Next)",
"description": "Bottom navigation bar (Back | Step X of Y | Next): Shows a bottom bar with Back/Next buttons and a \"Step X of Y\" counter. Replaces the original button layout.",
"properties": {},
"layout": [
{
"type": "layout",
"widget": {
"type": "dtl-fluent-steps"
},
"items": [],
"config": {
"steps": [
{
"header": "Step 1",
"content": []
},
{
"header": "Step 2",
"content": []
}
],
"nextButton": true,
"backButton": true,
"stepBar": true
}
}
]
}

Notes​

Guided wizard: sequential navigation, header state indicators, bottom navigation bar with a step counter, and two steps required to view before saving.

Complexity: intermediate

Tags: layout, wizard, steps, validation

navigationMode falls back to disableNextSteps for legacy schemas ('sequential' when true). requiredView blocks form validity until the step is opened and accepts a JEXL expression, so a step can be required conditionally. config.hideRequiredStepsNotice hides the notice listing not-yet-viewed required steps without unblocking the save. config.activeIndex accepts a JEXL expression to drive the active step from a form value. Only the active step is rendered; set disableLazy: true to render every step at once (inactive ones hidden) so validation and step states of not-yet-opened steps — including nested forms and characteristics — are accurate.