Pages are the objects that govern the appearance of the frontend in the Virtualitics AI Platform (VAIP). They contain all of the elements that a user views and interacts with within an App.
A Page object can be thought of as a web page canvas at any given point in an App. While frontend and backend tasks are performed in Steps, Pages must be invoked to display and/or update the content that a user sees when running an App.
Pages are like Apps and Steps in that they are ubiquitous within the VAIP. Any App you write needs at least one Page.
Exploring Pages
A hierarchical structure has been built into Pages to allow you fine control over content layout on pages:
- Pages: Parent object containing everything a user might see in an App at the conclusion of a Step.
-
Sections:
- Pages must have at least one Section.
- Sections operate as dividers between Cards and Elements, and can be used to display groups of Elements with titles (headings) and descriptions.
-
Cards:
- A Section will likely consist of one or more Cards.
- A Card object contains all Elements to be displayed on a given card-style UI element.
-
Elements
- Elements must exist in Cards.
- Please refer to the Elements article for an overview of the Elements supported in the VAIP.
Page Layouts
A combination of Sections, Cards, and Elements can be used to customize Pages, providing end users with a streamlined data input/processing process and consumable tables and plots.
In the example below, you'll see a Page with:
- A Page title (“Merging Data & Engineering Features”)
- One Section (no title; contains two Cards)
-
Card #1: “Visualizing Training Data Gearbox Lifetime”
- This Card contains three bar plots (each bar chart is a Plot Element) in two rows:
- Row #1: Single Bar Plot (“Overview of Component Lifetime in Training Data”)
- Row #2: Two Bar Plots; each bar chart takes up the same width within the row
- This Card contains three bar plots (each bar chart is a Plot Element) in two rows:
-
Card #2: “Visualizing Training Data Gearbox Failures”
- This Card also contains three (bar) Plot Elements arranged in two Rows.
-
Card #1: “Visualizing Training Data Gearbox Lifetime”
- One Section (no title; contains two Cards)
Card Layouts
Use the Row and Column classes within Card.content to define layouts within pages. Rows are used to create horizontal layouts and Columns are used to create vertical layouts. Additionally, ratios can be set to create relative sizes between elements within a Row or Column.
This is how we define the layout of the first card ("Visualizing Training Data Gearbox Lifetime") in the image above:
# Generate lifetime hours card and add to page
selected_cols = ['Remaining Useful Life (hours)', 'Serial Number']
data_max = train_data[selected_cols].groupby(by='Serial Number').max().reset_index()
data_max = data_max.rename(columns={'Remaining Useful Life (hours)': 'Component Lifetime (hours)'})
data_max = data_max.sort_values(by='Component Lifetime (hours)')
bar_plot_max_life = create_bar_plot(data_max, 'Serial Number', 'Component Lifetime (hours)',
f'Overview of Component Lifetime in Training Data', is_primary=True)
bar_plot_max_life_low = create_bar_plot(data_max.head(20), 'Serial Number', 'Component Lifetime (hours)',
f'Worst Performing Components by Lifetime in Training Data')
bar_plot_max_life_high = create_bar_plot(data_max.tail(20), 'Serial Number', 'Component Lifetime (hours)',
f'Best Performing Components by Lifetime in Training Data')
dashboard_card_lifetime = Card(
title="Visualizing Training Data Gearbox Lifetime",
content=[bar_plot_max_life, Row([bar_plot_max_life_low, bar_plot_max_life_high])])
# Adding lifetime dashbaord to page
current_page.add_card_to_section(dashboard_card_lifetime, "")
If you want to add Columns to your layout, you must define them within a Row as shown below:
content=[Row([bar_plot_max_life,
Column([bar_plot_max_life_low, bar_plot_max_life_high)]
])
])
]
This would create a layout with two columns where the left column contains the bar_plot_max_life plot and the right column contains the bar_plot_max_life_low and bar_plot_max_life_high plots stacked vertically.
Creating a Page
In these articles, the Hello World tutorial App is used to provide context for the code being used. For a more high-level runthrough of the code in Hello World, see this article. For more detailed technical documentation, see the Virtualitics SDK.
Once you have brought in your imports and created a Step, you’re now ready to create a Page within that Step. To do so, we will create a Page with one Section that contains one Card, with a simple Element within the Card.
First, ensure that you have the correct imports and have created a Step to contain your page. For more information about creating a Step, see this article.
In this example, we want our User to see a Page with a title, a Section with a title, and in that section, we want a Card displayed with a simple Element. In this case, it will be a DataUpload Element for the User to leverage to upload their data.
To create this, after your created Step (also shown below), add the following code:
# This step has the user upload the dataset we'll be using
class DataUpload(Step):
dataset_name = "SP 500 Dataset"
def run(self, flow_metadata):
# Get store_interface and then current page and section
store_interface = StoreInterface(**flow_metadata)
page = store_interface.get_page()
section = page.get_section_by_title("")
# Set section title
upload_section_title = "Loading Data from Databases, Datastores, and Data Lakes"
section.title = upload_section_title
# Create DataUpload Card
guide_link = "https://docs.virtualitics.com/hc/en-us/articles/24831125452307-Configure-a-Connection"
data_link = "https://docs.virtualitics.com/hc/en-us/articles/24831066190995-Flow-Building-Guide-1-Hello-World"
upload_subtitle1 = (
f"To learn more about how to load data from databases, datastores,"
f" and data lakes, check out this link: {guide_link}"
)
upload_subtitle2 = (
f"You can find the relevant data for this tutorial here: {data_link}"
)
upload_subtitle = upload_subtitle1 + "\n \n" + upload_subtitle2
data_upload_card = Card(
title="Data Source Title (Optional): Upload the stock ticker data!",
content=[
DataSource(
title="S&P 500 Dataset",
options=["csv"],
description=upload_subtitle,
show_title=False,
)
],
)
# Add card to section, set section title and subtitle, and update page
page.add_card_to_section(data_upload_card, "")
store_interface.update_page(page)
Defining Sections, Pages, and Steps
After all of your steps are defined, you will define Sections and Pages and feed them into the Data Upload Step, as shown in the code below:
# Build data upload step
data_upload_section = Section("", [])
data_upload_page = Page(
"Getting Data Into the Platform", [data_upload_section]
)
data_upload_step = DataUpload(
title="Data Upload",
description="Upload the S&P 500 data.",
parent="Inputs",
type=StepType.INPUT,
page=data_upload_page,
)
This will result in the App appearing like this to the user:
When building a more complex AI App, you may choose to incorporate multiple Sections with multiple Cards and multiple Elements on your Page.
For more information on building Pages, see the Virtualitics SDK documentation.