Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Taipy extension assets #1228

Merged
merged 4 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 187 additions & 0 deletions docs/userman/gui/extension/accessing_assets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Accessing the library assets

In certain scenarios, you might want to enrich your user interface by displaying a small image alongside text.
For example, when using a caption control to represent a company name along with its logo,
adding an image can enhance visual context and usability.

Traditionally, in HTML, you would use an `img` tag with the `src` attribute pointing to the image’s file path.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
However, directly referencing resources in this way can expose your application to potential security vulnerabilities,
such as unauthorized access or malicious resource requests.

To mitigate these risks, Taipy introduces the `ElementLibrary.get_resource()^` method.
This method acts as a secure gateway for resource handling,
allowing the application to validate and filter resource requests based on predefined settings.
It ensures that only authorized and properly configured files are served, protecting your application while maintaining
functionality.

## Declaring element {data-source="gui:doc/extension/example_library/example_library.py#L62"}

In this section, we will create a new element that displays a logo image alongside a text caption. This visual element
will utilize the `(ElementLibrary.)get_resource()^` method to securely access the image file on the server.

```python title="example_library.py"
import base64

from taipy.gui.extension import Element, ElementLibrary, ElementProperty, PropertyType


class ExampleLibrary(ElementLibrary):
def __init__(self) -> None:
# Initialize the set of visual elements for this extension library
logo_path = self.get_resource("assets/logo.png")
with open(logo_path, "rb") as f:
logo_base64 = base64.b64encode(f.read()).decode("utf-8")

self.elements = {
"logo_with_text": Element(
"text",
{
"text": ElementProperty(PropertyType.string),
"logo_path": ElementProperty(PropertyType.string, default_value=logo_base64),
},
)
}
```

The detailed explanation of the code is as follows:

- The `(ElementLibrary.)get_resource()^`
method retrieves the absolute path to the logo image file on your local file system.
This means the file is not accessible from the front-end.
To make the file accessible via the web, you should use the `(ElementLibrary.)get_resource_url()^` method instead.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
- The `logo_with_text` element includes two properties: `text` and `logo_path`.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
- The `text` property has the type `PropertyType.string^`, meaning it holds a string value.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
- The `logo_path` property has the type `PropertyType.string^`, meaning it holds a string value.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
The `default_value` parameter is set to the base64-encoded image file, which is used as the default value for the property.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved

## Creating the React component {data-source="gui:doc/extension/example_library/front-end/src/LogoWithText.tsx"}
```tsx title="LogoWithText.tsx"
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
import React from "react";
import { useDynamicProperty } from "taipy-gui";

interface CaptionProps {
text: string;
defaultText: string;
logoPath: string;
}

const styles = {
container: {
display: "flex",
alignItems: "center",
},
logo: {
width: "4em",
height: "4em",
marginRight: "10px",
},
};

const LogoWithText = ({ text, defaultText, logoPath }: CaptionProps) => {
const value = useDynamicProperty(text, defaultText, "");

return (
<div style={styles.container}>
<img
src={`data:image/png;base64,${logoPath}`}
alt="LogoWithText"
style={styles.logo}
/>
<div>{value}</div>
</div>
);
};

export default LogoWithText;
```

namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
## Exporting the React component {data-source="gui:doc/extension/example_library/front-end/src/index.ts"}

When the component is entirely defined, it must be exported by the library's JavaScript bundle.
This is done by adding the export directive in the file *<project dir>/<package dir>front-end/src/index.ts*.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved

```ts title="index.ts"
import LogoWithText from "./LogoWithText";

export { LogoWithText };
```

## Using the element {data-source="gui:doc/extension/logo_with_text.py"}

```python title="logo_with_text.py"
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
name = "Taipy"

page = """
<|{name}|logo_with_text|>
"""
```

When you run this application, the page displays the element like this:
<figure>
<img src="../logo_with_text-d.png" class="visible-dark"/>
<img src="../logo_with_text-l.png" class="visible-light"/>
<figcaption>Logo with text</figcaption>
</figure>

