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=\"<mxfile host="127.0.0.1" agent="CETIN draw.io skill" compressed="false"><diagram id="redraw-dslam-mpls" name="DSLAM to MPLS">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=</diagram></mxfile>\"><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=\"<mxfile host="127.0.0.1" agent="CETIN draw.io skill" compressed="false"><diagram id="redraw-dslam-mpls" name="DSLAM to MPLS">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=</diagram></mxfile>\"><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=\"<mxfile host="embed.diagrams.net" agent="tsm-ui docs" compressed="false"><diagram id="svg-canvas-demo" name="SVG Canvas demo">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/</diagram></mxfile>\"><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.