Skip to the content.

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:

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:

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:

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')

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)
})

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.


Last Gasp

Further Resources and Learning

Becoming a Crafting Superhero