File size: 2,496 Bytes
42ee455
 
 
 
 
 
 
 
 
 
 
 
 
b699ae9
 
42ee455
 
 
 
 
 
b699ae9
42ee455
 
 
 
 
b699ae9
 
 
 
 
 
 
 
 
 
 
 
42ee455
b699ae9
 
 
42ee455
b699ae9
42ee455
 
 
 
 
 
 
 
 
 
 
 
 
 
cb3fc60
06ff95b
cb3fc60
42ee455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b699ae9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""Contains custom components used inside the dashboard."""

from typing import Literal

import dash_bootstrap_components as dbc
import vizro.models as vm
from dash import dcc, html

try:
    from pydantic.v1 import Field
except ImportError:  # pragma: no cov
    from pydantic import Field

from urllib.parse import quote


class CodeClipboard(vm.VizroBaseModel):
    """Code snippet with a copy to clipboard button."""

    type: Literal["code_clipboard"] = "code_clipboard"
    code: str
    mode: Literal["vizro", "plotly"]
    language: str = ""

    def build(self):
        """Returns the code clipboard component inside an accordion."""
        markdown_code = "\n".join([f"```{self.language}", self.code, "```"])

        pycafe_link = dbc.Button(
            [
                "Edit code live on PyCafe",
                html.Span("open_in_new", className="material-symbols-outlined open-in-new"),
            ],
            href=f"https://py.cafe/snippet/vizro/v1#code={quote(self.code)}",
            target="_blank",
            className="pycafe-link",
        )

        return html.Div(
            [
                pycafe_link if self.mode == "vizro" else None,
                dcc.Clipboard(target_id=self.id, className="code-clipboard"),
                dcc.Markdown(markdown_code, id=self.id),
            ],
            className="code-clipboard-container",
        )


class Markdown(vm.VizroBaseModel):
    """Markdown component."""

    type: Literal["markdown"] = "markdown"
    text: str = Field(
        ..., description="Markdown string to create card title/text that should adhere to the CommonMark Spec."
    )
    classname: str = ""

    def build(self):
        """Returns a markdown component with an optional classname."""
        return dcc.Markdown(
            id=self.id, children=self.text, dangerously_allow_html=False, className=self.classname, link_target="_blank"
        )


class FlexContainer(vm.Container):
    """Custom flex `Container`."""

    type: Literal["flex_container"] = "flex_container"
    title: str = None  # Title exists in vm.Container but we don't want to use it here.

    def build(self):
        """Returns a flex container."""
        return html.Div(
            id=self.id, children=[component.build() for component in self.components], className="flex-container"
        )


vm.Container.add_type("components", FlexContainer)
vm.Container.add_type("components", Markdown)
vm.Container.add_type("components", CodeClipboard)