# Additional resources {data-source="gui:doc/extension/example_library/example_library.py#L92"}

Beside the `ElementLibrary.get_resource()^` method, Taipy provides other methods to manage resources securely.
One of them is the `ElementLibrary.get_scripts()^` method, which allows you to include JavaScript files in your application.
This method ensures that only authorized scripts are loaded, protecting your application from potential security threats.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved

The code snippet below illustrates how to use the `(ElementLibrary.)get_scripts()^` method to include a JavaScript file that adds animation to your application’s logo.
namnguyen20999 marked this conversation as resolved.
Show resolved Hide resolved
This snippet should be placed within your extension library class, where you override the `(ElementLibrary.)get_scripts()^` method to return a list of script paths.

```python title="example_library.py"
def get_scripts(self) -> list[str]:
return [
"front-end/dist/exampleLibrary.js",
"front-end/scripts/logoAnimation.js",
]
```

## Custom Javascript file {data-source="gui:doc/extension/example_library/front-end/scripts/logoAnimation.js"}

By adding this custom script to your extension library, it will be included in the application bundle.
When the application is run, the script will be executed, adding animation to the logo image.

```js title="logoAnimation.js"
const style = document.createElement('style');
style.innerHTML = `
@keyframes logoAnimation {
from {
transform: scale(1);
}
to {
transform: scale(1.5);
}
}

.logo-animate {
animation: logoAnimation 2s infinite alternate;
}
`;
document.head.appendChild(style);

document.addEventListener("DOMContentLoaded", () => {
const checkForElement = setInterval(() => {
const logoImage = document.querySelector('img[alt="LogoWithText"]');
if (logoImage) {
logoImage.classList.add('logo-animate');
clearInterval(checkForElement);
}
}, 100);
});
```

<figure>
<img src="../animation_logo_with_text-l.gif" class="visible-light" alt="Logo with Animation">
<img src="../animation_logo_with_text-d.gif" class="visible-dark" alt="Logo with Animation">
<figcaption>Logo with Animation</figcaption>
</figure>

!!! info
Keep in mind that there will be a delay between the page loading and the component rendering.
The script will execute only after the page has fully loaded and the component has been rendered.


Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/userman/gui/extension/dynamic_element/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,5 +355,5 @@ Here are the sections that address the different use cases that your custom
element may need:

- [Scalar properties](scalar_props.md)
- [Tabular data properties](../extension_tabular_data)
- [Tabular data properties](../tabular_data)

41 changes: 0 additions & 41 deletions docs/userman/gui/extension/extension_assets.md

This file was deleted.

6 changes: 3 additions & 3 deletions docs/userman/gui/extension/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ make your way from one example to the next.
- [Custom static elements](static_element.md)
- [Custom dynamic elements](dynamic_element/index.md)
- [Using scalar properties](dynamic_element/scalar_props.md)
- [Using List of Values](extension_list_of_values.md)
- [Using tabular data](extension_tabular_data.md)
- [Accessing assets](extension_assets.md)
- [Using List of Values](list_of_values.md)
- [Using tabular data](tabular_data.md)
- [Accessing assets](accessing_assets.md)
- [Packaging an element library](extension_packaging.md)
Binary file added docs/userman/gui/extension/logo_with_text-d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/userman/gui/extension/logo_with_text-l.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions mkdocs.yml_template
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ nav:
- "Dynamic Elements":
- userman/gui/extension/dynamic_element/index.md
- "Scalar properties": userman/gui/extension/dynamic_element/scalar_props.md
- "List of Values Elements": userman/gui/extension/extension_list_of_values.md
- "Tabular Elements": userman/gui/extension/extension_tabular_data.md
- "List of Values Elements": userman/gui/extension/list_of_values.md
- "Tabular Elements": userman/gui/extension/tabular_data.md
- "Accessing assets": userman/gui/extension/accessing_assets.md

- "Scenario features":
- "Data integration":
Expand Down
Loading