Simplifying Software Architecture Like a Superhero
A Lightweight Approach to Crafting Interactive and Dynamic Data-Driven Reports and Visualizations
Introduction
Getting Started with Crafting Reports
Adding Graphs to Your Reports
Dynamic Graph Data
Advanced Report Customization
Case Studies and Examples
Last Gasp
Introduction
Crafting and the Superhero Tool Chain
The Superhero Tool Chain is a set of software development tools designed to help developers build, deploy, and maintain software solutions more effectively. By providing developers with tools that simplify common tasks and promote best practices, the Superhero Tool Chain allows the developer to focus on delivering buisness value and creating high-quality software.
In this section, we will introduce Crafting, its role in the Superhero Tool Chain, and how it complements the other tools in the series.
Understanding the Superhero Tool Chain
The Superhero Tool Chain consists of various tools that facilitate different aspects of software development, such as:
- Superhero Core: A lightweight JavaScript framework that simplifies the development of web applications by providing reusable components and an easy-to-use API.
- Superhero Eventsource: A flexible data storage solution that supports a variety of data models and provides seamless integration with other components of the Superhero Tool Chain. Inspired by Event Sourcing as described by Greg Young.
- Superhero Crafting: A library for creating interactive, data-driven reports and visualizations. Inspired by Streamlit and similar solutions.
These tools are designed to address different aspects of software development, making it easier for developers to build and manage solutions while utelizing well-known software development approaches.
Introducing Crafting
Crafting provides developers with a simple, efficient, and extensible solution for creating interactive, data-driven reports and visualizations. With a wide variety of built-in chart types and extensive customization options, Crafting allows developers to easily design and implement visually appealing and informative reports.
Key features of Crafting include:
- Support for multiple chart types, such as line graphs, bar charts, area charts, candle bar charts, and more.
- Flexible integration with various data sources, such as different APIs and databases.
- A responsive, mobile-friendly design that adapts to different screen sizes and devices.
- Customization options for styling, interactivity, and performance tuning.
- A modular architecture that allows for addition of new chart types and features than what’s already provided.
Crafting’s Role in the Superhero Tool Chain
Crafting plays a data visualization role in the Superhero Tool Chain that’s offering a simple and efficient way to create dynamic, data-driven reports. This capability is essential when monitoring and tracing issues in a data driven systems, where understanding and analyzing complex data is key to making informed decisions and optimizing system performance.
By working with Crafting in the Superhero Tool Chain, developers can create comprehensive reporting solutions that incorporate data from various sources, allowing developers to build live dashboards and monitoring systems that accurately reflect the current state of the system.
About This Book
This book is part of the “Simplifying Software Architecture Like a Superhero” series, which focuses on providing practical, lightweight approaches to solving common software development challenges. In this installment, we explore how to create interactive and dynamic data-driven reports and visualizations using the Superhero Crafting solution, an essential tool within the Superhero Tool Chain.
Throughout this book, we will guide you through the process of designing, implementing, and customizing a variety of reports and visualizations using the Crafting solution. The goal is to provide you with the knowledge and techniques needed to build informative and visually appealing reports that can help drive better decision-making within your buisness.
This book is designed for developers, data analysts, and software architects who are interested in creating dynamic, data-driven reports and visualizations. A basic understanding of JavaScript and web development concepts is assumed. Familiarity with the Superhero Tool Chain or other tools in the series would be beneficial but is not required.
Whether you’re new to the Superhero Tool Chain or an OG, this book aims to provide you with valuable insights, techniques, and practical examples.
Prerequisites and Setup
This section will guide you through the necessary prerequisites and steps to get started with Crafting.
Prerequisites
To follow along with this book, you will need:
-
Node.js
A JavaScript runtime that allows you to run JavaScript code on the server-side. You can download the latest version of Node.js from the official website: https://nodejs.org/. Installing Node.js will also include the Node Package Manager (npm), which is required to manage dependencies. -
Basic knowledge of JavaScript and web development
Familiarity with JavaScript and web development concepts, such as HTML, CSS, and the DOM, will be essential to understanding the examples and techniques presented in this book.
Setting Up Your Project
Once you have installed Node.js and npm, follow these steps to set up a new project with the Crafting component:
Step 1: Create a new directory for your project
Open a terminal or command prompt, navigate to the folder where you want to create your project, and run the following command to create a new directory:
mkdir my-crafting-project
Replace my-crafting-project
with your desired project name.
Step 2: Navigate to the project directory
Change to the newly created project directory by running:
cd my-crafting-project
Step 3: Initialize a new npm project
Run the following command to create a new package.json
file, which will store information about your project and its dependencies:
npm init -y
This command will create a package.json
file with default settings. You can customize these settings later if needed.
Step 4: Install the Crafting component
Add the Crafting component as a dependency by running:
npm install crafting
This command will download and install the Crafting library in your project’s node_modules
folder.
Step 5: Creating Your Main JavaScript File
Now that you have set up your project, create a new JavaScript file, main.js, in your project directory. Add the following code to main.js:
require('crafting').bootstrap().then(async (core) =>
{
const crafting = core.locate('crafting')
crafting.title('Crafting')
// your awesome report logic goes here...
})
This code snippet imports the Crafting library, bootstraps the core components, and sets the title of your report. You can now start building your report by adding your desired logic within the // your awesome report logic goes here...
section.
With your project set up and your main JavaScript file in place, you are ready to explore the features of Crafting and begin crafting dynamic, data-driven reports and visualizations.
Getting Started with Crafting Reports
Understanding Crafting’s Core Concepts
Understand the core concepts that form the foundation of the library. By familiarizing yourself with these concepts, you’ll be better equipped to create customized reports that meet your specific requirements. In this section, we’ll cover the following key concepts:
Report
A report is the primary object in Crafting that represents a collection of data and visualizations. Reports can be simple or complex, depending on the data and the goals of the report. Each report contains a layout, which defines the structure and appearance of the report, and one or more charts or visualizations to display the data.
Layout
The layout is a crucial aspect of a Crafting report that determines the structure and appearance of the report. It is responsible for organizing the content, such as charts and other visual elements, and ensuring that the report is visually appealing and easy to read. Layouts can be simple, with a single chart or visualization, or complex, with multiple charts and visual elements arranged in a specific order or hierarchy.
Chart
A chart is a graphical representation of data in a Crafting report. Crafting supports a wide variety of chart types, such as line graphs, bar charts, area charts, and candle bar charts. Each chart type is designed to present data in a specific way, making it easier for the report’s readers to understand and analyze the information. You can choose the most suitable chart type for your data based on the relationships and trends you want to emphasize.
Creating Your First Report
In this section, we’ll walk you through the process of creating your first report using Crafting. We assume that you have already completed the Prerequisites and Setup chapter and have your main JavaScript file set up as described.
require('crafting').bootstrap().then((core) =>
{
const crafting = core.locate('crafting')
crafting.header('Chart example')
crafting.caption('Chart example caption...')
const
random_walk = crafting.random_walk(100),
chart_line = crafting.chart_line({ dataset:[ random_walk ] })
})
In above example, we first require the Crafting library and bootstrap it, then its demonstrated how to create a basic report structure with Crafting, including a header element and a chart. We create a line chart by generating a random walk data set using the random_walk
method and creating a new line chart using the chart_line
method with the generated data.
Defining a Layout for Your Report
In this section, we’ll walk you through the process of creating a layout for a report produced by Crafting. We assume that you have already completed the Prerequisites and Setup chapter and have your main JavaScript file set up as described.
Layouts
The Crafting library has 2 types of layouts, one of 2 columns, and one of 3 columns: layout_columns_2
and layout_columns_3
.
const layout = crafting.layout_columns_2()
layout.column1.header('Header example 1')
layout.column1.caption('Caption example 1')
layout.column1.text('Text example 1')
layout.column2.header('Header example 2')
layout.column2.caption('Caption example 2')
layout.column2.text('Text example 2')
Here, we create a two-column layout using the layout_columns_2
method, which returns an object with two columns (column1 and column2). We then define headers, captions, and text for each column using the header, caption, and text methods, respectively.
The columns of the layout instance, has the same interface as the located crafting instance, offering the same functionality in a column as by the main scope of the Crafting solution.
Title
The title is the main heading of your report, which gives a brief overview of the content. Use the title
function to set the title:
crafting.title('Main Title')
Header
Headers are used to break your report into sections and provide a clear structure. Use the header
function to add a header:
crafting.header('Section Header')
Subheader
Subheaders are used to create subsections within a section, providing further organization. Use the subheader
function to add a subheader:
crafting.subheader('Subsection Header')
Caption
Captions provide a brief description of a specific element, such as a graph or table. Use the caption
function to add a caption:
crafting.caption('Graph Caption')
Text
Text is used to add paragraphs and other content to your report. Use the text
function to add plain text:
crafting.text('This is a paragraph of text.')
Table
Tables are an excellent way to display structured data in rows and columns. Use the table
function to create a table:
const tableData =
{
head: ['Column 1', 'Column 2', 'Column 3'],
body:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
}
crafting.table(tableData)
Metric
Metrics display a single numerical value, which can be useful for summarizing key performance indicators or other important data points. Use the metric
function to create a metric:
const metricValue = 42
const metricDisplay = crafting.metric(metricValue)
JSON
JSON is a common format for data interchange, and it can be useful to display JSON data in a human-readable format within your report. Use the json
function to display JSON data:
const jsonData =
{
key1: 'value1',
key2: 'value2',
}
crafting.json(jsonData)
Code
Code blocks can be used to display source code or other text that should be formatted as a monospace font. Use the code
function to create a code block:
const codeExample = `
const example = 'This is a code example'
console.log(example)
`
crafting.code(codeExample)
Adding Graphs to Your Reports
Now that we have covered the basics of creating a report with Crafting, let’s dig deeper and explore how to utelize various types of graphs. Crafting provides a smaller collection of graph types that you can easily add to your reports.
In this section, lets walk you through the process of adding different graphs to your reports.
Line Graph
Line graphs are a popular choice for representing continuous data over time. To add a line graph to your report, use the chart_line
method and pass in an object with a dataset
property containing an array of datasets.
const random_walk = crafting.random_walk(100)
const chart_line = crafting.chart_line({ dataset: [random_walk] })
Bar Chart
Bar charts are suitable for comparing discrete data across categories. To create a bar chart, use the chart_bar
method, similar to the line graph:
const random_walk_1 = crafting.random_walk(100)
const random_walk_2 = crafting.random_walk(100)
const chart_bar = crafting.chart_bar({ dataset: [random_walk_1, random_walk_2] })
Area Chart
Area charts are useful for displaying quantitative data over time and highlighting the total value across a trend. To create an area chart, use the chart_area
function:
const random_walk = crafting.random_walk(50).map((v) => [v, v + 15 + crafting.random_integer(5)])
const chart_area = crafting.chart_area({ dataset: [random_walk] })
Candle Bar Chart
Candlestick charts are widely used in financial markets to visualize price movements over time. They provide a clear picture of the open, close, high, and low prices during a specific time frame. To create a candlestick chart, use the chart_candle
function:
const random_walk = crafting.random_walk_candles(100)
const chart_candle = crafting.chart_candle({ dataset: [random_walk] })
Pie chart
Pie charts are circular charts that display proportions of a whole. They are excellent for visualizing the distribution of a dataset across different categories. To create a pie chart, use the chart_pie
function:
const random_walk = crafting.random_walk(12).map((v) => Math.abs(v))
const chart_pie = crafting.chart_pie({ dataset: random_walk })
Donut chart
Donut charts are similar to pie charts but have a hollow center. They can be used for the same purposes as pie charts. To create a donut chart, use the chart_donut
function:
const random_walk = crafting.random_walk(4).map((v) => Math.abs(v))
const chart_donut = crafting.chart_donut({ dataset: random_walk })
Dynamic Graph Data Updates
In this chapter, we will explore the different ways to update graph data dynamically. The ability to update data in real-time or based on user interactions can provide engaging experiences in your crafted reports.
Crafting’s WebSocket Implementation
Crafting’s dynamic updates and communications between the frontend and the backend are achieved through a WebSocket. The Superhero Crafting solution utelizes the Superhero WebSocket component, part of the same Superhero Tool Chain. The Superhero WebSocket component is built utelizing the WebSocket protocol to offer socket communication functionality. The WebSocket implementation in Crafting allows for seamless data exchange between the client and server without the need to manually refresh the page to see data changes.
The Dynamic Data
Utelize the dynamic data aspects of the graphs for situations where you need to visualize dynamic data that is continuously changed. This can be useful for monitoring systems or any other data source that is updated frequently. With the help of the Websocket solution in the Superhero Tool Chain - utelized by the Crafting solution, we can easily update the graph in real-time.
Here’s an example of how you can create a streamed data graph:
const random_walk = crafting.random_walk(100)
const chart_line = crafting.chart_line({ dataset: [random_walk] })
setInterval(() =>
{
const lastValue = random_walk[random_walk.length - 1]
const input = random_walk[random_walk.length] = crafting.random_walk_next(lastValue)
chart_line.input({ dataset: [random_walk] })
chart_line.emit2all('input appended', { 'dataset.0': input })
}, 1000)
In this example, we update the graph data every second using the setInterval
function. We append a new data point to the random_walk
array and then update the chart using the chart_line.input
method. Finally, we emit the updated data to all connected sockets using the chart_line.emit2all
method.
The Interactiv Graph
Interactive graphs allow you to update the data based on user interactions or other events. For example, you can create an interactive graph that updates when the user clicks a button or selects a different data source, or similar…
example... to come...
If you need to send the updated data to a specific socket instead of all connected sockets, you can use the emit2socket
method. This can be useful in scenarios where you want to tailor the graph updates to specific users or interactions.
Advanced Report Customization
In this chapter, we will explore advanced customization techniques for your reports. Crafting allows you to personalize the look and feel of your reports to match your branding or personal preferences. One of the ways to customize your reports is by changing the color schemes…
Styling Your Reports
Crafting offers configuration settings that enable you to alter the colors of your report. The following example shows the default settings:
{
view:
{
color:
{
graph: [ '#feffbe', '#d7ebba', '#9ad2cb', '#79a9d1', '#7d8ca3', '#59544b', '#36311f' ],
label: '#efe9f4'
}
}
}
Above stated example is the default color settings. The palette features seven colors with a mix of warm and cool tones, a spectrum between pale yellow to a dusty blue.
It’s possible to change the color scheme to suit your needs, or you can use one of these other recomended color schemes.
Grayscale
This palette features five shades of gray, ranging from pure white to very dark gray.
graph: [ '#fff', '#ddd', '#bbb', '#999', '#777' ]
Vibrant Sunset
This palette features five colors with a mix of warm and cool tones, including warm yellows, bright orange and bright red. The colors have an energizing feel.
graph: [ '#f2f3ae', '#edd382', '#fc9e4f', '#f4442e', '#020122' ]
Earthy Tones
This palette features seven colors with a mix of warm and cool tones, including a neutral gray, dusty greenish-blue, pale yellowish-green, bright orange, dark blue-green, bright yellow, and muted olive green.
The colors have a mix of muted and bright tones, with the orange and yellow adding warmth and energy.
graph: [ '#ccccc4', '#80a8a7', '#f3f1e5', '#f08e37', '#203a49', '#eec84b', '#bdc24c' ]
Oceanic Blues
This palette features six colors with a mix of cool and warm tones, including shades of blue, a very dark blue-purple, and a neutral gray. The colors have a calming and sophisticated feel.
graph: [ '#76f9f9', '#5dccf3', '#4688ce', '#2d227d', '#2b134a', '#606b71' ]
Colorful Contrast
This palette features five colors, including a muted turquoise, dark blue, bright yellow, bright red, and neutral gray. The colors have a mix of cool and warm tones, with the bright colors adding energy and warmth to the overall calming feel of the palette.
graph: [ '#70c1b3', '#247ba0', '#ffe066', '#f25f5c', '#50514f' ]
Frosty Serenity
The palette consists of six colors, primarily shades of blue, with one bright reddish-orange accent color. The overall feel of the palette is cool and calming, with the accent color adding energy and interest.
graph: [ '#293241', '#ee6c4d', '#e0fbfc', '#98c1d9', '#98c1d9', '#3d5a80' ]
Customizing Graphs and Chart Elements
To come…
Case Studies and Examples
Lets go through the versatility of Crafting by providing examples that demonstrate how Crafting can be used to create a range of reports and visualizations. These case studies illustrate how to effectively utilize Crafting’s features to present data in a visually appealing, informative, and user-friendly manner.
Each case study is accompanied by detailed explanations and code snippets, purposefully allowing you to follow along and implement the examples altered to suit your own projects to create impactful reports.
Crafting Report for Financial Analyse
In this case study, we will demonstrate how Crafting can be used to create a financial report for the EURUSD currency pair. The following example showcases how to retrieve historical market data, create a line chart, and update it in real-time with new market data.
require('crafting').bootstrap().then((core) =>
{
const
crafting = core.locate('crafting'),
request = core.locate('core/http/request')
crafting.header('Financial Report')
crafting.caption('Chart example of the EURUSD market')
const
symbol = 'EURUSD=X',
interval = '1m',
range = '1h',
url = `https://query1.finance.yahoo.com/v8/finance/chart/${symbol}?interval=${interval}&range=${range}`,
response = await request.get(url),
timestamps = response.data.chart.result[0].timestamp,
prices = response.data.chart.result[0].indicators.quote[0].close,
timeline = timestamps.reduce((timeline, timestamp, index) =>
{
const
date = new Date(timestamp * 1000),
x = date.toJSON()
timeline[x] = prices[index]
return timeline
}, {}),
chart_line = crafting.chart_line({ dataset:[ timeline ] })
// append new market data to the graph each minute...
setInterval(async () =>
{
const
url = `https://query1.finance.yahoo.com/v8/finance/chart/${symbol}?interval=${interval}&range=1m`,
response = await request.get(url),
lastBar = response.data.chart.result[0].indicators.quote[0].close.slice(-1)[0],
x = new Date().toJSON()
timeline[x] = lastBar
chart_line.input({ dataset: [ timeline ] })
chart_line.emit2all('input appended', { 'dataset.0': { [x]:lastBar }})
}, 60e3)
})
- First, the Crafting core is bootstrapped, and the
request
component is located. - The financial report header and caption are set.
- The symbol, interval, and range are defined for the EURUSD market.
- The Yahoo Finance API URL is constructed.
- The historical data is fetched using the API.
- The timestamps and closing prices are extracted from the API response.
- The timeline object is created by combining the timestamps and closing prices.
- A line chart is created using the timeline dataset.
- A
setInterval
function is set up to update the chart every minute. - The latest market data is fetched from the API.
- The last closing price is extracted and added to the timeline.
- The chart is updated with the new dataset.
- An event is emitted to all connected clients to notify them of the new data.
Tracking and Analyzing Event Source Data
In this chapter, we’ll explore how to track and analyze event source data using Crafting and the Superhero Eventsource solution. Event source data can provide valuable insights into the behavior of users or the performance of systems over time. By visualizing this data in real-time, you can make informed decisions and quickly respond to changes or trends.
The example below demonstrates how to read events from redis, using the Superhero Eventsource solution:
const
crafting = require('./src/server'),
EventsourceClientFactory = require('@superhero/core.eventsource/src/client/factory'),
EventsourceMapper = require('@superhero/core.eventsource/src/mapper'),
redisOptions =
{
gateway :
{
url : 'redis://127.0.0.1:6379'
}
}
crafting.core.add('@superhero/core.eventsource/src/schema')
crafting.bootstrap().then(async (core) =>
{
const
crafting = core.locate('crafting'),
eventbus = core.locate('core/eventbus'),
deepmerge = core.locate('core/deepmerge'),
console = core.locate('core/console'),
schema = core.locate('core/schema/composer'),
string = core.locate('core/string'),
esMapper = new EventsourceMapper(schema, string),
factory = new EventsourceClientFactory(console, esMapper, eventbus, deepmerge),
eventsource = factory.create(redisOptions),
group = 'system-report-' + process.env.COMMIT + Math.random()
crafting.title('Eventsource')
const id = Date.parse('2010-01-01T00:00:00Z')
while(event = await eventsource.readStream(group, id))
{
const timestamp = new Date(event.timestamp).toJSON()
dataset[timestamp] = event.data.value
chart_candle.input({ dataset : [ dataset ] })
chart_candle.emit2all('input appended', { 'dataset.0' : { [x]:event.data.value }})
}
})
In this example, we first import the required modules and configure Redis options. We then bootstrap Crafting and create an Eventsource client to read data from the Redis-based event source.
We define a group name for our event source and set an initial ID to start reading events from a specific timestamp. The while
loop reads events from the event source and adds each event to the dataset as a data point with its corresponding timestamp.
Finally, the updated dataset is sent as input to the Crafting chart, and the new data point is emitted to all connected clients, allowing them to see the real-time updates on the chart.
By using Crafting and the Superhero Eventsource module, you can easily track and analyze event source data in real-time, providing valuable insights into system performance or user behavior. This approach enables you to create interactive, dynamic, and responsive reports for a variety of use cases.