mirror of
https://github.com/noodlapp/noodl-docs.git
synced 2026-01-11 14:52:54 +01:00
Initial commit
Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: Michael Cartner <32543275+michaelcartner@users.noreply.github.com>
This commit is contained in:
18
library/examples/conditional-form.mdx
Normal file
18
library/examples/conditional-form.mdx
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Conditional Form
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Conditional Form
|
||||
|
||||
This is an example of a form using Noodl logical nodes to change contents depending on what options the user picks in the form.
|
||||
The example is walked through in detail in the [Conditional Form with Nodes guide](/docs/guides/business-logic/client-side-biz-logic-nodes).
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/conditional-form/conditional-form-1.zip" name="Mapbox Example" thumb="/library/examples/conditional-form/final-2.png" />
|
||||
|
||||
</div>
|
||||
18
library/examples/crud-form.mdx
Normal file
18
library/examples/crud-form.mdx
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: CRUD Form
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# CRUD Form
|
||||
|
||||
This is an example of a CRUD form. CRUD stands for _Create, Read, Update and Delete_, and the example shows how to do these actions using the Noodl data nodes.
|
||||
The example is walked through in detail in the [UI Controls and Data guide](/docs/guides/data/ui-controls-and-data).
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/crud-form/final-crud-1.zip" name="Mapbox Example" thumb="/library/examples/crud-form/final-crud-thumb.png" />
|
||||
|
||||
</div>
|
||||
18
library/examples/javascript-example.mdx
Normal file
18
library/examples/javascript-example.mdx
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Javascript Example
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Javascript Example
|
||||
|
||||
This example shows how you can mix and match nodes with Javascript in Noodl. It implements a multi select list with a couple of operations on the list, such as batch delete and copy.
|
||||
The example is walked through in detail in the [Business logic with Javascript guide](/docs/guides/business-logic/client-side-biz-logic-js).
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/javascript-example/biz-logic-js.zip" name="Mapbox Example" thumb="/library/examples/javascript-example/final-1.png" />
|
||||
|
||||
</div>
|
||||
17
library/examples/localization.mdx
Normal file
17
library/examples/localization.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Localization Example (i18next)
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Localization Example (i18next)
|
||||
|
||||
This example app shows different usage of the i18next translation module (available [here](/library/modules/i18next)).
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/localization/i18next-example.zip" name="Localization Example" thumb="/library/examples/localization/i18next-screenshot.png"/>
|
||||
|
||||
</div>
|
||||
17
library/examples/mapbox.mdx
Normal file
17
library/examples/mapbox.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Mapbox Example
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Mapbox Example
|
||||
|
||||
This simple example shows how to use the [Mapbox Module](/library/modules/mapbox) to build a map based application. Note that you will need to create an account (free) on [Mapbox](http://www.mapbox.com) to retrive a token needed by the module.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/mapbox/markers.zip" name="Mapbox Example" thumb="/library/examples/mapbox/markers-1.png" />
|
||||
|
||||
</div>
|
||||
26
library/examples/modal-wizard.mdx
Normal file
26
library/examples/modal-wizard.mdx
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: Modal Wizard in Popup
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
import ReactPlayer from 'react-player'
|
||||
|
||||
# Modal Wizard in Popup
|
||||
|
||||
<ReactPlayer
|
||||
playing
|
||||
autoplay
|
||||
muted
|
||||
loop
|
||||
url="modal-wizard/component-stack-final.mp4"
|
||||
/>
|
||||
|
||||
This example shows how to use a [Component Stack](/nodes/component-stack/component-stack-node) in combination with a **Popup** to create a simple modal wizard-type of form to create new items in an **Array**. You can follow the guides for creating a [Popup](/docs/guides/navigation/popups) and [using a Component Stack](/docs/guides/navigation/component-stack) to walk through the example in detail.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/modal-wizard/component-stack-1.zip" name="Modal Wizard In Popup" thumb="/library/examples/modal-wizard/final-1.png" />
|
||||
|
||||
</div>
|
||||
17
library/examples/navigation-url-encoding.mdx
Normal file
17
library/examples/navigation-url-encoding.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Navigation with URL encoded Parameters
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Navigation with URL encoded parameters example
|
||||
|
||||
This example demonstrated how to use **Multiple levels of navigation stacks** and how to **Encode Parameters in the URL** to pass values between pages. Follow the [Navigation Guides](/docs/guides/navigation/basic-navigation) to learn how the example was built.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/navigation-url-encoding/param-encoding-url.zip" name="Navigation Example" thumb="/library/examples/navigation-url-encoding/show-products-page-4.png"/>
|
||||
|
||||
</div>
|
||||
10
library/examples/overview.mdx
Normal file
10
library/examples/overview.mdx
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Examples Overview
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import { ProjectListing } from '../../src/blocks/ProjectListing.tsx'
|
||||
|
||||
# Examples Overview
|
||||
|
||||
<ProjectListing title="All example projects" hasNoLink />
|
||||
19
library/examples/recipe-app.mdx
Normal file
19
library/examples/recipe-app.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: Recipe App
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Recipe App
|
||||
|
||||
This is a simple app for managing recipes built to demonstrate how to work with [Arrays](/nodes/data/array/array-node). It's not connected to a backend but is using the [Static Array](/nodes/data/array/static-array) node. It shows how to add and remove items from an **Array** as well as some simple filtering. It also includes a little bit of **Navigation** logic.
|
||||
|
||||
To learn more about how it's built you can follow the [Array Guide](/docs/guides/data/arrays).
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/recipe-app/arrays.zip" name="Recipe App" thumb="/library/examples/recipe-app/thumbnail-1.png" />
|
||||
|
||||
</div>
|
||||
16
library/examples/sign-up.mdx
Normal file
16
library/examples/sign-up.mdx
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Sign up / Sign In Example
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Sign up / Sign In Example
|
||||
This app includes a simple Sign Up / Sign In form, including buttons for requesting a new password and validating your email. This [video](https://www.youtube.com/watch?v=DWwE1RzuN2o) walks through the example and shows how to connect to a email service using Zapier.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/sign-up/signuptemplate-1-2.zip" name="Task List App" thumb="/library/examples/sign-up/signup_thumbnail.png" cf="/library/examples/sign-up/signup-app-cf.json"/>
|
||||
|
||||
</div>
|
||||
20
library/examples/star-rating-component.mdx
Normal file
20
library/examples/star-rating-component.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: Star Rating Component
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Star Rating Component
|
||||
|
||||
This component shows how to work with *animations*, *visual states* and *component logic* to build a visually rich star rating component. You can also follow the [Build Along](/docs/build-alongs/star-rating-component) clip if you want to see how it's constructed.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/star-rating-component/star-rating-1-1.zip" name="Star Rating Component" thumb="/library/examples/star-rating-component/star-rating-thumb.png"/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
21
library/examples/suatch.mdx
Normal file
21
library/examples/suatch.mdx
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Suatch Google Sheets Example
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Suatch Google Sheets Example
|
||||
|
||||
This neat little color selection app shows how you can use the [Google Sheets module](/library/modules/gsheets) to retrieve data from a **Google Sheets** and how to filter the data. It also shows how to build a good looking list.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton
|
||||
zip="/library/examples/suatch/suatch_1-2.zip"
|
||||
name="Suatch App"
|
||||
thumb="/library/examples/suatch/suatch_1-1-thumb.png"
|
||||
/>
|
||||
|
||||
</div>
|
||||
17
library/examples/survey-app.mdx
Normal file
17
library/examples/survey-app.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Survey App
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Custom Survey App
|
||||
|
||||
This app is a simple user survey. It shows how to work with **navigation**, **visual and interaction states** and **custom components**. You can also follow the [Build Along](/docs/build-alongs/survey-app) clip if you want to see how it's constructed.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/survey-app/survey_app_1-4.zip" name="Custom Survey App" thumb="/library/examples/survey-app/survey_thumbnail2.png"/>
|
||||
|
||||
</div>
|
||||
16
library/examples/task-list-app.mdx
Normal file
16
library/examples/task-list-app.mdx
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Task List App
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Task List App
|
||||
This is a simple example of a Task List App. It's a great starting point if you want to learn about the basics in Noodl. It shows how to do simple **Layouts** with **UI Controls**. It also uses a simple **Backend** with a **Database** to store the tasks created by the users. There is also a [Build Along](/docs/build-alongs/task-list-app) series that walks through the complete app.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/task-list-app/task-app-1-2.zip" name="Task List App" thumb="/library/examples/task-list-app/task_list_thumbnail.png" cf="/library/examples/task-list-app/task-app-cf.json"/>
|
||||
|
||||
</div>
|
||||
17
library/examples/travel-app.mdx
Normal file
17
library/examples/travel-app.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Travel App
|
||||
hide_title: true
|
||||
---
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
|
||||
# Travel App
|
||||
|
||||
This app for travelers shows a number of destinations in a card like **horizontal list**. It also includes a simple **Navigation** system.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton zip="/library/examples/travel-app/travel_app_1-2.zip" name="Travel App" thumb="/library/examples/travel-app/travel_app_thumbnail.png"/>
|
||||
|
||||
</div>
|
||||
117
library/examples/weavy-integration.mdx
Normal file
117
library/examples/weavy-integration.mdx
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: Weavy Integration
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import ImportButton from '/src/components/importbutton';
|
||||
|
||||
# Using Weavy with Noodl
|
||||
|
||||
Weavy is a service that lets you add collaboration features to your app. Chat, feeds and file sharing/editing can be integrated in a fraction of the time it would take to build it from scratch. This template sets up all the user management, authentication and Weavy app registration you need to get started quickly.
|
||||
|
||||
<div className="ndl-image-with-background m">
|
||||
|
||||

|
||||
|
||||
<ImportButton
|
||||
zip="/library/examples/weavy-integration/weavy-template-2.zip"
|
||||
cf="/library/examples/weavy-integration/weavy-template-cf.json"
|
||||
name="Weavy Template"
|
||||
thumb="/library/examples/weavy-integration/weavy-thumb.png"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
In order to connect to Weavy, you need a Weavy account with an API key and an Environment URL. If you don't have that already [here's a handy guide](https://www.weavy.com/docs/learn/weavy-account).
|
||||
|
||||
## Setting up the backend
|
||||
|
||||
When you have the API key and Environment URL you need to add them to the **Config** paramters in the Noodl Cloud Service. If you haven't already imported the project template in the thumbnail above, now is the perfect time to do it.
|
||||
|
||||
With your newly created project open, click the **Cloud Services** tab in the sidebar, and find the Weavy related cloud service that has been created.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Make sure to click the **Use in editor** button if it isn't already in use. Then click **Open dashboard**.
|
||||
|
||||
Navigate to the **Config** tab in the dashboard. Click the **Create a parameter** button to create two parameters named `WeavyAPIKey` and `WeavyEnvUrl`.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
These are case sensitive, so make sure to double check that. Also take an extra look at the `Type` and `Requires master key`.
|
||||
|
||||
When this is done, you should have everything you need to get going.
|
||||
|
||||
## The template structure
|
||||
|
||||
The template has two routers, one for the pages that can be accessed by logged out users, and one for the pages that can be accessed when a user has logged in.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
To be able to use the Weavy apps a user needs to have an account and be logged in. For this there are two pages, called **Signup** and **Login**. You can find all the pages in the **Components Panel**.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Creating a Weavy app
|
||||
|
||||
There are three unstyled example pages when logged in. **Chat**, **Files** and **Posts**, that use the respective Weavy apps **Chat**, **Files** and **Posts**. They all contain a basic page layout, but most importantly they feature the **Weavy App** component.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The **Weavy App** component has two purposes - registering a Weavy app in the Weavy environment (if it hasn't already been registered), and rendering it. It has 3 settings out of the box:
|
||||
|
||||
- **UID**: This is the unique ID of the app you want to register.
|
||||
- **Type**: The type of Weavy app you want to use.
|
||||
- **Height**: The height you want the Weavy app to render in.
|
||||
|
||||
You can pick any string for the UID, but it cannot have any spaces and must contain at least one non-digit character.
|
||||
|
||||
:::info
|
||||
|
||||
If you created a **Weavy App** with a new UID and it doesn't show up on the page, it might be because the Weavy app has not been regisetered yet. This will be the case the first time you run the template app as well.<br/><br/>
|
||||
|
||||
To solve this, try reloading the page that the **Weavy App** component resides in. This will send a request to the Weavy server to register a new app with your new UID.<br/><br/>
|
||||
|
||||
The app registration only has to be done once, so this issue will only show up during development.
|
||||
|
||||
:::
|
||||
|
||||
If you change the **Type** of your Weavy App you will also have to give it a new **UID** for the registration to work properly.
|
||||
|
||||
## Modifying the _Weavy App_ component
|
||||
|
||||
While you can use the **Weavy App** component as is, you will probably want to modify it and make it your own. The best way to do this is to duplicate the component and edit the **Script** node inside of it.
|
||||
|
||||
This way you can have multiple Weavy apps working differently, and always have a clean backup of the integration.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You can read more about customizing Weavy [here](https://www.weavy.com/docs/reference/uikit-js).
|
||||
63
library/modules/avatar/README.md
Normal file
63
library/modules/avatar/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: Avatar Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Avatar Module
|
||||
|
||||
This module allows you to add avatars to your Noodl App.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Nodes
|
||||
|
||||
In this module, there are a few nodes, which include:
|
||||
|
||||
### Avatar Node
|
||||
|
||||
This node is written using the SDK and gives you all the options to modify the style of the avatar.
|
||||
|
||||
### Avatar Group
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This is a simple node that takes in an array of objects.
|
||||
It makes a few modifications to the array like taking only x amount of items and then sending that into a Repeater node,
|
||||
using the Avatar Group Item component.
|
||||
|
||||
Items input:
|
||||
|
||||
```js
|
||||
[
|
||||
{
|
||||
Text: 'AA',
|
||||
Image: 'avatars/avatar-n4KewLKFOZw.jpg',
|
||||
},
|
||||
{
|
||||
Text: 'AA',
|
||||
Image: 'avatars/avatar-TW_z_iUD_bQ.jpg',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
### Avatar Group Item
|
||||
|
||||
A node that maps the inputs from the Avatar Group into what should be used on the Avatar node.
|
||||
|
||||
### [Logic] Name Abbreviation
|
||||
|
||||
Converts a full name to 2 characters.
|
||||
For example:
|
||||
|
||||
```
|
||||
Input: "John Doe"
|
||||
Output: "JD"
|
||||
```
|
||||
76
library/modules/carousel-scroll/README.md
Normal file
76
library/modules/carousel-scroll/README.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Carousel Scroll
|
||||
hide_title: true
|
||||
---
|
||||
# Carousel Scroll
|
||||
|
||||
This module contains a simple horizontal Carousel scroll with the following features:
|
||||
|
||||
- Can be scrolled by swiping horizontally or by clicking scroll buttons
|
||||
- Can auto scroll
|
||||
- One selected item that can be aligned to the left, to the center or to the right
|
||||
- Easy to visually modify
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Overview of what's included in the import project
|
||||
|
||||
When you import the module into your project you will get the following components:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
**Carousel/Carousel Logic**
|
||||
|
||||
This folder contains the logic that controls the scrolling of the application. This is needed by the Carousel component and you should generally not modify this unless you really know what you are doing :)
|
||||
|
||||
**Carousel/Card**
|
||||
|
||||
This component is the template for the card that represents an item in the Carousel list. You should base your own Carousel item on this Card, either by modifying this directly or making a copy of it. Feel free to change the structure of the component, however it's important to keep the **Parent Component** node and have the **Width** output connected to the **Width** of the main container of the Card. Also note the selection logic if you want the Card to change appearance if it's selected.
|
||||
|
||||
**Carousel/Carousel**
|
||||
|
||||
This is the main component that represents the Carousel list. You should generally not change anything major in this component unless you know what you are doing.
|
||||
|
||||
Note that the **Carousel** node should have its cards as direct children. This can be achieved by either manually putting them there or using a [Repeater](/nodes/ui-controls/repeater) node.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
**Carousel Buttons**
|
||||
|
||||
This component the two buttons that controls left/right scrolling. Feel free to style the **Buttons** according to your liking.
|
||||
|
||||
## Using the snippet
|
||||
|
||||
You typically use the snippet by using the **Carousel** component more or less as it is and style the **Card** component to fit your app.
|
||||
The **Carousel** component have a few options available to tweak.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- **Width** - This is the width of each Carousel Card in the Carousel.
|
||||
- **Start from Index** - The selected index from start.
|
||||
- **Item Change Timer** - The delay between each autoscroll. Will only apply if **Autoscroll** is set to **true**.
|
||||
- **Autoscroll** - A boolean that controls if the list should automatically scroll to the next item whenver the **Item Change Timer** expires.
|
||||
|
||||
The most impactful component to change is the **Carousel Card**. You can for example keep the background color **Group** node and then add your own content as children to the **Group** named _Put your content in this group_. Another option is to rebuild the card completely but the it's important to let the width stored in the **Component Object** control the width of the card.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
77
library/modules/chartjs/README.md
Normal file
77
library/modules/chartjs/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Chart.js Module
|
||||
|
||||
[](https://github.com/noodlapp/modules/tree/main/modules/noodl-chartjs)
|
||||
|
||||
This module allows you to add charts to your Noodl App, using [Chart.js](https://www.chartjs.org/).
|
||||
|
||||

|
||||
|
||||
Supported chart types:
|
||||
* Line and Area
|
||||
* Bar
|
||||
* Radar
|
||||
* Doughnut
|
||||
* Pie
|
||||
* Polar Area
|
||||
* Bubble
|
||||
* Scatter
|
||||
|
||||
There are many different kinds inputs to change the style of the chart.
|
||||
Like the title, tooltip and legends.
|
||||
|
||||
## Changing the Data
|
||||
|
||||
To style the chart data, it should be added next to the data it want to style.
|
||||
To recreate for example this chart ([Bar Chart Border Radius](https://www.chartjs.org/docs/latest/samples/bar/border-radius.html)).
|
||||
It should send the style in the datasets to the chart.
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
label: "Fully Rounded",
|
||||
data: [99, 41, 94, 1, 32, -63, 36]
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)",
|
||||
borderWidth: 2,
|
||||
borderRadius: 1.8,
|
||||
borderSkipped: false
|
||||
},
|
||||
{
|
||||
label: "Small Radius",
|
||||
data: [-59, -80, -62, -25, -40, 58, 95],
|
||||
borderColor: "rgb(54, 162, 235)",
|
||||
backgroundColor: "rgba(54, 162, 235, 0.5)",
|
||||
borderWidth: 2,
|
||||
borderRadius: 5,
|
||||
borderSkipped: false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Changing the Scales
|
||||
|
||||
```js
|
||||
Outputs.Scales = {
|
||||
x: {
|
||||
stacked: true
|
||||
},
|
||||
y: {
|
||||
stacked: true
|
||||
}
|
||||
}
|
||||
```
|
||||
78
library/modules/chartjs/charts/bar.md
Normal file
78
library/modules/chartjs/charts/bar.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
title: Bar Chart Example | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Bar Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
[32, 36],
|
||||
[-86, 50],
|
||||
[-37, 0],
|
||||
[-3, 43],
|
||||
[3, -46],
|
||||
[-36, 6],
|
||||
[3, 4]
|
||||
],
|
||||
backgroundColor: "rgb(255, 99, 132)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
[91, 31],
|
||||
[50, -56],
|
||||
[-79, -14],
|
||||
[44, -47],
|
||||
[91, 78],
|
||||
[12, 53],
|
||||
[-71, -16]
|
||||
],
|
||||
backgroundColor: "rgb(54, 162, 235)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Horizontal
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Change the "Index Axis" to "Y" in the property panel.
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [-91.99588477, 52.35768176, -57.81550069, 61.43518519, 64.43072702, -1.91529492, 57.45884774],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [74.65192044, -58.97805213, -37.25823045, -50.31207133, 37.66289438, 43.95061728, -43.79458162],
|
||||
borderColor: "rgb(54, 162, 235)",
|
||||
backgroundColor: "rgba(54, 162, 235, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
50
library/modules/chartjs/charts/bubble.md
Normal file
50
library/modules/chartjs/charts/bubble.md
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Bubble Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Bubble Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
{ x: 6.64266118, y: 17.53858025, r: 9.3146433470507550 },
|
||||
{ x: 96.5149177, y: 11.62894376, r: 7.6109825102880660 },
|
||||
{ x: 76.4077503, y: 26.60408093, r: 11.861539780521262 },
|
||||
{ x: 58.6668381, y: 93.32818930, r: 6.2947102194787380 },
|
||||
{ x: 63.0452674, y: 61.18398491, r: 9.2129629629629620 },
|
||||
{ x: 61.1479766, y: 9.183813440, r: 11.881730109739369 },
|
||||
{ x: 87.5428669, y: 23.74742798, r: 14.084962277091908 }
|
||||
],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
{ x: 13.47350823, y: 60.22333676, r: 10.254929698216735 },
|
||||
{ x: 18.52066187, y: 81.83427641, r: 13.214334705075446 },
|
||||
{ x: 18.52666324, y: 36.67566872, r: 8.6403034979423870 },
|
||||
{ x: 88.80015432, y: 63.01911866, r: 5.5760459533607690 },
|
||||
{ x: 89.83496228, y: 62.09919410, r: 14.916623799725650 },
|
||||
{ x: 78.42121056, y: 75.89120370, r: 11.631172839506174 },
|
||||
{ x: 85.42309671, y: 31.55564129, r: 13.651791838134430 }
|
||||
],
|
||||
borderColor: "rgb(255, 159, 64)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
39
library/modules/chartjs/charts/doughnut.md
Normal file
39
library/modules/chartjs/charts/doughnut.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: Doughnut Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Doughnut Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["Red", "Orange", "Yellow", "Green", "Blue"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [96.79955418, 80.80761317, 36.31772977, 64.56447188, 7.52314815],
|
||||
backgroundColor: [
|
||||
"rgb(255, 99, 132)",
|
||||
"rgb(255, 159, 64)",
|
||||
"rgb(255, 205, 86)",
|
||||
"rgb(75, 192, 192)",
|
||||
"rgb(54, 162, 235)",
|
||||
"rgb(153, 102, 255)",
|
||||
"rgb(201, 203, 207)",
|
||||
"rgba(255, 99, 132, 0.5)",
|
||||
"rgba(255, 99, 132, 0.5)",
|
||||
"rgba(75, 192, 192, 0.5)",
|
||||
"rgba(54, 162, 235, 0.5)"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
68
library/modules/chartjs/charts/line.md
Normal file
68
library/modules/chartjs/charts/line.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Line Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Line Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
-95.88820302, 46.40775034, 99.6090535, 6.92558299, 37.49314129,
|
||||
-58.07098765, 41.22085048
|
||||
],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
48.94890261, 26.84156379, 73.66426612, -52.55829904, 21.01337449,
|
||||
-29.07750343, -0.36179698
|
||||
],
|
||||
borderColor: "rgb(54, 162, 235)",
|
||||
backgroundColor: "rgba(54, 162, 235, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Change Interpolation modes
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Scales = {
|
||||
x: {
|
||||
display: true,
|
||||
title: {
|
||||
display: true
|
||||
}
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Value'
|
||||
},
|
||||
suggestedMin: -10,
|
||||
suggestedMax: 200
|
||||
}
|
||||
}
|
||||
```
|
||||
34
library/modules/chartjs/charts/pie.md
Normal file
34
library/modules/chartjs/charts/pie.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Pie Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Pie Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: [
|
||||
'Red',
|
||||
'Yellow',
|
||||
'Blue'
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
data: [10, 20, 30],
|
||||
backgroundColor: [
|
||||
'#FF5382',
|
||||
'#FFCC34',
|
||||
'#00A3F1'
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
62
library/modules/chartjs/charts/polar-area.md
Normal file
62
library/modules/chartjs/charts/polar-area.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: Polar Area Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Polar Area Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
5.64900549, 32.6611797, 33.64454733, 91.31515775, 18.01868999,
|
||||
33.50823045, 9.38871742
|
||||
],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
80.22805213, 21.33487654, 93.20301783, 52.62259945, 30.45781893,
|
||||
76.09139232, 68.53566529
|
||||
],
|
||||
borderColor: "rgb(54, 162, 235)",
|
||||
backgroundColor: "rgba(54, 162, 235, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Centered point labels
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Scales = {
|
||||
r: {
|
||||
pointLabels: {
|
||||
display: true,
|
||||
centerPointLabels: true,
|
||||
font: {
|
||||
size: 18
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
40
library/modules/chartjs/charts/radar.md
Normal file
40
library/modules/chartjs/charts/radar.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: Radar Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Radar Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
68.09585048, 29.88168724, 29.83624829, 69.19410151, 89.93055556,
|
||||
19.20610425, 80.47753772
|
||||
],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
71.27572016, 7.65003429, 35.27949246, 7.2505144, 28.50137174,
|
||||
66.93329904, 31.1882716
|
||||
],
|
||||
borderColor: "rgb(54, 162, 235)",
|
||||
backgroundColor: "rgba(54, 162, 235, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
81
library/modules/chartjs/charts/scatter.md
Normal file
81
library/modules/chartjs/charts/scatter.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Scatter Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Scatter Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
{ x: 47.22136488, y: 88.67283951, r: 1 },
|
||||
{ x: 84.31584362, y: 63.31875857, r: 1 },
|
||||
{ x: 44.76423182, y: 92.18278464, r: 1 },
|
||||
{ x: 40.91220850, y: 6.129115230, r: 1 },
|
||||
{ x: 92.51286008, y: 54.54046639, r: 1 },
|
||||
{ x: 71.17112483, y: 16.42918381, r: 1 },
|
||||
{ x: 11.45490398, y: 78.21502058, r: 1 }
|
||||
],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
{ x: 5.441100820, y: 16.07981824, r: 1 },
|
||||
{ x: 91.04381001, y: 51.57964678, r: 1 },
|
||||
{ x: 4.938700270, y: 53.64326132, r: 1 },
|
||||
{ x: 22.43441358, y: 60.54226680, r: 1 },
|
||||
{ x: 4.024777090, y: 73.51123114, r: 1 },
|
||||
{ x: 6.499914270, y: 34.52546296, r: 1 },
|
||||
{ x: 60.72402263, y: 70.74545610, r: 1 }
|
||||
],
|
||||
borderColor: "rgb(255, 159, 64)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Multi axis
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Scales = {
|
||||
y: {
|
||||
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
position: 'left',
|
||||
ticks: {
|
||||
color: "rgb(255, 99, 132)",
|
||||
}
|
||||
},
|
||||
y2: {
|
||||
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
position: 'right',
|
||||
reverse: true,
|
||||
ticks: {
|
||||
color: "rgb(54, 162, 235)",
|
||||
},
|
||||
grid: {
|
||||
drawOnChartArea: false // only want the grid lines for one axis to show up
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
56
library/modules/chartjs/charts/stacked-line.md
Normal file
56
library/modules/chartjs/charts/stacked-line.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: Stacked Line Chart | Chart.js Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Stacked Line Chart Example
|
||||
|
||||
## Basic
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset 1",
|
||||
data: [
|
||||
-95.88820302, 46.40775034, 99.6090535, 6.92558299, 37.49314129,
|
||||
-58.07098765, 41.22085048
|
||||
],
|
||||
borderColor: "rgb(255, 99, 132)",
|
||||
backgroundColor: "rgba(255, 99, 132, 0.5)"
|
||||
},
|
||||
{
|
||||
label: "Dataset 2",
|
||||
data: [
|
||||
48.94890261, 26.84156379, 73.66426612, -52.55829904, 21.01337449,
|
||||
-29.07750343, -0.36179698
|
||||
],
|
||||
borderColor: "rgb(54, 162, 235)",
|
||||
backgroundColor: "rgba(54, 162, 235, 0.5)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
Outputs.Scales = {
|
||||
y: {
|
||||
stacked: true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
Outputs.Plugins = {
|
||||
filler: {
|
||||
propagate: true
|
||||
}
|
||||
}
|
||||
```
|
||||
87
library/modules/chartjs/examples/custom-axis.md
Normal file
87
library/modules/chartjs/examples/custom-axis.md
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: Custom Axis
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Custom Axis
|
||||
|
||||
Here is a very rough example of how to setup custom axes, and the different options that are available.
|
||||
|
||||
```js
|
||||
Outputs.Data = {
|
||||
datasets: [
|
||||
{
|
||||
data: [Inputs.data1],
|
||||
yAxisID: "y-axis-1",
|
||||
},
|
||||
{
|
||||
data: [Inputs.data2],
|
||||
yAxisID: "y-axis-2",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
Outputs.Scales = {
|
||||
"y-axis-1": {
|
||||
position: "left",
|
||||
title: {
|
||||
display: true,
|
||||
text: "Hello World",
|
||||
},
|
||||
},
|
||||
"y-axis-2": {
|
||||
position: "right",
|
||||
axis: "y",
|
||||
type: "linear",
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
minRotation: 0,
|
||||
maxRotation: 50,
|
||||
mirror: false,
|
||||
textStrokeWidth: 0,
|
||||
textStrokeColor: "",
|
||||
padding: 3,
|
||||
display: true,
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 3,
|
||||
labelOffset: 0,
|
||||
minor: {},
|
||||
major: {},
|
||||
align: "center",
|
||||
crossAlign: "near",
|
||||
showLabelBackdrop: false,
|
||||
backdropColor: "rgba(255, 255, 255, 0.75)",
|
||||
backdropPadding: 2,
|
||||
color: "#666",
|
||||
},
|
||||
display: true,
|
||||
offset: false,
|
||||
reverse: false,
|
||||
bounds: "ticks",
|
||||
grace: 0,
|
||||
grid: {
|
||||
display: true,
|
||||
lineWidth: 1,
|
||||
drawBorder: true,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
tickLength: 8,
|
||||
offset: false,
|
||||
borderDash: [],
|
||||
borderDashOffset: 0,
|
||||
borderWidth: 1,
|
||||
color: "rgba(0,0,0,0.1)",
|
||||
borderColor: "rgba(0,0,0,0.1)",
|
||||
},
|
||||
title: {
|
||||
display: false,
|
||||
text: "",
|
||||
padding: {
|
||||
top: 4,
|
||||
bottom: 4,
|
||||
},
|
||||
color: "#666",
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
266
library/modules/chartjs/examples/custom-tooltip/README.md
Normal file
266
library/modules/chartjs/examples/custom-tooltip/README.md
Normal file
@@ -0,0 +1,266 @@
|
||||
---
|
||||
title: Custom Tooltip
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Custom Tooltip
|
||||
|
||||
:::tip
|
||||
|
||||
There are some known timing problems when setting `Plugins Object`,
|
||||
solution is to set the `Plugins Object` on `Did Mount`.
|
||||
|
||||
:::
|
||||
|
||||
## Custom Tooltip Content
|
||||
|
||||
This sample shows how to use the tooltip callbacks to add additional content to the tooltip.
|
||||
[Chart.js Example](https://www.chartjs.org/docs/3.6.0/samples/tooltip/content.html)
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
Outputs.Plugins = {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
footer: (tooltipItems) => {
|
||||
let sum = 0;
|
||||
|
||||
tooltipItems.forEach(function (tooltipItem) {
|
||||
sum += tooltipItem.parsed.y;
|
||||
});
|
||||
return "Sum: " + sum;
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## External HTML Tooltip
|
||||
|
||||
This sample shows how to use the external tooltip functionality to generate an HTML tooltip.
|
||||
[Chart.js Example](https://www.chartjs.org/docs/3.6.0/samples/tooltip/html.html)
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
```js
|
||||
const getOrCreateTooltip = (chart) => {
|
||||
let tooltipEl = chart.canvas.parentNode.querySelector("div");
|
||||
|
||||
if (!tooltipEl) {
|
||||
tooltipEl = document.createElement("div");
|
||||
tooltipEl.style.background = "rgba(0, 0, 0, 0.7)";
|
||||
tooltipEl.style.borderRadius = "3px";
|
||||
tooltipEl.style.color = "white";
|
||||
tooltipEl.style.opacity = 1;
|
||||
tooltipEl.style.pointerEvents = "none";
|
||||
tooltipEl.style.position = "absolute";
|
||||
tooltipEl.style.transform = "translate(-50%, 0)";
|
||||
tooltipEl.style.transition = "all .1s ease";
|
||||
|
||||
const table = document.createElement("table");
|
||||
table.style.margin = "0px";
|
||||
|
||||
tooltipEl.appendChild(table);
|
||||
chart.canvas.parentNode.appendChild(tooltipEl);
|
||||
}
|
||||
|
||||
return tooltipEl;
|
||||
};
|
||||
|
||||
const externalTooltipHandler = (context) => {
|
||||
// Tooltip Element
|
||||
const { chart, tooltip } = context;
|
||||
const tooltipEl = getOrCreateTooltip(chart);
|
||||
|
||||
// Hide if no tooltip
|
||||
if (tooltip.opacity === 0) {
|
||||
tooltipEl.style.opacity = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set Text
|
||||
if (tooltip.body) {
|
||||
const titleLines = tooltip.title || [];
|
||||
const bodyLines = tooltip.body.map((b) => b.lines);
|
||||
|
||||
const tableHead = document.createElement("thead");
|
||||
|
||||
titleLines.forEach((title) => {
|
||||
const tr = document.createElement("tr");
|
||||
tr.style.borderWidth = 0;
|
||||
|
||||
const th = document.createElement("th");
|
||||
th.style.borderWidth = 0;
|
||||
const text = document.createTextNode(title);
|
||||
|
||||
th.appendChild(text);
|
||||
tr.appendChild(th);
|
||||
tableHead.appendChild(tr);
|
||||
});
|
||||
|
||||
const tableBody = document.createElement("tbody");
|
||||
bodyLines.forEach((body, i) => {
|
||||
const colors = tooltip.labelColors[i];
|
||||
|
||||
const span = document.createElement("span");
|
||||
span.style.background = colors.backgroundColor;
|
||||
span.style.borderColor = colors.borderColor;
|
||||
span.style.borderWidth = "2px";
|
||||
span.style.marginRight = "10px";
|
||||
span.style.height = "10px";
|
||||
span.style.width = "10px";
|
||||
span.style.display = "inline-block";
|
||||
|
||||
const tr = document.createElement("tr");
|
||||
tr.style.backgroundColor = "inherit";
|
||||
tr.style.borderWidth = 0;
|
||||
|
||||
const td = document.createElement("td");
|
||||
td.style.borderWidth = 0;
|
||||
|
||||
const text = document.createTextNode(body);
|
||||
|
||||
td.appendChild(span);
|
||||
td.appendChild(text);
|
||||
tr.appendChild(td);
|
||||
tableBody.appendChild(tr);
|
||||
});
|
||||
|
||||
const tableRoot = tooltipEl.querySelector("table");
|
||||
|
||||
// Remove old children
|
||||
while (tableRoot.firstChild) {
|
||||
tableRoot.firstChild.remove();
|
||||
}
|
||||
|
||||
// Add new children
|
||||
tableRoot.appendChild(tableHead);
|
||||
tableRoot.appendChild(tableBody);
|
||||
}
|
||||
|
||||
const { offsetLeft: positionX, offsetTop: positionY } = chart.canvas;
|
||||
|
||||
// Display, position, and set styles for font
|
||||
tooltipEl.style.opacity = 1;
|
||||
tooltipEl.style.left = positionX + tooltip.caretX + "px";
|
||||
tooltipEl.style.top = positionY + tooltip.caretY + "px";
|
||||
tooltipEl.style.font = tooltip.options.bodyFont.string;
|
||||
tooltipEl.style.padding =
|
||||
tooltip.options.padding + "px " + tooltip.options.padding + "px";
|
||||
};
|
||||
|
||||
Outputs.Plugins = {
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
position: "nearest",
|
||||
external: externalTooltipHandler,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Only show titles
|
||||
|
||||
For this we just change the code to only return the titles.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
```js
|
||||
const getOrCreateTooltip = (chart) => {
|
||||
let tooltipEl = chart.canvas.parentNode.querySelector("div");
|
||||
|
||||
if (!tooltipEl) {
|
||||
tooltipEl = document.createElement("div");
|
||||
tooltipEl.style.background = "rgba(0, 0, 0, 0.7)";
|
||||
tooltipEl.style.borderRadius = "3px";
|
||||
tooltipEl.style.color = "white";
|
||||
tooltipEl.style.opacity = 1;
|
||||
tooltipEl.style.pointerEvents = "none";
|
||||
tooltipEl.style.position = "absolute";
|
||||
tooltipEl.style.transform = "translate(-50%, 0)";
|
||||
tooltipEl.style.transition = "all .1s ease";
|
||||
|
||||
const table = document.createElement("table");
|
||||
table.style.margin = "0px";
|
||||
|
||||
tooltipEl.appendChild(table);
|
||||
chart.canvas.parentNode.appendChild(tooltipEl);
|
||||
}
|
||||
|
||||
return tooltipEl;
|
||||
};
|
||||
|
||||
const externalTooltipHandler = (context) => {
|
||||
// Tooltip Element
|
||||
const { chart, tooltip } = context;
|
||||
const tooltipEl = getOrCreateTooltip(chart);
|
||||
|
||||
// Hide if no tooltip
|
||||
if (tooltip.opacity === 0) {
|
||||
tooltipEl.style.opacity = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set Text
|
||||
if (tooltip.body) {
|
||||
const titleLines = tooltip.title || [];
|
||||
const bodyLines = tooltip.body.map((b) => b.lines);
|
||||
|
||||
const tableHead = document.createElement("thead");
|
||||
|
||||
titleLines.forEach((title) => {
|
||||
const tr = document.createElement("tr");
|
||||
tr.style.borderWidth = 0;
|
||||
|
||||
const th = document.createElement("th");
|
||||
th.style.borderWidth = 0;
|
||||
const text = document.createTextNode(title);
|
||||
|
||||
th.appendChild(text);
|
||||
tr.appendChild(th);
|
||||
tableHead.appendChild(tr);
|
||||
});
|
||||
|
||||
const tableRoot = tooltipEl.querySelector("table");
|
||||
|
||||
// Remove old children
|
||||
while (tableRoot.firstChild) {
|
||||
tableRoot.firstChild.remove();
|
||||
}
|
||||
|
||||
// Add new children
|
||||
tableRoot.appendChild(tableHead);
|
||||
}
|
||||
|
||||
const { offsetLeft: positionX, offsetTop: positionY } = chart.canvas;
|
||||
|
||||
// Display, position, and set styles for font
|
||||
tooltipEl.style.opacity = 1;
|
||||
tooltipEl.style.left = positionX + tooltip.caretX + "px";
|
||||
tooltipEl.style.top = positionY + tooltip.caretY + "px";
|
||||
tooltipEl.style.font = tooltip.options.bodyFont.string;
|
||||
tooltipEl.style.padding =
|
||||
tooltip.options.padding + "px " + tooltip.options.padding + "px";
|
||||
};
|
||||
|
||||
Outputs.Plugins = {
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
position: "nearest",
|
||||
external: externalTooltipHandler,
|
||||
},
|
||||
};
|
||||
```
|
||||
62
library/modules/chartjs/guides/interactions.md
Normal file
62
library/modules/chartjs/guides/interactions.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: Chart.js Interactions
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Interactions
|
||||
|
||||
This guide is based on the documentation from Chart.js, which can be found [here](https://www.chartjs.org/docs/latest/configuration/interactions.html).
|
||||
|
||||
## Converting Events to Data Values
|
||||
|
||||
A common occurrence is taking an event, such as a click, and finding the data coordinates on the chart where the event occurred. Chart.js provides helpers that make this a straightforward process.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
In this screenshot, we connect the "Click", "Data" and "Helpers" outputs to a function node to be able to process the chart data.
|
||||
|
||||
With this code in the Function node, we can start by getting the values on the X and Y axis.
|
||||
|
||||
```js
|
||||
const data = Inputs.data;
|
||||
const helpers = Inputs.helpers;
|
||||
|
||||
const canvasPosition = helpers.getRelativePosition(data, data.chart);
|
||||
|
||||
// Substitute the appropriate scale IDs
|
||||
const dataX = data.chart.scales.x.getValueForPixel(canvasPosition.x);
|
||||
const dataY = data.chart.scales.y.getValueForPixel(canvasPosition.y);
|
||||
```
|
||||
|
||||
Now with `dataX` and `dataY` we know what values the user clicked on.
|
||||
|
||||
To continue from here, you can follow [Chart.js guides](https://www.chartjs.org/docs/latest/configuration/interactions.html).
|
||||
|
||||
There are for examples [getPixelForValue](https://www.chartjs.org/docs/latest/api/classes/Scale.html#getpixelforvalue), that returns the location of the given data point.
|
||||
|
||||
### Before Event
|
||||
|
||||
Make all the connections under the "Before Event" category and helpers from the "Click Event" category,
|
||||
and this function will be triggered on any of the before events.
|
||||
|
||||
```js
|
||||
const chart = Inputs.chart;
|
||||
const args = Inputs.args;
|
||||
const helpers = Inputs.helpers;
|
||||
|
||||
const canvasPosition = helpers.getRelativePosition(args.event, chart);
|
||||
|
||||
// Substitute the appropriate scale IDs
|
||||
const dataX = chart.scales.x.getValueForPixel(canvasPosition.x);
|
||||
const dataY = chart.scales.y.getValueForPixel(canvasPosition.y);
|
||||
|
||||
console.log({
|
||||
canvasPosition,
|
||||
dataX,
|
||||
dataY,
|
||||
});
|
||||
```
|
||||
36
library/modules/chartjs/nodes/bar.md
Normal file
36
library/modules/chartjs/nodes/bar.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Bar Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Bar Chart
|
||||
|
||||
This visual node adds a bar chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/bar) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/bubble.md
Normal file
36
library/modules/chartjs/nodes/bubble.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Bubble Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Bubble Chart
|
||||
|
||||
This visual node adds a bubble chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/bubble) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/doughnut.md
Normal file
36
library/modules/chartjs/nodes/doughnut.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Doughnut Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Doughnut Chart
|
||||
|
||||
This visual node adds a doughnut chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/doughnut) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/line.md
Normal file
36
library/modules/chartjs/nodes/line.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Line Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Line Chart
|
||||
|
||||
This visual node adds a line chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/line) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/pie.md
Normal file
36
library/modules/chartjs/nodes/pie.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Pie Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Pie Chart
|
||||
|
||||
This visual node adds a pie chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/pie) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/polar-area.md
Normal file
36
library/modules/chartjs/nodes/polar-area.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Polar Area Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Polar Area Chart
|
||||
|
||||
This visual node adds a polar area chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/polar-area) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/radar.md
Normal file
36
library/modules/chartjs/nodes/radar.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Radar Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Radar Chart
|
||||
|
||||
This visual node adds a radar chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/radar) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
36
library/modules/chartjs/nodes/scatter.md
Normal file
36
library/modules/chartjs/nodes/scatter.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Scatter Chart
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Scatter Chart
|
||||
|
||||
This visual node adds a scatter chart to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
[Here](../charts/scatter) is an example how to use used the node.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_inputs.md"
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
@include "./shared/_outputs.md"
|
||||
|
||||
</div>
|
||||
95
library/modules/chartjs/nodes/shared/_inputs.md
Normal file
95
library/modules/chartjs/nodes/shared/_inputs.md
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
### General Options
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Index Axis</span> | |
|
||||
| <span className="ndl-data">Responsive</span> | Resizes the chart canvas when its parent node changes size. |
|
||||
| <span className="ndl-data">Maintain Aspect Ratio</span> | Maintain the original canvas aspect ratio (width / height) when resizing. |
|
||||
| <span className="ndl-data">Aspect Ratio</span> | Canvas aspect ratio (i.e. width / height, a value of 1 representing a square canvas). Default: 1 |
|
||||
|
||||
### Animation
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">On Data Update</span> | When false, it wont animate when you update the data object. ([Preventing Animations](https://www.chartjs.org/docs/latest/developers/updates.html#preventing-animations)) |
|
||||
|
||||
### Title
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Show Title</span> | Is the title shown? |
|
||||
| <span className="ndl-data">Text</span> | Title text to display. |
|
||||
| <span className="ndl-data">Align</span> | Alignment of the title. |
|
||||
| <span className="ndl-data">Position</span> | Position of title. |
|
||||
| <span className="ndl-data">Color</span> | Color of text. |
|
||||
|
||||
### Title Font
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Font Family</span> | The font family. |
|
||||
| <span className="ndl-data">Font Size</span> | The font size. |
|
||||
| <span className="ndl-data">Font Style</span> | The font style. |
|
||||
| <span className="ndl-data">Weight</span> | The font weight (boldness). |
|
||||
| <span className="ndl-data">Line Height</span> | The height of an individual line of text. |
|
||||
|
||||
### Tooltips
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Show Tooltips</span> | Are on-canvas tooltips enabled? |
|
||||
| <span className="ndl-data">Mode</span> | Sets which elements appear in the tooltip. |
|
||||
| <span className="ndl-data">Position</span> | The mode for positioning the tooltip. |
|
||||
| <span className="ndl-data">Background Color</span> | Background color of the tooltip. |
|
||||
| <span className="ndl-data">Body Color</span> | Color of body text. |
|
||||
| <span className="ndl-data">Spacing</span> | Spacing to add to top and bottom of each tooltip item. |
|
||||
| <span className="ndl-data">Corner Radius</span> | Radius of tooltip corner curves. |
|
||||
| <span className="ndl-data">Display Colors</span> | If true, color boxes are shown in the tooltip. |
|
||||
|
||||
### Tooltips Font
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Font Family</span> | The font family. |
|
||||
| <span className="ndl-data">Font Size</span> | The font size. |
|
||||
| <span className="ndl-data">Font Style</span> | The font style. |
|
||||
| <span className="ndl-data">Weight</span> | The font weight (boldness). |
|
||||
| <span className="ndl-data">Line Height</span> | The height of an individual line of text. |
|
||||
|
||||
### Legend Labels
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Text Color</span> | |
|
||||
| <span className="ndl-data">Text Align</span> | |
|
||||
| <span className="ndl-data">Use Point Style</span> | |
|
||||
| <span className="ndl-data">Point Style</span> | |
|
||||
|
||||
### Legend Label Font
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Font Family</span> | The font family. |
|
||||
| <span className="ndl-data">Font Size</span> | The font size. |
|
||||
| <span className="ndl-data">Font Style</span> | The font style. |
|
||||
| <span className="ndl-data">Weight</span> | The font weight (boldness). |
|
||||
| <span className="ndl-data">Line Height</span> | The height of an individual line of text. |
|
||||
|
||||
### Data Decimation
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Enabled</span> | Is decimation enabled? |
|
||||
| <span className="ndl-data">Algorithm</span> | Decimation algorithm to use. See the [more...](https://www.chartjs.org/docs/latest/configuration/decimation.html#decimation-algorithms) |
|
||||
| <span className="ndl-data">Samples</span> | If the `lttb` algorithm is used, this is the number of samples in the output dataset. Defaults to the canvas width to pick 1 sample per pixel. |
|
||||
| <span className="ndl-data">Threshold</span> | If the number of samples in the current axis range is above this value, the decimation will be triggered. Defaults to 4 times the canvas width. The number of point after decimation can be higher than the `threshold` value. |
|
||||
|
||||
### Interaction
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Intersect</span> | If true, the interaction mode only applies when the mouse position intersects an item on the chart. |
|
||||
| <span className="ndl-data">Mode</span> | Sets which elements appear in the interaction. |
|
||||
| <span className="ndl-data">Axis</span> | |
|
||||
| <span className="ndl-data">Include Invisible</span> | If true, the invisible points that are outside of the chart area will also be included when evaluating interactions. |
|
||||
27
library/modules/chartjs/nodes/shared/_outputs.md
Normal file
27
library/modules/chartjs/nodes/shared/_outputs.md
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
### Click Event
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Data</span> | |
|
||||
|
||||
| Signal | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Click</span> | |
|
||||
|
||||
### Before Event
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Chart</span> | |
|
||||
| <span className="ndl-data">Args</span> | |
|
||||
|
||||
| Signal | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Before</span> | |
|
||||
|
||||
### Debug
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Chart.js Options</span> | |
|
||||
28
library/modules/chartjs/release-notes.md
Normal file
28
library/modules/chartjs/release-notes.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Release Notes
|
||||
hide_title: true
|
||||
---
|
||||
# Release Notes
|
||||
|
||||
Version 1.4.3 [2023-06-08]
|
||||
* Add Animation `On Data Update` input on Chart nodes, provides the ability to prevent animations when updating the chart in real time. ([Preventing Animations](https://www.chartjs.org/docs/latest/developers/updates.html#preventing-animations))
|
||||
* Add Animations object to all nodes, similar to Scales, making it possible to create nicer animations. ([Chart.js Animations](https://www.chartjs.org/docs/latest/configuration/animations.html#animations))
|
||||
|
||||
Version 1.4.2 [2023-05-16]
|
||||
* Add Chart node, custom node allowing a full Chart.js config to create the chart.
|
||||
|
||||
Version 1.4.1 [2023-05-04]
|
||||
* Add Helpers output to all nodes, allowing for interactions.
|
||||
|
||||
Version 1.4.0 [2023-04-06]
|
||||
* Change "Maintain Aspect Ratio" default from `true` to `false`
|
||||
* Fix responsiveness
|
||||
* Fix default inputs not applied
|
||||
* Fix issue when data is updated before Did Mount
|
||||
* Add a link to docs on each node
|
||||
|
||||
Version 1.3.0 [2023-03-31]
|
||||
* Support for Before Event and Click Event
|
||||
* Support for Data Decimation plugin
|
||||
* Support for Interaction
|
||||
* Only show default chart data when there is no connection to data
|
||||
38
library/modules/custom-html/README.md
Normal file
38
library/modules/custom-html/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Custom HTML
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Custom HTML
|
||||
|
||||
This node allows you to add your own custom HTML markup to your visual tree. Common use cases include embeds or inline SVG's.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You can pass dynamic values to your markup by using template strings. `{{ FillColor }}` will create an input port named `FillColor`.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Security notice
|
||||
|
||||
This node also allows you to add script tags to your app. For security reasons all script tags are deactivated, but if you need to run a script (required for some embeds) you can turn off that fail safe. <strong>Please note that passing user input to your template string variables can be a security risk for you and your users, leaving you vulnerable to [XSS Attacks](https://en.wikipedia.org/wiki/Cross-site_scripting).</strong>
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">HTML</span> | Your custom markup that will be rendered in the visual tree. |
|
||||
| <span className="ndl-data">Run inline JavaScript</span> | Running scripts with user input can be dangerous. To provide an extra layer of security JavaScript in the custom HTML is prevented from running. Turn this on if your embed require scripts or if you are an advanced user with knowledge of [XSS Attacks](https://en.wikipedia.org/wiki/Cross-site_scripting) |
|
||||
| <span className="ndl-data">Custom Variables</span> | Any variable in a template string will become an input. Only one variable per template string allowed |
|
||||
25
library/modules/data-context/README.md
Normal file
25
library/modules/data-context/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: Data Context Module
|
||||
hide_title: true
|
||||
---
|
||||
# Data Context Module
|
||||
|
||||
This module allows you to work with scoped data objects.
|
||||
|
||||
This module is designed to make it easier to work with data objects in complex data scenarios,
|
||||
where the [Parent Component Object nodes](https://docs.noodl.net/#/nodes/component-utilities/parent-component-object/) will not be enough or will make it harder to maintain.
|
||||
|
||||
## How to use it?
|
||||
|
||||
This module is adding 4 new nodes.
|
||||
|
||||
- Context
|
||||
- Get State (to get the data from the context, you have to call the Fetch method)
|
||||
- Set State
|
||||
- Subscriber (this is a reactive object so when something changes on the context this one get the new data automatically)
|
||||
|
||||
The Context node is the most important node,
|
||||
where you design the data object you want to use and share it with all the child components.
|
||||
When you have a Context you can use either the Get State or Subscriber nodes (which work similarly to the Variable nodes) to get the current data, it will then find the closest Context node upwards in the graph to get the data.
|
||||
|
||||
[Source Code](https://github.com/noodlapp/modules/tree/main/modules/data-context)
|
||||
28
library/modules/font-awesome-brands/README.md
Normal file
28
library/modules/font-awesome-brands/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Font Awesome Brands
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Font Awesome Brands
|
||||
|
||||
[](https://github.com/noodlapp/modules/tree/main/modules/font-awesome-brands)
|
||||
|
||||
This module contains all the Font Awesome brand icons. Add it to your project and you will have access to it in all core nodes that support icons. Most notably the [Icon](/nodes/basic-elements/icon) node.
|
||||
|
||||
You can find a list of all the icons here: https://fontawesome.com/search?o=r&f=brands
|
||||
|
||||
<div className="ndl-image-with-background xl">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Using this via code, works like this:
|
||||
|
||||
```js
|
||||
Outputs.iconObject = {
|
||||
class: "fa-brands",
|
||||
code: Inputs.iconCode,
|
||||
codeAsClass: true
|
||||
}
|
||||
```
|
||||
28
library/modules/font-awesome-solid/README.md
Normal file
28
library/modules/font-awesome-solid/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Font Awesome Solid
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Font Awesome Solid
|
||||
|
||||
[](https://github.com/noodlapp/modules/tree/main/modules/font-awesome-solid)
|
||||
|
||||
This module contains all the Font Awesome brand icons. Add it to your project and you will have access to it in all core nodes that support icons. Most notably the [Icon](/nodes/basic-elements/icon) node.
|
||||
|
||||
You can find a list of all the icons here: https://fontawesome.com/search?o=r&m=free&s=solid&f=solid%2Cclassic
|
||||
|
||||
<div className="ndl-image-with-background xl">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Using this via code, works like this:
|
||||
|
||||
```js
|
||||
Outputs.iconObject = {
|
||||
class: "fa-solid",
|
||||
code: Inputs.iconCode,
|
||||
codeAsClass: true
|
||||
}
|
||||
```
|
||||
18
library/modules/geospatial-analysis/README.md
Normal file
18
library/modules/geospatial-analysis/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Geospatial Analysis
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Geospatial Analysis
|
||||
|
||||
[](https://github.com/noodlapp/modules/tree/main/modules/geospatial-analysis)
|
||||
|
||||
This module allows you to use [Turf.js](https://turfjs.org/) geospatial analysis library to make calculations on coordinates.
|
||||
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Geospatial Turf API
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Turf.js API
|
||||
|
||||
Returns the Turf.js API object, allowing to use other Turf.js functions that doesn't have nodes yet.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| -------------------------------------- | ------------------------------------------------------------------ |
|
||||
| <span className="ndl-data">Turf</span> | The Turf.js object, making it possible to call any Turf.js method. |
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: Geospatial Area
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Geospatial Area
|
||||
|
||||
Takes an array of coordinates and returns their area in different formats.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | --------------- |
|
||||
| <span className="ndl-data">Coordinates</span> | GeoJSON feature |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------------- | ----------- |
|
||||
| <span className="ndl-data">Square Meters</span> | |
|
||||
| <span className="ndl-data">Square Hectares</span> | |
|
||||
| <span className="ndl-data">Square Km</span> | |
|
||||
| <span className="ndl-data">Acres</span> | |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ------------------------------------ |
|
||||
| <span className="ndl-signal">Changed</span> | Occurs when the outputs are updated. |
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: Geospatial Center Of Mass
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Geospatial Center Of Mass
|
||||
|
||||
Takes an array of coordinates and returns its center of mass using this formula: Centroid of Polygon.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | --------------- |
|
||||
| <span className="ndl-data">Coordinates</span> | GeoJSON feature |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------------ | ----------- |
|
||||
| <span className="ndl-data">Center Of Mass</span> | |
|
||||
| <span className="ndl-data">Centroid</span> | |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ------------------------------------ |
|
||||
| <span className="ndl-signal">Changed</span> | Occurs when the outputs are updated. |
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Geospatial Center
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Geospatial Center
|
||||
|
||||
Takes a GeoJSON feature and returns the absolute center point.
|
||||
|
||||
<##head##>
|
||||
|
||||
Here is an example of how to use it.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This is what is inside the "Get GeoJSON Feature" funciton node:
|
||||
|
||||
```js
|
||||
Outputs.Feature = {
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: [
|
||||
[102.0, 0.0],
|
||||
[103.0, 1.0],
|
||||
[104.0, 0.0],
|
||||
[105.0, 1.0],
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
This is what is inside the "Extract Coordinate" function node:
|
||||
|
||||
```js
|
||||
const feature = Inputs.Feature;
|
||||
const coordinate = feature.geometry.coordinates;
|
||||
Outputs.Text = `${coordinate[0]}, ${coordinate[1]}`;
|
||||
```
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | -------------------- |
|
||||
| <span className="ndl-data">Coordinates</span> | The GeoJSON feature. |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------- | ------------------------------------------- |
|
||||
| <span className="ndl-data">Center</span> | A GeoJSON feature with the center position. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ----------------------------------------- |
|
||||
| <span className="ndl-signal">Changed</span> | Occurs when the Center output is updated. |
|
||||
|
||||
</div>
|
||||
12
library/modules/geospatial-analysis/release-notes.md
Normal file
12
library/modules/geospatial-analysis/release-notes.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Release Notes
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
Version 1.0 [2023-05-31]
|
||||
* Added Geospatial Area node, calculate the area of a polygon
|
||||
* Added Geospatial Center node, calculate the center from a list of coordinates
|
||||
* Added Geospatial Center Of Mass, calculate the center of mass from a list of coordinates
|
||||
* Added Turf.js API node, to get direct access to Turf.js library
|
||||
15
library/modules/google-analytics/README.md
Normal file
15
library/modules/google-analytics/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Google Analytics Module
|
||||
hide_title: true
|
||||
---
|
||||
# Google Analytics Module
|
||||
|
||||
This module allows you to track user interactions with your Noodl app, using Google Analytics.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Follow the [Setting up Google Analytics](/library/modules/google-analytics/guides/setting-up-google-analytics/) guide or jump straight to the [node documentation](/library/modules/google-analytics/nodes/google-analytics-root/).
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
title: Setting up Google Analytics
|
||||
hide_title: true
|
||||
---
|
||||
# Setting up Google Analytics
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will show you how to add basic tracking with Google Analytics. After this guide you will be able to collect data on how many users that see your app, some of their behaviors and how they move through your application.
|
||||
|
||||
## Overview
|
||||
|
||||
We will go through the following topics:
|
||||
|
||||
- Beginners guide to Google Analytics
|
||||
- Set up Google Analytics
|
||||
- Set up the Noodl Module
|
||||
- Allow tracking
|
||||
- Next steps
|
||||
|
||||
## Beginners guide to Google Analytics
|
||||
|
||||
If you're already familiar with _impressions_ and _page views_ and just want to set up your tracking, feel free to jump along to [the next section](/library/modules/google-analytics/guides/setting-up-google-analytics).
|
||||
|
||||
If tracking in Google Analytics is new to you, keep reading for a quick crash course.
|
||||
|
||||
The most common things to track with Google Analytics are _visitor count_ and _page views_. These are coincidentally two of the metrics that Google Analytics track by default without you having to take any other action than just starting the tracking script in your app.
|
||||
|
||||
The user data lets you know how many people visit your app. It also include a lot of helpful information on the visiting demographics and what technologies they use to access your app. What is the average length of the users visit? What part of the world are they from? What languages do they speak? Are they primarily desktop or mobile users? All of this, and much more can be answered by reading the collected data.
|
||||
|
||||
While the demographic data is good for tracking general behavior, page views can be used to see details on specific interaction. What are the most visited pages? On what page do your users spend the most time? Are they reaching that last step of the form, or do they drop off earlier? Where do they drop off?
|
||||
|
||||
It is well worth learning more about [finding your way around Google Analytics](https://support.google.com/analytics/answer/9367631), and especially the contents and capabilities of [GA4 Reports](https://support.google.com/analytics/answer/9212670), as they are the backbone of Google Analytics and an instrumental tool in shaping the success of your app.
|
||||
|
||||
## Set up Google Analytics
|
||||
|
||||
To be able to use Google Analytics you need to have:
|
||||
|
||||
1. an Analytics account with a _Google Analytics 4 (GA4)_ **Property**
|
||||
2. with a _Web_ **Data Stream**
|
||||
3. pointing to the deployed app URL (or a placeholder one, like `example.com`)
|
||||
4. with _Enhanced Measurement_ **disabled**
|
||||
|
||||
If this list is crystal clear, you already know how to do this and can skip along to the [next section](/library/modules/google-analytics/guides/setting-up-google-analytics#setting-up-the-noodl-module) of this guide. Otherwise - Google has some handy documentation:
|
||||
|
||||
### Setting up your Google account
|
||||
|
||||
If you don't already have a Google Analytics account you need to [create one](https://support.google.com/analytics/answer/9304153#account&zippy=%2Cweb).
|
||||
|
||||
After that we need to [set up a **Property**](https://support.google.com/analytics/answer/9304153#property&zippy=%2Cweb), which is Google terminology for "a collection of **Data Streams** that you want to track".
|
||||
|
||||
:::caution
|
||||
Make sure that you are using _Google Analytics 4_ and **NOT** _Universal Analytics_, as this Module only supports _GA4_.
|
||||
:::
|
||||
|
||||
So what is a **Data Stream**? Simply put, it's a connection that will stream data from your app to Google Analytics. You can have multiple **Data Streams** in your **Property**, but in most cases you will only need one.
|
||||
|
||||
Let's set up our first **Data Stream**. As Noodl outputs Web Apps, we will need to select the [**Web** option](https://support.google.com/analytics/answer/9304153#stream&zippy=%2Cweb). When asked for the URL of the primary website, this needs to be the URL for your app [when it's deployed](/docs/guides/deploy/deploying-an-app-on-sandbox). `example.com` works for testing purposes as well.
|
||||
|
||||
!> Make sure to disable [_Enhanced Measurement_](https://support.google.com/analytics/answer/9216061), as this might send double page views.
|
||||
|
||||
## Seting up the Noodl Module
|
||||
|
||||
In the Google Analytics admin panel, go to your newly created **Data Stream** settings and copy the [Measurement ID](https://support.google.com/analytics/answer/9539598#find-G-ID). You will be needing this later.
|
||||
|
||||
Open up your Noodl Project and locate your **Root Component**. It's easy to identify, since it has a small house icon in front of it and is called `App` (if you haven't renamed it).
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Create a `Google Analytics Root` node and place it in the visual tree, as high up as you can, then paste the **Measurement ID** that you copied earlier into the `Measurement ID` input in the **Property Panel**.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Allow tracking
|
||||
|
||||
To be able to track anything we need to check the <span className="ndl-data">Allow Tracking</span> input. This can be done by simply checking the input in the **Property Panel**.
|
||||
|
||||
In most cases it is recommended that you notify the user of your tracking and only track after having been given the users consent.
|
||||
|
||||
To do this we can use a **Button** node and a **Switch** node. Connect the **Switch** nodes <span className="ndl-data">Current State</span> output to the <span className="ndl-data">Allow Tracking</span> input on the **Google Analytics Root** node. Use the **Button** nodes <span className="ndl-signal">Click</span> output to flip the **Switch** to `On`.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This will initiate the tracking when the user clicks the button.
|
||||
|
||||
To make sure that everything is correct, we can use the <span className="ndl-signal">Starting Tracking</span> output on the **Google Analytics Root** node. This will send a <span className="ndl-signal">signal</span> when the Google Analytics tracking code has been activated. This <span className="ndl-signal">signal</span> can also be used to hide the button after consent has been given. Simply use the same "flip the switch" trick we did above, but setting the **Switch** initial state to `On` (letting the **Button** flip the switch to `Off`) and connecting the <span className="ndl-data">Current State</span> output to the <span className="ndl-data">Mounted</span> input on the **Button**.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Next steps
|
||||
|
||||
Congratulations! The Google Analytics integration is complete! You should now be able to see stored and real time data in your [Google Analytics Reports](https://support.google.com/analytics/answer/9212670) view.
|
||||
|
||||
Google Analytics is very powerful and has a lot of features, and it's highly recommended to learn more about it if you're just starting your Analytics journey. Sadly, we've reached the end of this guide, but there are many resources where you can learn more about GA4. Google themselves provide free online courses in the [Analytics Academy](https://analytics.google.com/analytics/academy/) that are well worth checking out if you want to learn all the ins and outs of both the tool and tracking strategies. Less in-depth information is also available - one Google (or YouTube) search away.
|
||||
|
||||
When you feel it's time to go further on your tracking journey in Noodl, check out our guide on [tracking custom events](/library/modules/google-analytics/guides/tracking-custom-events/).
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: Tracking Custom Events in Google Analytics
|
||||
hide_title: true
|
||||
---
|
||||
# Tracking custom events in Google Analytics
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will take you through the process of setting up and tracking custom events in Google Analytics. It is recommended that you take a look through the [setup guide](/library/modules/google-analytics/guides/setting-up-google-analytics) before reading this one.
|
||||
|
||||
## Overview
|
||||
|
||||
We will learn about the following things:
|
||||
|
||||
- Sending static data
|
||||
- Sending dynamic data based on user input
|
||||
|
||||
## Sending static data
|
||||
|
||||
To send custom events we use the **Send Google Analytics Data** node.
|
||||
|
||||
The **Send Google Analytics Data** node is built on top of Google's own `gtag` function, meaning that all _Google Analytics 4_ documentation you see that uses `gtag` can be directly copied and pasted into the node.
|
||||
|
||||
In Google's own documentation on [sending events](https://support.google.com/analytics/answer/11147304) we can find the following code in the section named "Send an event":
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```html
|
||||
<script>
|
||||
gtag("event", "publish", {
|
||||
role: "Writer",
|
||||
})
|
||||
</script>
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
We can copy the data passed to the gtag function and paste it directly into the <span className="ndl-data">Gtag Tracking Data</span> input in the **Property Panel** for the **Send Google Analytics Data** node, like so:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We can now submit the data to Google by sending a signal to the nodes <span className="ndl-signal">Do</span> input.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We have now successfully tracked our first custom event!
|
||||
|
||||
## Sending dynamic data based on user input
|
||||
|
||||
In some cases we want to provide more in depth data that might be dependent on specific user input. In this case we can use the **String Format** node.
|
||||
|
||||
Let's build a small app that tracks the user's favourite type of noodle dish. We'll use a **Text Input** and a **Button** to build a tiny form.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We are now ready to add the tracking.
|
||||
|
||||
Create a **String Format** node and open up it's **Property Panel**. In the <span className="ndl-data">Format</span> input we can now write our custom event.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
"event", "submitted_dish", {"dish": "{userDish}"}
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
The `{userDish}` part of this code will create an input named <span className="ndl-data">userDish</span> on this node. We can now send the <span className="ndl-data">Text</span> from **Text Input** to the <span className="ndl-data">userDish</span> input on **String Format**.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
:::caution
|
||||
It is **very important** that the `{userDish}` is in quotation marks if the value is a <span className="ndl-data">string</span>, otherwise the tracking will fail. <span className="ndl-data">Numbers</span> can be unquoted.
|
||||
:::
|
||||
|
||||
Now we need to send this data to Google. Create a **Send Google Analytics Data** node, and connect the **String Format** <span className="ndl-data">Formatted</span> output to the **Send Google Analytics Data** <span className="ndl-data">Gtag Tracking Data</span> input, and the **Button** <span className="ndl-signal">Click</span> output to the **Send Google Analytics Data** <span className="ndl-signal">Do</span> input. We will also connect the <span className="ndl-signal">Data Sent</span> output from **Send Google Analytics Data** to the **Text Input** <span className="ndl-signal">Clear</span>, to visually indicate that the data has been sent.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We have now successfully tracked the users favourite noodle dish! Hop on into the Google Analytics Reports view and use this knowledge responsibly.
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: Google Analytics Root
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Google Analytics Root
|
||||
|
||||
This node loads Google Analytics in your Noodl app. It _must_ be placed in your **Root Component** for the tracking to work properly. You can find your **Root Component** in the **Components** list in the sidebar, having a house icon beside it.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This node uses [Google Analytics 4](https://developers.google.com/analytics/devguides/collection/ga4) and requires a [Google Analytics Measurement ID](https://support.google.com/analytics/answer/9539598#find-G-ID).
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Measurement ID</span> | The [Google Analytics Measurement ID](https://support.google.com/analytics/answer/9539598#find-G-ID) to send the data to. |
|
||||
| <span className="ndl-data">Allow Tracking</span> | Sets if tracking should be allowed. For GDPR reasons this is disabled by default. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Signal | Description |
|
||||
| ----------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Starting Tracking</span> | Sends a signal after the tracking code is activated, before it's initialised in the app. |
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Send Google Analytics Data
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Send Google Analytics Data
|
||||
|
||||
This node is used to send custom data to Google Analytics. It works similarily to the [gtag](https://support.google.com/analytics/answer/11147304) function provided by Google.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| <span className="ndl-data">Gtag Tracking Data</span> | The data that should be sent to Google Analytics. <br/><br/>For the code `gtag("event", "search", {"term": "Noodl"})` you would send `"event", "search", {"term": "Noodl"}` to this input. |
|
||||
|
||||
| Signal | Description |
|
||||
| -------------------------------------- | ------------------------------------------------------------------ |
|
||||
| <span className="ndl-signal">Do</span> | Send a signal to this input to track the data in Google Analytics. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Signal | Description |
|
||||
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Data Sent</span> | Sends a signal when the data has been sent to Google Analytics. Useful for clearing user inputs after submission. |
|
||||
10
library/modules/google-analytics/release-notes.md
Normal file
10
library/modules/google-analytics/release-notes.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Release Notes
|
||||
hide_title: true
|
||||
---
|
||||
# Release Notes
|
||||
|
||||
Version 1.0 [2022-01-14]
|
||||
|
||||
- Support for basic tracking and late initialisation with the `Google Analytics Root` node.
|
||||
- Support for custom event tracking with the `Send Google Analytics Data` node.
|
||||
12
library/modules/graphql/README.md
Normal file
12
library/modules/graphql/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Graph QL Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# GraphQL Module
|
||||
|
||||
This module enables you to use the GraphQL node which makes it quick and easy to connect to services using [GraphQL](https://graphql.org/).
|
||||
|
||||
After you add the module to your project you will have access to the **GraphQL Query** node. Find details in the [**GraphQL Query**](/library/modules/graphql/graphql-node) reference docs.
|
||||
|
||||

|
||||
39
library/modules/graphql/graphql-node.md
Normal file
39
library/modules/graphql/graphql-node.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: GraphQL Query
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
# GraphQL Query
|
||||
|
||||
This node enables you to connect to GraphQL based API:s in a quick and easy way.
|
||||
|
||||

|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
**Query**
|
||||
Input your GraphQL query in this field. Example: `{ hero { name } }`
|
||||
|
||||
**Endpoint**
|
||||
A URL for the service that you are using.
|
||||
|
||||
**Results**
|
||||
Click the plus button to define the name of the results array you want to receive from your query. If your query was `{ hero { name } }`, you would give your result the name `hero`.
|
||||
|
||||
**Request Headers**
|
||||
Use this field to add any headers the GraphQL service requires.
|
||||
Example:
|
||||
```javascript
|
||||
headers({ 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer f60e2ea4dcd07fbcdaef8c8cd8418e', })
|
||||
```
|
||||
|
||||
**Fetch**
|
||||
Send a signal to this input to execute your GraphQL query.
|
||||
|
||||
## Outputs
|
||||
|
||||
**Results**
|
||||
This is a list of the results that were defined in the inputs. Each result will have the name that was defined in the inputs section and it will be an array of items.
|
||||
17
library/modules/gsheets/README.md
Normal file
17
library/modules/gsheets/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Google Sheets Module
|
||||
hide_title: true
|
||||
---
|
||||
# Google Sheets Module
|
||||
|
||||
The Google Sheets Module makes it easy to read data from publich Google Sheets. Use it for example to use Google Sheets as a CMS system or a read-only data repository. There are three nodes included, [Query Sheet](/library/modules/gsheets/node-docs/query-sheet), [Query Sheet Aggregate](/library/modules/gsheets/node-docs/query-sheet-aggregate) and [Sheet Row](/library/modules/gsheets/node-docs/sheet-row).
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The module will interpret a Google Sheet as a giant table meaning the first row encountered in the sheet will decide the names of the columns, and then each row will contains values for those columns in its cells. Empty rows and columns will be skipped.
|
||||
|
||||
?> Note that the Google Sheet need to be made publicly available for the module to be able to access it. Also, the module is read-only, i.e. you cannot write data to the Google Sheet.
|
||||
539
library/modules/gsheets/guides/filtering/README.mdx
Normal file
539
library/modules/gsheets/guides/filtering/README.mdx
Normal file
@@ -0,0 +1,539 @@
|
||||
---
|
||||
title: Google Sheets Filtering
|
||||
hide_title: true
|
||||
---
|
||||
# Google Sheets Filtering
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will look at how we can apply filters to our Google Sheets data and use that in our example app.
|
||||
|
||||
## Overview
|
||||
|
||||
If you haven't already followed the previous guides for the Google Sheets Module, it's recommended to do that before starting this guide. You can find them [part 1 here](library/modules/gsheets/guides/setting-up/ and [part 2 here](/library/modules/gsheets/guides/park-details).
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We will go though the following steps:
|
||||
|
||||
- Creating a visual filter component.
|
||||
- Using the Query Sheet Aggregate node to pull out specific data from different columns in the Google Sheet and then ause that data to populate a Dropdown node and Slider that will be used for filtering.
|
||||
- Creating filters on the Query Sheet node.
|
||||
|
||||
## Creating the visual Filters component and adding it to the App component
|
||||
|
||||
Let's first create a new visual component that we will call Filters.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
To begin with we will style the Group node in the Filters component like this:
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We will soon get back to building out this component, but before we do that, let's add some functionality and visuals in the App component so that we can bring up our Filter component. The first thing we will do is to add a Button. Let's call it Filter Button.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then let's style the button. We will remove the label and use an icon for the button just like in the images below. It's important that the Button's Position property is set to Absolute. That way we get it to float on top of our Park Details view.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now that we have a button, let's add an area for our Filters component. Let's add a Group like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This Group has a bit of styling, and again it's important that the Position is set to Absolute so that it will be on top of our Park Details. Here's the actual styling for the Group.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's add our Filters component as a child to the Group. The visual node tree in the App component should now look like the first image below, and your preview should look something like the second image.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Hiding and Showing the Filters component
|
||||
|
||||
We don't want the Filters component to always be visible, it should only show when you click the Filter Button, and then if you click the Filter Button again, it should hide. We can easily add this functionality by using a Switch node, and hook it up like below:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now, when you click on the Filter Button you should alternately hide and show the Filters component.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Finishing the visuals for the Filters component
|
||||
|
||||
Let's select the Filters component again and finish building the visuals. The idea is that we should be able to filter the list of national parks based on which state they are in and/or what size they have. A Dropdown node would be a good pick for a UI element to select a state from, and to choose a size, a Slider node would be good to use. Add nodes to the Filters component so that you have a visual tree that looks like the image below. We will go through each node and it's properties next.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Dropdown node that we will use to select which state to filter on has been styled as below:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Next we have a Group node that holds two text nodes. The Group has been named Slider Info and it has the following styling:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The two text nodes that follow have slightly different styling from each other. The first one is a Label for the Slider and it has the following styling:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The second Text node that will hold the Current Slider Value looks like this:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Lastly we have the Slider node where we have only changed the padding a bit:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Using Query Sheet Aggregate nodes to set the min and max value of the Slider
|
||||
|
||||
The Slider component will be used to set a number that we want to be between the smallest sized national park and the largest sized national park. In our Google Sheet we have a column for size so it would be cool if we could figure what the smallest and largest number is in this column. This is where the [Query Sheet Aggregate](/library/modules/gsheets/node-docs/query-sheet-aggregate) node comes in. This node is used to do aggregate data queries on a column from a public Google Sheet which is exactly what we are after here.
|
||||
|
||||
Let's first add a Query Sheet Aggregate node to our Filters component, and fill in the following properties:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
As you can see we need to tell the node which Google Sheet document it should look at (Document Id: 1gjttBIT4bHGFS8ynF31DoYw143ZY3UAiwopAW0N97KQ) and which sheet in that document we are interested in. Once the node has that information it will present a list of all the columns that the specific sheet has. Here we want to pick the Size (km2) column, and then we can choose how we want to aggregate the data of that column. We want to set up a Slider with a minimum and maximum value, so let's select Max to get the maximum value of the Size (km2) column.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then we connect it to the Slider like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now we need another Query Sheet Aggregate node to get the minimum value so let's add one and set it's properties as follows, and also hook it up as in the second image:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now the Slider has it's min and max value set, so let's now make sure that we show the current value of the slider in our Current Slider Value Text node. It would also be nice to show that the number is in km<sup>2</sup> so we will add a String Format node and set it up like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then let's connect everything like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The reason we hook up the result from the Query Sheet Aggregate - Min Size, is so that we show the initial slider value when we first open up the Filters component. The Value output from the Slider only updates as we interact with the Slider so the initial value needs to be set from the Query Sheet Aggregate - Min Size.
|
||||
|
||||
## Getting a list of all states
|
||||
|
||||
Now that we know how to use the Query Sheet Aggregate node, let's use it again, to get a list of all states that are in our Google Sheet for US national parks. This time we will set the Aggregare property to unique which means the node will return an array of all the unique values from the states column.
|
||||
|
||||
?> Note that some parks span two states, e.g. the Great Smoky Mountains are in both North Carolina and Tennessee. We have chosen to treat North Carolina, Tennessee as it's own option in the states list. A different solution would be to have two entries for Great Smoky Mountains, one for each state it's in.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's connect it to our Dropdown node, and then click on the Dropdown list in the preview.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This looks pretty good, but there is one problem. There is no option for selecting All states which is the initial state of our list. To solve this, we need to add another option to the array of states.
|
||||
|
||||
## Adding All option to states Dropdown
|
||||
|
||||
The result we get from the Query Sheet Aggregate - States is an array of items, so let's create a new Array and call it AllStates and then connect the result from Query Sheet Aggregate - States to the Items input of the Array:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Next we want to use a Create New Object node to create a new object that we can then insert into the Array. Set up the Create New Object node like below and then we connect it like in the second image.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now that we have a new Object, we want to insert it into our Array and we do that with an Insert Object Into Array node. Connect everything like below:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Our AllStates Array contains one extra option, the All option. Before we connect it to our Dropdown, let's make sure that the Array is sorted alphabetically, so we will connect an Array Filter node like in the image below. Here it's important that we use the Done signal from the Insert Object Into Array node, to tell the Array Filter to do the sorting, as that ensures that the All option is in the Array before we do the sorting.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Array Filter node should sort on the Value property of the items in the array, and we can do that by setting it up like this:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We could now make a connection from the Array Filter to the Dropdown, but as you can see the Filters component is getting quite big in terms of nodes.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's turn the selected nodes below into it's own Logic Component.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Creating Add All Option component
|
||||
|
||||
From the Component Actions button, select Logic Component and name it Add All Option.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then from the Filters node, cut out the marked nodes and paste them into the Add All Option component (use standard keyboard shortcuts for cutting and pasting). It should now look like below.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's add a port to the Component Inputs node that we call Items:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We also want to send out the sorted array, so let's add a port on the Component Outputs node called Sorted Items.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now we just make the following connections.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Back in the Filters component let's add out newly create Add All Options node, and hook it up like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now we have a nice Dropdown with our All option as well.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
Only problem is there is no initial value set in the Dropdown.
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We can easily fix that but adding a String node and giving it the value "A" and then connecting it like the image below:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Adding filters.
|
||||
|
||||
All of our visuals are now set up. All that is missing are the actual filters. Let's work on those now.
|
||||
|
||||
First let's add a new Logic Component that we call State and Size Filter.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Add two ports to the Component Inputs node called Selected State and Size. You can also delete the Component Outputs node, we won't need that.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Jump back to the Filters component and add the State and Size Filter component and hook it up like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now, we head back to the State and Size Filter component. Let's first make a filter for Size. We will add a Query Sheet node, and set it up like this.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Query Sheet node has a very nice visual filter builder so click here to add a filter:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then let's build out our filter using the visual builder. The following images show you each step. T
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
In this final step it's important to change the Value to Input, and then you can change the MyInput to a better name, like Size for instance.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We are going to add one more Query Sheet node, and this one we will call Query Sheet State and Size Filter. Then add two filters to it so the final properties for it looks like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Next, we want to take the output from our Query Sheet nodes and hook them up to the Array node with the id Parks. If you remember from the previous guides, we are using this Array to feed the Repeater node that creates our list. If the Array is updated or changed, the Repeater node will automatically rerender, so everytime we get a new result from our filter nodes the list will update.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
So why did we create two Query Sheet nodes with two different filters. It's so that we can handle the case when we choose All as the option in the Dropdown list. All is not a state that exists in our sheet, so the filter that is looking at both state and size will fail everytime we feed A into it. So to handle this we will use an expression in combination with a condition node to check if we are looking at all states, in which case we will just filter on size, or if we have selected a specific state, then we can filter on both state and size. The images below first show the expression in the Expression node, and the second image shows how everything should be connected.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Summary
|
||||
|
||||
In this guide we added filters to our National Parks and used the Query Sheets Aggregate nodes. Hope you enjoyed it, and you can import the final project by clicking the "Import" button below and follow the instructions.
|
||||
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl'
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
<img
|
||||
src={useBaseUrl(
|
||||
'/modues/gsheets/guides/filtering/filter-final-preview.gif'
|
||||
)}
|
||||
className="ndl-image small"
|
||||
></img>
|
||||
<ImportButton
|
||||
zip="gsheets-part3-1.zip"
|
||||
name="Google Sheets National Parks"
|
||||
thumb="filter-view.png"
|
||||
/>
|
||||
</div>
|
||||
217
library/modules/gsheets/guides/park-details/README.mdx
Normal file
217
library/modules/gsheets/guides/park-details/README.mdx
Normal file
@@ -0,0 +1,217 @@
|
||||
---
|
||||
title: Park Details View
|
||||
hide_title: true
|
||||
---
|
||||
# Park Details View
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will continue to explore how we can build front ends to data from Google Sheets.
|
||||
|
||||
## Overview
|
||||
|
||||
If you haven't already looked at the guide for setting up the Google Sheets Module, it's recommended to do that before starting this guide. You can find it [here](/library/modules/gsheets/guides/setting-up).
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We will go though the following steps:
|
||||
|
||||
- Using the Sheet Row node.
|
||||
- Building a simple details view for data from a Google Sheet
|
||||
|
||||
## Creating the Park Details component
|
||||
|
||||
First let's create a new visual component that we will call Park Details.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then, build out the following visual tree and then we will look at the properties for each node.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
First the properties for the top group, and the only thing that is different from the defaults is the white background:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Next we have the Image node which is setup like this:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Group that we have called Text Content, only has some padding set:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We will be displaying the park name in the Text node that we call just Park Name, and the properties for that node are as follows:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
There is another group in our tree, the Horizontal Group, that we use to lay out some of the other information, and the properties for this group are:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
All three of the Text nodes that are inside of the Horizontal Group have the same styling which is the default styling of a Text node so there is no need to change any properties for these nodes.
|
||||
|
||||
Finally the Text node that we have named Description has the following styling:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Adding the Park Details to the App component
|
||||
|
||||
Now that we have built out and styled the visuals for our Park Details, let's add them to our App component. In the App component we will first add another group that we can call Details Container and then we add the Park Details as a child to that Group. It should look like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You should also see something like this in the preview window:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This is great, but it would be even nicer with some actual content!
|
||||
|
||||
## Using the Sheet Row node to get the correct details data
|
||||
|
||||
To get the correct content in the Park Details component, we will again use a [Sheet Row](/library/modules/gsheets/node-docs/sheet-row) node, so let's place it next to our visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We need to tell the Sheet Row node which row we want to look at, and if you remember from the previous [guide](/library/modules/gsheets/guides/setting-up/), we already have a Variable named SelectedRowId. We set this everytime we click on an item in the list. Below you can see where in the List Item component the Variable is being set.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Since Variables are global we can use that same Variable in our Park Details component and connect it to the Row Id input of the Sheet Row node.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now we can start to connect all the outputs from the Sheet Row node to our visual tree. Go ahead and make the following connections first, and then we will handle the remaining two.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You still don't see anything in the preview window, unless you go ahead and click on an item in the list. In the image below I clicked on the Arches park.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
As you can see we haven't filled in the size information or the date for when the park was established so let's tackle that now.
|
||||
|
||||
The size that we are getting out from the Sheet Row is in km<sup>2</sup>, so it would be nice to add that at the end of the number. To do that we will use a String Format node, with the following set up, and then connected like in the second image.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Established date that we get from the Sheet Row is a Date type and it looks a bit strange if we connect it directly to our text node, so let's put a [Date To String](/nodes/utilities/date-to-string) node in between. After it's connected it will look like the image below.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The last thing we will do in this guide is to make sure we set the SelectedRowId Variable to the first item in the list. We can do that in the App component like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now everytime we reload the first item in the list will always be selected and we will always show something in the Park Details section.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Summary
|
||||
|
||||
In this guide we added a details view to our National Parks example using data from a Google Sheet. If you want to import the final project, click the "Import" button below and follow the instructions.
|
||||
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl'
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
<img
|
||||
src={useBaseUrl(
|
||||
'/library/modules/gsheets/guides/park-details/first-item-selected-preview.png'
|
||||
)}
|
||||
className="ndl-image small"
|
||||
></img>
|
||||
<ImportButton
|
||||
zip="gsheets-part2-1.zip"
|
||||
name="Google Sheets Park Details"
|
||||
thumb="arches.png"
|
||||
/>
|
||||
</div>
|
||||
|
||||
In the next guide we will look at how we can apply filters to our Google Sheet data.
|
||||
364
library/modules/gsheets/guides/setting-up/README.mdx
Normal file
364
library/modules/gsheets/guides/setting-up/README.mdx
Normal file
@@ -0,0 +1,364 @@
|
||||
---
|
||||
title: Setting up the Google Sheets Module
|
||||
hide_title: true
|
||||
---
|
||||
# Setting up the Google Sheets Module
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will show you how to include the Google Sheets module in a project and how to get data from a Google Sheet into your Noodl project.
|
||||
|
||||
## Overview
|
||||
|
||||
In this guide we will build a small application where we display a list of US National Parks. We will get the data for the parks from a public Google Sheet.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We will go though the following steps:
|
||||
|
||||
- Install the Google Sheets Module in a Noodl Project.
|
||||
- Set up a Query Sheets node to pull data from a public Google Sheet
|
||||
- Create a small list based on the data from the Google Sheet
|
||||
|
||||
## Install the Google Sheets Module
|
||||
|
||||
The easiest way to get started with the Google Sheets Module is to use the "GSheets" template when creating a new project in Noodl. In that template, the Google Sheets module is already included.
|
||||
|
||||
However, if you have an existing project, or want to start from a different template, it's easy to get started as well. Just follow these instructions.
|
||||
|
||||
When in the project, open the "Library" tab to the left. Find the "GSheet" module and click "Add".
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
After the module is imported, you should now be able to find the [Query Sheet](/library/modules/gsheets/node-docs/query-sheet), [Query Sheet Aggregate](/library/modules/gsheets/node-docs/query-sheet-aggregate) and [Sheet Row](/library/modules/gsheets/node-docs/sheet-row) nodes in the node picker. Right click in the node editor area to bring up the node picker. Look under "External libraries" to find the **Google Sheets** nodes.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Getting data from a Query Sheet
|
||||
|
||||
In this guide we will start building from the Hello World template.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Go ahead and delete the text node and you should end up just having a Group node as in the image below:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then style your group like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Before we build out our simple list UI, let's have a look at the Google Sheet that contains our data. You will find the document [here.](https://docs.google.com/spreadsheets/d/1gjttBIT4bHGFS8ynF31DoYw143ZY3UAiwopAW0N97KQ/)
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The document contains three different sheets, but we are only interested in the sheet named Parks.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
To get all the data from the Parks sheet into our Noodl project we will use a Query Sheets node, so let's add that and have a look at the properties.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Document Id property takes the id of the Google Sheet document, and we get that from this part of the Google Sheet URL (1gjttBIT4bHGFS8ynF31DoYw143ZY3UAiwopAW0N97KQ):
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's also fill in the name of the sheet we are interested wich is Parks. After you have done this, the properies of the Google Sheet node should look like this:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We will leave the Use Column For Id property set to Unique id, but you can select a column that will become the Id of the Noodl Objects that will represent each row. It's important that the values in this column are unique. Since we have chosen Unique Id, Noodl will generate it's own id's for us.
|
||||
|
||||
We can now get the data from the Query Sheet on the Items output, so let's create an Array node and give it the Id Parks and connect it like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now that we have all of the parks in an Array node, let's build out our list.
|
||||
|
||||
## Creating the Park List component
|
||||
|
||||
First let's create a new visual component that we will call Park List.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Park List component will be pretty simple. First let's enable scroll on the Group, by setting the following property.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Next we will add a [Repeater](/nodes/ui-controls/repeater) node as a child to our Group. The [Repeater](/nodes/ui-controls/repeater) node is used to generate one component for each row in the Parks Array so let's also add an Array node and give it the Parks id.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then we connect it to the Repeater node like this.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now let's jump back to our App component and add a Group that we will call List Container.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's set this List Container to be 400 px in width and then let's add the Park List component as a child.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now let's jump back to the Park List component and look at the Repeater properties. We need to tell the Repeater node which component it should generate, so before we fill this in, let's create our list items.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Building the list items
|
||||
|
||||
Let's create the visuals for our list items first by creating a new Visual Component that we call List Item.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The list items shouldn't be too tall so let's set an explicit height to 100 pixels and let's add some padding and change the Layout to Horizontal. We also want a nice bottom border.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The items should all show an image as well as the park name and which state the park is located, so let's add nodes so that we get the following node tree:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now set the Image properties like in the image below.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Group that holds the two Text nodes is using all the default settings so we don't need to change anything there, but set the properties of the Park Name Text node to:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The State Text node should have the following properties:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now that we have visuals for our list items, we can tell the Repeater node in the Park List component to use this as the template so let's do that:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
If you reload your project now you should see the following in the preview window.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This is great, now let's make sure each list item displays the correct data.
|
||||
|
||||
## Using the Sheet Row node in our List Items
|
||||
|
||||
Let's go back to our List Item component and add a Sheet Row node.
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The Sheet Row node can point to a specific row in the Google Sheet, but we need to tell it which row by providing an Id. That Id we will get from a [Repeater Item](/nodes/ui-controls/repeater-item) node. This all works exactly the same as it does when you are working with the Noodl Query Records and Record nodes, and you can read more about that in this [guide.](/docs/guides/cloud-data/quering-records-from-database)
|
||||
|
||||
Connect the Repeater Item and Sheet row like below
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now, the Sheet Row node should have a bunch of new outputs. Let's hook them up like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You should now see something like this in your preview window, and you should be able to scroll your list.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Before we finish, let's add a little bit of logic to highlight which List Item is selected. Create a States node and set it up like this:
|
||||
|
||||
<div className="ndl-image-with-background ">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's also add an Expression node and set it up like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Finally we will add a Variable node with the name SelectedRowId, a Set Variable node, and a Condition node. Then we will hook it all up like this:
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now when you click on an item in the list it should become highlighted.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Summary
|
||||
|
||||
In this guide we built a list of National Parks using data from a Google Sheet. If you want to import the final project, click the "Import" button below and follow the instructions.
|
||||
|
||||
import ImportButton from '/src/components/importbutton'
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl'
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
<img
|
||||
src={useBaseUrl('/modules/gsheets/guides/setting-up/parks-final.gif')}
|
||||
className="ndl-image small"
|
||||
></img>
|
||||
<ImportButton
|
||||
zip="gsheets-part1-1-2.zip"
|
||||
name="Google Sheets Getting Started"
|
||||
thumb="final-result.png"
|
||||
/>
|
||||
</div>
|
||||
|
||||
In the next guide, we will create a details view for our parks, and in the final guide we will look at how we can filter the data we get in the Query Sheet node.
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: Query Sheet Aggregate
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Query Sheet Aggregate
|
||||
|
||||
This node is used do aggregate data queries on a column from a public Google Sheet. The aggregate query will be either
|
||||
|
||||
- `min`/`max` - The minimum/maximum value of the specfied column.
|
||||
- `unique` - An **Array** containing all unique values in the column.
|
||||
- `count` - The number of entries in total of that column. Empty cells will not be counted.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
?> Note that the Google Sheet need to be made public for Noodl to be able to access it.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Results from the Aggregate Query
|
||||
|
||||
Note the the type of the **Result** output is dependent on which aggregate query that is run. For `min`/`max` and `count` **Result** will be a **Number**. For `unique` it will be an **Array**.
|
||||
|
||||
## Document Id and Sheet Name
|
||||
|
||||
You refer to the document through its id. You find the id in the URL of the Google Sheet.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You also have to specify the Sheet Name. You find the Sheet names in the Google Document at the bottom of the sheet.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Filters
|
||||
|
||||
A filter can be added to the query, meaning the aggregate will only be calculated based on the filtered rows. It can be a combination of various filter operators (`equalTo`, `notEqualTo`, `exists`, etc) depending on the type of the column. Multiple filters can be combined using `AND` and `OR`. A the values to filter against can be set dynamic by making the filter use an `Input` rateher than a static value. This will create an input on the node that you can connect.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Controlling when queries are performed
|
||||
|
||||
If the `Do` signal is unconnected, the Query will automatically be run when the **Query Sheet Aggregate** node is created and whenever any of its inputs change. By connecting the `Do` signal, the Query will only be run when `Do` is triggered.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| <span className="ndl-data">Document Id</span> | The id of the Google Sheets document. You can find it in the URL of the sheet. |
|
||||
| <span className="ndl-data">Sheet Name</span> | The name of the sheet where to capture the data in the Google Sheet. |
|
||||
| <span className="ndl-data">Column</span> | The name of the column in the Google Sheet to run the aggreagate query on. |
|
||||
| <span className="ndl-data">Aggregate</span> | Can be one of the following values: `Min`/`Max`/`Unique`/`Count`. `Min`/`Max` will set the miminum value in the specified column on the `Result` output. `count` will set the number of non-empty cells in the column on `Result`. Finally `Unique` will set the `Result` output to an **Array** of objects of the form `{Label:<unique value>, Value:<unique value>}` with all unique values of the column. |
|
||||
| <span className="ndl-data">Filter</span> | Each filter that is set up to controlled by an input will show up as an input on the node. |
|
||||
|
||||
| Signal | Description |
|
||||
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Do</span> | This signal will trigger the query to be executed. If the signal is not connected, the query will automatically be triggered when instanciated and when any of its inputs changes. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Result</span> | The result of the aggregate query. It's either a <span className="ndl-data">Number</span> or an **Array** depending on what aggregation query that that was performed (see `Aggregate` input above). |
|
||||
| <span className="ndl-data">Error</span> | A textual description of the latest error, when the `Failure` signal was triggered as a result of a failed Query. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Success</span> | This signal is sent when a Query was successfully performed. |
|
||||
| <span className="ndl-signal">Failure</span> | This signal is sent when a Query failed for some reason. The `Error` property will contain the error message. |
|
||||
94
library/modules/gsheets/node-docs/query-sheet/README.md
Normal file
94
library/modules/gsheets/node-docs/query-sheet/README.md
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
title: Query Sheet
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Query Sheet
|
||||
|
||||
This node is used to query data from a public Google Sheet. You can filter and sort the data. The data is organized in _Rows_ where the values of each cell in the row is exposed in a properties of the row.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The node works in a similar way as the [Query Records](/nodes/data/cloud-data/query-records) node where you can add filters and sorting.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
?> Note that the Google Sheet need to be made public for Noodl to be able to access it.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Document Id and Sheet Name
|
||||
|
||||
You refer to the document through its id. You find the id in the URL of the Google Sheet.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You also have to specify the Sheet Name. You find the Sheet names in the Google Document at the bottom of the sheet.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Filters
|
||||
|
||||
A filter can be added to the query. It can be a combination of various filter operators (`equalTo`, `notEqualTo`, `exists`, etc) depending on the type of the column. Multiple filters can be combined using `AND` and `OR`. A the values to filter against can be set dynamic by making the filter use an `Input` rateher than a static value. This will create an input on the node that you can connect.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Returned results
|
||||
|
||||
The results of the query is an **Array**, just as with a regular **Query Record**. The Array contains Objects that represents the rows in the Google Sheet. Each column value will be represented by a property in the respective object, with the same name as the column. When using a [Sheet Row](/library/modules/gsheets/node-docs/sheet-row) node, the **Id** of the object can be used to set the **Row Id** of the Sheet Row node.
|
||||
|
||||
## Controlling when queries are performed
|
||||
|
||||
If the `Do` signal is unconnected, the Query will automatically be run when the **Query Sheet** node is created and whenever any of its inputs change. By connecting the `Do` signal, the Query will only be run when `Do` is triggered.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Document Id</span> | The id of the Google Sheets document. You can find it in the URL of the sheet. |
|
||||
| <span className="ndl-data">Sheet Name</span> | The name of the sheet where to capture the data in the Google Sheet. |
|
||||
| <span className="ndl-data">Use Column For Id</span> | You can select a column that will become the **Id** of the Noodl Objects that will represent each row. It's important that the values in this column are unique. You can also chose `Unique Id`, then Noodl will generate it's own id's. |
|
||||
| <span className="ndl-data">Use limit</span> | A<span className="ndl-data"> boolean </span> that selects whether there will be a limit or not on how many items that are loaded when the query is run. This is useful when you are handling large amount of items and you want to do pagination. |
|
||||
| <span className="ndl-data">Limit</span> | This input is only available if `Use Limit` is set to<span className="ndl-data"> true </span>. It decides how many items that will be loeded when the query is triggered. To be used in combination with `Skip` to create paginations. |
|
||||
| <span className="ndl-data">Skip</span> | This input is only available if `Use Limit` is set to<span className="ndl-data"> true </span>. It sets how many items that will be skipped when the query is triggered. To be used in combination with `Skip` to create paginations. For example, if `Limit` is set to 10 and `Skip` is set to 30, the query will fetch item 31-40. |
|
||||
| <span className="ndl-data">Filter</span> | Each filter that is set up to controlled by an input will show up as an input on the node. |
|
||||
|
||||
| Signal | Description |
|
||||
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Do</span> | This signal will trigger the query to be executed. If the signal is not connected, the query will automatically be triggered when instanciated and when any of its inputs changes. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Data | Description |
|
||||
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Items</span> | An array of items that's the result of the query. The items represents a row in the Google Sheet and will contain all column values as properties on the Object, as well as an id that's set up depending on the `Set Column For Id` property is set up. |
|
||||
| <span className="ndl-data">Count</span> | The number of items the latest query returned. |
|
||||
| <span className="ndl-data">First Item Id</span> | The id of the first item that was returned in the latest query. |
|
||||
| <span className="ndl-data">Error</span> | A textual description of the latest error, when the `Failure` signal was triggered as a result of a failed Query. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Success</span> | This signal is sent when a Query was successfully performed. |
|
||||
| <span className="ndl-signal">Failure</span> | This signal is sent when a Query failed for some reason. The `Error` property will contain the error message. |
|
||||
49
library/modules/gsheets/node-docs/sheet-row/README.md
Normal file
49
library/modules/gsheets/node-docs/sheet-row/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
title: Sheet Row
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Sheet Row
|
||||
|
||||
This node is used do simplify handling of results from a [Query Sheet](/library/modules/gsheets/node-docs/sheet-row) node. It's typically used in a combination with a [Repeater Item](/nodes/ui-controls/repeater-item) to easily connect any columns available in a row in a Google Sheets sheet.
|
||||
|
||||
By setting the `Row Id` of the **Sheet Row**, and selecting the **Sheet** (if you use more than one) your **Sheet Row** will automatically show all available column values.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
?> Note that the Google Sheet need to be made public for Noodl to be able to access it.
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Sheet</span> | The name of the Sheet in which the row lies. This input only exists if you are querying multiple sheets, otherwise it will automatically select the sheet you are querying. |
|
||||
| <span className="ndl-data">Row Id</span> | The id of the Sheet Row. The Id is determined by the [Query Sheet](/library/modules/gsheets/node-docs/query-sheet) node accessing the Sheet, where you can decide how the Id is generated throguh the **Use Column For Id** property. |
|
||||
|
||||
| Signal | Description |
|
||||
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Fetch</span> | Explicitly tells the **Sheet Row** to fetch data from the Google Sheet. If this signal is unconnected it will fetch automatically when the **Sheet Row** node is created. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Data | Description |
|
||||
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Column Values</span> | Each column in the row will become and output with the same name holding the value of the cell. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Fetched</span> | This signal is sent when new data have been fetched from the Google Sheet to the **Sheet Row**. |
|
||||
10
library/modules/gsheets/release-notes.md
Normal file
10
library/modules/gsheets/release-notes.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Release Notes
|
||||
hide_title: true
|
||||
---
|
||||
# Release Notes
|
||||
|
||||
Version 1.0 [2022-01-21]
|
||||
* Query Sheet node that can filter and sort rows in a public Google Sheet document
|
||||
* Query Sheet Aggregate that can apply an aggregate filter on a specific column on a public Google Sheet document
|
||||
* Sheet Row node that serves as an easy to access data node representing a row in a Google Sheet document
|
||||
14
library/modules/i18next/README.md
Normal file
14
library/modules/i18next/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: i18next Module
|
||||
hide_title: true
|
||||
---
|
||||
# i18next Module
|
||||
|
||||
Module for using [i18next](https://www.i18next.com) in Noodl.
|
||||
The module has three nodes, _i18next_, _Language Bundle_ and _Translation_.
|
||||
|
||||
- i18next node is used to keep track of current language and to change the language
|
||||
- Language Bundle holds the resources (i.e. localized texts) for a specific language
|
||||
- Translation retrieves the correct translation for a specific string (identified by a key) from the currently selected language. If the current language changes, all strings are updated accordingly.
|
||||
|
||||
An example with the most common cases can be found [here](/library/examples/localization).
|
||||
26
library/modules/i18next/i18next-node.md
Normal file
26
library/modules/i18next/i18next-node.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
title: i18next
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
# i18next
|
||||
|
||||
This is used to register bundles and to set and get the current language.
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
**Language**
|
||||
This is a string input that is used to specify the current language. It should be a language code that matches a langugage in the bundle.
|
||||
|
||||
**ChangeLanguage**
|
||||
This signal is used in combination with **Language** to set a new current language. The **Language** string should be a language code, and is matched to a language bundle. For example `en` for English.
|
||||
|
||||
## Outputs
|
||||
|
||||
**LanguageChanged**
|
||||
This is triggered when the current language is changed, as a result of a signal received on **ChangeLanguage**. This is useful if your application needs to take action when the language is changed.
|
||||
|
||||
**CurrentLanguage**
|
||||
Contains the language code of the currently set language.
|
||||
58
library/modules/i18next/language-bundle.md
Normal file
58
library/modules/i18next/language-bundle.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: LanguageBundle
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
# LanguageBundle
|
||||
|
||||
The language bundle contains the translations for a language. If you have multiple languages you will have one LanguageBundle for each language and they generally should contain the same strings, translated to the respective language.
|
||||
|
||||
Each language bundle also has a "Namespace". This can be used to separate different parts of translations to different bundles that can be loaded at different times. For example you can have one bundle for static UI-texts called "UI" and one bundle for texts that are dynamically loaded based on content in the database called "Dbtexts". If you support two languages, English and Spanish, this would mean that you have four language bundle nodes: UI and Dbtexts for English and Spanish.
|
||||
|
||||
The bundle itself is a JSON-object, as described on [i18next website](https://www.i18next.com/translation-function/essentials). It contains `key:string` pairs for each text. It can also include an inner structure (JSON objects) to help organize strings based on features. Aa bundle for English could look like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"loginpage":{
|
||||
"user_name":"User Name",
|
||||
"confirm_button":{
|
||||
"label":"Confirm",
|
||||
"hover_text":"Press here to confirm"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example the key `loginpage.confirm_button.hover_text` would identify the button hover text translation when used in a Translation node.
|
||||
Note that i18next supports various dynamic features in the texts, e.g. plurals, date formats, etc. These are generally supported when used in Noodl.
|
||||
|
||||
There are typically two ways to use Language Bundles. For static texts, for example UI texts, you edit the bundle object directly in Noodl (pressing the "Edit" button on the property panel). As you build the UI you add new texts to the bundle. You have one bundle per language. For dynamic texts, for example loaded during execution from a database, you programatically create bundle objects and load them into the **LanguageBundle** when available and using the AddBundleObject input.
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
**Language**
|
||||
The language that this bundle applies to. Typically a language code string, e.g. `en`.
|
||||
|
||||
**Namespace**
|
||||
The name of the Namespace. Can by any string.
|
||||
|
||||
**AddResource**
|
||||
A signal to add a specific resource to the bundle. This is used for dynamic language string, e.g. when reading content from a database.
|
||||
|
||||
**ResourceKey**
|
||||
The resource key that will be added when the **AddResource** signal is received.
|
||||
|
||||
**ResourceValue**
|
||||
The resource value that will be associated with the **ResourceKey** when the **AddResource** signal is received.
|
||||
|
||||
**AddBundleObject**
|
||||
This signal is used to add a complete bundle object to the language bundle. This is typically used to dynamically add language resources to a bundle e.g. when fetching from a database.
|
||||
|
||||
**Resource Bundle Object**
|
||||
The object (a javascript object) that will be added to the language bundle when the **AddBundleObject** signal is received.
|
||||
|
||||
## Outputs
|
||||
|
||||
**BundleLoaded**
|
||||
Triggered when a new bundle object has been loaded.
|
||||
32
library/modules/i18next/translation.md
Normal file
32
library/modules/i18next/translation.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Translation
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
# Translation
|
||||
|
||||
This is the node where the translation happens. You typically connect these to your **Text** nodes and **Text Input** nodes. Translation nodes automatically change their output if language changes, if the bundle is changing, and when it becomes available.
|
||||
|
||||
There are two dynamic features in the Translation node:
|
||||
|
||||
- If your translation includes some of i18next dynamic features, for example having a `{{count}}` variable deciding between a plural string or not, or by inserting variables in the middle of the string, any variables used can be added as inputs on the Translation node, and be connected to other nodes in Noodl. For example if a translation uses the variable `{{count}}` adding an input named "count" and connecting it to a Number node, the translation will change when the Number node is updated.
|
||||
|
||||
- The name of the key can be dynamic. In most cases the key of a translation is known when building the app, but there are cases when the name of the key is only known during runtime. For example, in a database with thousands of products and related texts translated to multiple languages, the translations are generated when needed. The name of the keys are also generated dynamically. A product with an id `xyz123abc` may have its translations stored in an object named `xyz123abc`, `{"xyz123abc":{"label":"Product A", "desc":"A great product"}}`. By using dynamic naming of the key in a Translation node, using the {}-pattern, the actual key can be resolved at runtime. In this scenario naming the Key in the translation node `{product_id}.label`, will expose a new input to the Translation node called "product_id" that can be connected to a Model node in Noodl.
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
**Key**
|
||||
The key of the translation. This can be a static text or a text including one or more variables using `{var}` syntax. Variables will become available as inputs.
|
||||
|
||||
**Namespace**
|
||||
The namespace that this translation is using. Should match a namespace of a Language Bundle.
|
||||
|
||||
### Variables
|
||||
You can also add custom inputs to the translation node. They will be mapped to variables in the translated text itself (`{{var}}`) to make use of the i18next transformation functionality, such as plurals.
|
||||
|
||||
## Outputs
|
||||
|
||||
**Translation**
|
||||
This translated and formatted text string.
|
||||
83
library/modules/image-cropper/README.mdx
Normal file
83
library/modules/image-cropper/README.mdx
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Image Cropper
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import ReactPlayer from 'react-player'
|
||||
|
||||
|
||||
# Image Cropper
|
||||
|
||||
This module contains a simple Image Cropper component, along with an example of how to use it. It's mainly intended to crop images for e.g. profile pictures. The cropper takes a **File** containing an image as an input (typically coming from an [Open File Picker](/nodes/utilities/open-file-picker) node). It then lets the user pan and zoom in the image to find the area to crop out. The Image Cropper provides a URL to the image and the file object to the area that's currently being cropped out.
|
||||
This file is typically passed to a [Upload File](/nodes/data/cloud-data/upload-file) node.
|
||||
|
||||
<ReactPlayer playing autoplay muted loop url='imagecropper-1.mp4' />
|
||||
|
||||
## How to use
|
||||
|
||||
The component itself is relatively simple. It shows the provided picture and a mask on top. The area in the mask is what will be cropped out. The user can pan around and Zoom using the scroll wheel. You can also zoom in and zoom out by triggering signals (e.g. coming from **Buttons**). The mask can be customized to fit the style of your app.
|
||||
|
||||
Each time the user pans or zooms to a new area the cropped version of the image is generated. The component outputs both the **File** and a URL to the image (which will be a local blob file). Below is an example of how it can be used. (The example is also provided as part of the module).
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
When you import the module you will get a new sheet called `Image Cropper`. This will include a folder called `Example Usage` with a simple example using it in a popup. The main component is the `Image Cropper`.
|
||||
|
||||
## Example Usage in 'Sign Up Template'
|
||||
|
||||
It's very easy to try out the Image Cropper in the Sign Up Template. Start a new project using that template. Then in the page `Profile`. Then change up the part where the profile picture is saved as the image below.
|
||||
|
||||
<div className="ndl-image-with-background xl">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Use the popup provided in the `Usage Example` called `Cropper Popup`.
|
||||
|
||||
## The Image Cropper Node
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Circluar Mask</span> | A <span className="ndl-data"> boolean </span> that decides whether tha mask should be circular or rectangular. Note that unless the ratio of the mask sides is 1:1 the mask will not be truly circular. |
|
||||
| <span className="ndl-data">Mask Ratio Height</span> | The ratio between height and width of the mask to use. For example 1:1 will produce a square mask. |
|
||||
| <span className="ndl-data">Mask Ratio Width</span> | The ratio between height and width of the mask to use. For example 1:1 will produce a square mask. |
|
||||
| <span className="ndl-data">Mounted</span> | Controls whether the control is mounted or not. |
|
||||
| <span className="ndl-data">Target Resolution</span> | The target resolution of the cropped area on it's longest dimension, in pixels. For example, if the ratio between height and width is 2:1, and the target resolution is set to 500 pixels .then the resulting crop will have a height of 500 pixels and width of 250 pixels. However, this resolution cannot exceed the source resolution and if the source resolution is lower, it will use the source resolution. |
|
||||
| <span className="ndl-data">Mask Color</span> | The color of the mask. You should probably use a semi-transparent color if you want the user to see what its cropping. |
|
||||
| <span className="ndl-data">Mask Border Style</span> | The border style of the mask, `Solid`, `Dotted`, `Dashed` or `None`. |
|
||||
| <span className="ndl-data">Mask Border Color</span> | The border color of the mask. Only applicable if a border style has been set. |
|
||||
| <span className="ndl-data">Mask Border Width</span> | The border width. Only applicable if a border style has been set. |
|
||||
| <span className="ndl-data">Image File</span> | The image file to be cropped. The should be a Javascript `File`, for example coming from a **Open File Picker** node. |
|
||||
|
||||
| Signal | Description |
|
||||
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Zoom In</span> | This signal will trigger a Zoom In into the image. |
|
||||
| <span className="ndl-signal">Zoom Out</span> | This signal will trigger a Zoom Out of the image. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Data | Description |
|
||||
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Cropped File</span> | A file containing the area that have been cropped. This can for example be inputted into a **Upload Cloud File** node to be stored in the cloud.|
|
||||
| <span className="ndl-data">Preview Url</span> | A URL to a local image. This can be fed into an **Image** node to render the area that's cropped. |
|
||||
| <span className="ndl-data">Cropped File Size</span> | The size of the image that's cropped in bytes.. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">New Area Selected</span> | This signal is sent whenever a new area have been selected by the user. When the signal is sent there is a new `Cropped File` and `Preview Url` available on the output. |
|
||||
|
||||
|
||||
|
||||
9
library/modules/lottie/README.md
Normal file
9
library/modules/lottie/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Lottie
|
||||
hide_title: true
|
||||
---
|
||||
# Lottie
|
||||
|
||||
Documentation coming soon...
|
||||
|
||||
|
||||
18
library/modules/lottie/lottie-node.md
Normal file
18
library/modules/lottie/lottie-node.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Lottie
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
# Lottie
|
||||
|
||||
The documentation for this node will be coming soon.
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||

|
||||
|
||||
## Outputs
|
||||
|
||||

|
||||
18
library/modules/mapbox/README.md
Normal file
18
library/modules/mapbox/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Mapbox
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Mapbox
|
||||
|
||||
[](https://github.com/noodlapp/modules/tree/main/modules/mapbox)
|
||||
|
||||
This module allows you to add a map with marker functionality to your Noodl App, using [Mapbox](https://www.mapbox.com/).
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Follow the guides ([setting up](/library/modules/mapbox/guides/setting-up), [interacting](/library/modules/mapbox/guides/interacting) and [markers](/library/modules/mapbox/guides/using-markers)) or jump to the [node documentation](/library/modules/mapbox/nodes/v2/mapbox-map).
|
||||
109
library/modules/mapbox/guides/3d-model.md
Normal file
109
library/modules/mapbox/guides/3d-model.md
Normal file
@@ -0,0 +1,109 @@
|
||||
https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/
|
||||
|
||||
```js
|
||||
const map = Inputs.map;
|
||||
|
||||
// parameters to ensure the model is georeferenced correctly on the map
|
||||
const modelOrigin = [148.9819, -35.39847];
|
||||
const modelAltitude = 0;
|
||||
const modelRotate = [Math.PI / 2, 0, 0];
|
||||
|
||||
const modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
|
||||
modelOrigin,
|
||||
modelAltitude
|
||||
);
|
||||
|
||||
// transformation parameters to position, rotate and scale the 3D model onto the map
|
||||
const modelTransform = {
|
||||
translateX: modelAsMercatorCoordinate.x,
|
||||
translateY: modelAsMercatorCoordinate.y,
|
||||
translateZ: modelAsMercatorCoordinate.z,
|
||||
rotateX: modelRotate[0],
|
||||
rotateY: modelRotate[1],
|
||||
rotateZ: modelRotate[2],
|
||||
/* Since the 3D model is in real world meters, a scale transform needs to be
|
||||
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
|
||||
*/
|
||||
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
|
||||
};
|
||||
|
||||
const THREE = window.THREE;
|
||||
|
||||
// configuration of the custom layer for a 3D model per the CustomLayerInterface
|
||||
const customLayer = {
|
||||
id: '3d-model',
|
||||
type: 'custom',
|
||||
renderingMode: '3d',
|
||||
onAdd: function (map, gl) {
|
||||
this.camera = new THREE.Camera();
|
||||
this.scene = new THREE.Scene();
|
||||
|
||||
// create two three.js lights to illuminate the model
|
||||
const directionalLight = new THREE.DirectionalLight(0xffffff);
|
||||
directionalLight.position.set(0, -70, 100).normalize();
|
||||
this.scene.add(directionalLight);
|
||||
|
||||
const directionalLight2 = new THREE.DirectionalLight(0xffffff);
|
||||
directionalLight2.position.set(0, 70, 100).normalize();
|
||||
this.scene.add(directionalLight2);
|
||||
|
||||
// use the three.js GLTF loader to add the 3D model to the three.js scene
|
||||
const loader = new THREE.GLTFLoader();
|
||||
loader.load(
|
||||
'https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf',
|
||||
(gltf) => {
|
||||
this.scene.add(gltf.scene);
|
||||
}
|
||||
);
|
||||
this.map = map;
|
||||
|
||||
// use the Mapbox GL JS map canvas for three.js
|
||||
this.renderer = new THREE.WebGLRenderer({
|
||||
canvas: map.getCanvas(),
|
||||
context: gl,
|
||||
antialias: true
|
||||
});
|
||||
|
||||
this.renderer.autoClear = false;
|
||||
},
|
||||
render: function (gl, matrix) {
|
||||
const rotationX = new THREE.Matrix4().makeRotationAxis(
|
||||
new THREE.Vector3(1, 0, 0),
|
||||
modelTransform.rotateX
|
||||
);
|
||||
const rotationY = new THREE.Matrix4().makeRotationAxis(
|
||||
new THREE.Vector3(0, 1, 0),
|
||||
modelTransform.rotateY
|
||||
);
|
||||
const rotationZ = new THREE.Matrix4().makeRotationAxis(
|
||||
new THREE.Vector3(0, 0, 1),
|
||||
modelTransform.rotateZ
|
||||
);
|
||||
|
||||
const m = new THREE.Matrix4().fromArray(matrix);
|
||||
const l = new THREE.Matrix4()
|
||||
.makeTranslation(
|
||||
modelTransform.translateX,
|
||||
modelTransform.translateY,
|
||||
modelTransform.translateZ
|
||||
)
|
||||
.scale(
|
||||
new THREE.Vector3(
|
||||
modelTransform.scale,
|
||||
-modelTransform.scale,
|
||||
modelTransform.scale
|
||||
)
|
||||
)
|
||||
.multiply(rotationX)
|
||||
.multiply(rotationY)
|
||||
.multiply(rotationZ);
|
||||
|
||||
this.camera.projectionMatrix = m.multiply(l);
|
||||
this.renderer.resetState();
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
this.map.triggerRepaint();
|
||||
}
|
||||
};
|
||||
|
||||
map.addLayer(customLayer, 'waterway-label');
|
||||
```
|
||||
21
library/modules/mapbox/guides/camera.md
Normal file
21
library/modules/mapbox/guides/camera.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Camera
|
||||
|
||||
## Fly to location
|
||||
|
||||
```js
|
||||
const mapboxObject = Inputs.MapboxObject;
|
||||
if (!mapboxObject) return;
|
||||
|
||||
// Mapbox example
|
||||
// https://docs.mapbox.com/mapbox-gl-js/example/flyto/
|
||||
|
||||
// flyTo doc:
|
||||
// https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto
|
||||
mapboxObject.flyTo({
|
||||
center: [(Math.random() - 0.5) * 360, (Math.random() - 0.5) * 100],
|
||||
zoom: 10,
|
||||
// this animation is considered essential
|
||||
// with respect to prefers-reduced-motion
|
||||
essential: true,
|
||||
});
|
||||
```
|
||||
253
library/modules/mapbox/guides/directions-api/README.md
Normal file
253
library/modules/mapbox/guides/directions-api/README.md
Normal file
@@ -0,0 +1,253 @@
|
||||
---
|
||||
title: Directions API with the Mapbox Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Directions API with the Mapbox Module
|
||||
|
||||
Here are some code heavy example of how to use the Directions API in Noodl.
|
||||
The code in this example is using [Getting started with the Mapbox Directions API
|
||||
](https://docs.mapbox.com/help/tutorials/getting-started-directions-api/) guide.
|
||||
|
||||
## Listen to on click events on Mapbox
|
||||
|
||||
Script node:
|
||||
|
||||
```js
|
||||
Script.Outputs = {
|
||||
["Mapbox Object"]: "*",
|
||||
["Clicked"]: "signal",
|
||||
["Clicked Longitude"]: "number",
|
||||
["Clicked Latitute"]: "number"
|
||||
};
|
||||
|
||||
Script.Signals["Mount Click Event"] = function () {
|
||||
// Listen to the Mapbox on click event
|
||||
// NOTE: This might cause some memory leaks,
|
||||
// Not sure how Mapbox is handling it.
|
||||
Script.Inputs["Mapbox Object"].on("click", (event) => {
|
||||
// Get the coordinates that the user pressed on
|
||||
const coords = Object.keys(event.lngLat).map((key) => event.lngLat[key]);
|
||||
|
||||
// Set the Noodl outputs
|
||||
Script.Outputs["Clicked Longitude"] = coords[0];
|
||||
Script.Outputs["Clicked Latitute"] = coords[1];
|
||||
|
||||
// Send the click signal
|
||||
Script.Outputs["Clicked"]();
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
## Create a route path on Mapbox
|
||||
|
||||
Script node:
|
||||
|
||||
```js
|
||||
// This function makes a Mapbox Directions API request
|
||||
async function getRoute(map, start, end) {
|
||||
const accessToken = Noodl.getProjectSettings().mapboxAccessToken;
|
||||
|
||||
// make a directions request using cycling profile
|
||||
// an arbitrary start will always be the same
|
||||
// only the end or destination will change
|
||||
const query = await fetch(
|
||||
`https://api.mapbox.com/directions/v5/mapbox/cycling/${start[0]},${start[1]};${end[0]},${end[1]}?steps=true&geometries=geojson&access_token=${accessToken}`,
|
||||
{ method: "GET" }
|
||||
);
|
||||
const json = await query.json();
|
||||
const data = json.routes[0];
|
||||
const route = data.geometry.coordinates;
|
||||
const geojson = {
|
||||
type: "Feature",
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: "LineString",
|
||||
coordinates: route,
|
||||
},
|
||||
};
|
||||
// if the route already exists on the map, we'll reset it using setData
|
||||
if (map.getSource("route")) {
|
||||
map.getSource("route").setData(geojson);
|
||||
}
|
||||
// otherwise, we'll make a new request
|
||||
else {
|
||||
map.addLayer({
|
||||
id: "route",
|
||||
type: "line",
|
||||
source: {
|
||||
type: "geojson",
|
||||
data: geojson,
|
||||
},
|
||||
layout: {
|
||||
"line-join": "round",
|
||||
"line-cap": "round",
|
||||
},
|
||||
paint: {
|
||||
"line-color": "#3887be",
|
||||
"line-width": 5,
|
||||
"line-opacity": 0.75,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//
|
||||
// Start of Noodl Script
|
||||
//
|
||||
|
||||
Script.Inputs = {
|
||||
map: {
|
||||
displayName: "Mapbox Object",
|
||||
type: "*",
|
||||
},
|
||||
|
||||
startLongitude: {
|
||||
displayName: "Start Longitude",
|
||||
type: "number",
|
||||
group: "Coordinates",
|
||||
default: 0,
|
||||
},
|
||||
startLatitute: {
|
||||
displayName: "Start Latitude",
|
||||
type: "number",
|
||||
group: "Coordinates",
|
||||
default: 0,
|
||||
},
|
||||
|
||||
endLongitude: {
|
||||
displayName: "End Longitude",
|
||||
type: "number",
|
||||
group: "Coordinates",
|
||||
default: 0,
|
||||
},
|
||||
endLatitute: {
|
||||
displayName: "End Latitude",
|
||||
type: "number",
|
||||
group: "Coordinates",
|
||||
default: 0,
|
||||
},
|
||||
|
||||
// You can read more about Routing profiles here:
|
||||
// https://docs.mapbox.com/api/navigation/directions/#routing-profiles
|
||||
routingProfile: {
|
||||
displayName: "Routing Profile",
|
||||
type: {
|
||||
name: "enum",
|
||||
enums: [
|
||||
{
|
||||
label: "Driving Traffic",
|
||||
value: "mapbox/driving-traffic",
|
||||
},
|
||||
{
|
||||
label: "Driving",
|
||||
value: "mapbox/driving",
|
||||
},
|
||||
{
|
||||
label: "Walking",
|
||||
value: "mapbox/walking",
|
||||
},
|
||||
{
|
||||
label: "Cycling",
|
||||
value: "mapbox/cycling",
|
||||
},
|
||||
],
|
||||
},
|
||||
default: "mapbox/cycling",
|
||||
},
|
||||
};
|
||||
|
||||
Script.Outputs = {
|
||||
Steps: "array",
|
||||
Duration: "number",
|
||||
};
|
||||
|
||||
Script.Signals.CreateRoute = function () {
|
||||
const map = Script.Inputs.Map;
|
||||
const startCoords = [
|
||||
Script.Inputs.startLongitude,
|
||||
Script.Inputs.startLatitute,
|
||||
];
|
||||
const endCoords = [Script.Inputs.endLongitude, Script.Inputs.endLatitute];
|
||||
|
||||
// Add starting point to the map
|
||||
map.addLayer({
|
||||
id: "point",
|
||||
type: "circle",
|
||||
source: {
|
||||
type: "geojson",
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: startCoords,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
paint: {
|
||||
"circle-radius": 10,
|
||||
"circle-color": "#3887be",
|
||||
},
|
||||
});
|
||||
|
||||
const endPoint = {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: endCoords,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (map.getLayer("end")) {
|
||||
map.getSource("end").setData(endPoint);
|
||||
} else {
|
||||
map.addLayer({
|
||||
id: "end",
|
||||
type: "circle",
|
||||
source: {
|
||||
type: "geojson",
|
||||
data: {
|
||||
type: "FeatureCollection",
|
||||
features: [
|
||||
{
|
||||
type: "Feature",
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: endCoords,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
paint: {
|
||||
"circle-radius": 10,
|
||||
"circle-color": "#f30",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// make an directions request that
|
||||
getRoute(map, startCoords, endCoords).then((data) => {
|
||||
// Extract the steps / instructions
|
||||
const steps = data.legs[0].steps;
|
||||
Script.Outputs.Steps = steps;
|
||||
|
||||
Script.Outputs.Duration = Math.floor(data.duration / 60);
|
||||
});
|
||||
};
|
||||
```
|
||||
131
library/modules/mapbox/guides/directions.md
Normal file
131
library/modules/mapbox/guides/directions.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Directions
|
||||
|
||||
|
||||
|
||||
## Create a request to Directions API
|
||||
|
||||
TODO: Add more info about "overview" (full, simplified, or false)
|
||||
|
||||
```js
|
||||
// Get the Mapbox access token from Noodl project settings
|
||||
const access_token = Noodl.getProjectSettings().mapboxAccessToken;
|
||||
|
||||
// For using the API to handle min/max road width, we have to use the "driving" profile.
|
||||
// https://docs.mapbox.com/api/navigation/directions#optional-parameters-for-the-mapboxdriving-profile
|
||||
const routingProfile = "driving";
|
||||
|
||||
// Encode the coordinates to be URL-safe
|
||||
const coordinates = encodeURIComponent([fromCoordinate, toCoordinate].join(";"));
|
||||
|
||||
// Define query parameters for the API request
|
||||
//
|
||||
// Playground by Mapbox to test out all the features:
|
||||
// https://docs.mapbox.com/playground/directions/
|
||||
const queryParams = {
|
||||
access_token, // Provide the access token
|
||||
alternatives: true,
|
||||
continue_straight: true,
|
||||
geometries: "geojson",
|
||||
language: "en",
|
||||
overview: "simplified",
|
||||
steps: true,
|
||||
// The max vehicle height, in meters. If this parameter is provided, the
|
||||
// Directions API will compute a route that includes only roads with a height
|
||||
// limit greater than or equal to the max vehicle height. max_height must be
|
||||
// between 0 and 10 meters. The default value is 1.6 meters. Coverage for road
|
||||
// height restriction may vary by region.
|
||||
max_height,
|
||||
// The max vehicle width, in meters. If this parameter is provided, the
|
||||
// Directions API will compute a route that includes only roads with a width
|
||||
// limit greater than or equal to the max vehicle width. max_width must be
|
||||
// between 0 and 10 meters. The default value is 1.9 meters. Coverage for road
|
||||
// width restriction may vary by region.
|
||||
max_width,
|
||||
};
|
||||
|
||||
// Construct the query string from the query parameters
|
||||
const query = Object.keys(queryParams)
|
||||
.filter((key) => !!queryParams[key]) // Filter out empty values
|
||||
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
|
||||
.join('&');
|
||||
|
||||
// Set the endpoint URL for the Mapbox directions API
|
||||
const ENDPOINT = 'https://api.mapbox.com/directions/v5/mapbox';
|
||||
|
||||
// Make the API request and get the response as JSON
|
||||
const response = await fetch(`${ENDPOINT}/${routingProfile}/${coordinates}?${query}`);
|
||||
const json = await response.json();
|
||||
|
||||
if (json.code === "Ok") {
|
||||
Outputs.Routes = jsonroutes;
|
||||
Outputs.Success();
|
||||
} else {
|
||||
Outputs.Failure();
|
||||
}
|
||||
```
|
||||
|
||||
Draw the route:
|
||||
```js
|
||||
Script.Inputs = {
|
||||
MapboxObject: "object",
|
||||
Routes: "array"
|
||||
};
|
||||
|
||||
Script.Outputs = {
|
||||
Done: "signal",
|
||||
};
|
||||
|
||||
|
||||
Script.Signals = {
|
||||
Update() {
|
||||
const map = Script.Inputs.MapboxObject;
|
||||
|
||||
const route = Script.Inputs.Routes[0];
|
||||
|
||||
function createOrUpdateSource(id, newSource) {
|
||||
const source = map.getSource(id);
|
||||
if (source) {
|
||||
source.setData(newSource.data);
|
||||
} else {
|
||||
map.addSource(id, newSource);
|
||||
}
|
||||
}
|
||||
|
||||
function createOrUpdateLayer(newLayer) {
|
||||
const layer = map.getLayer(newLayer.id);
|
||||
if (layer) {
|
||||
if (newLayer.paint) {
|
||||
Object.keys(newLayer.paint).forEach((key) => {
|
||||
layer.setPaintProperty(key, newLayer.paint[key]);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
map.addLayer(newLayer);
|
||||
}
|
||||
}
|
||||
|
||||
createOrUpdateSource('route', {
|
||||
'type': 'geojson',
|
||||
'data': {
|
||||
'type': 'Feature',
|
||||
'properties': {},
|
||||
'geometry': route.geometry,
|
||||
}
|
||||
});
|
||||
|
||||
createOrUpdateLayer({
|
||||
'id': 'route',
|
||||
'type': 'line',
|
||||
'source': 'route',
|
||||
'layout': {
|
||||
'line-join': 'round',
|
||||
'line-cap': 'round'
|
||||
},
|
||||
'paint': {
|
||||
'line-color': '#888',
|
||||
'line-width': 8
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
```
|
||||
111
library/modules/mapbox/guides/geocoder.md
Normal file
111
library/modules/mapbox/guides/geocoder.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: Geocoder
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Geocoder
|
||||
|
||||
Mapbox Geocoder API is a geocoding service that allows developers to convert human-readable addresses into geographic coordinates (latitude and longitude) and vice versa. It is a RESTful API that provides geocoding and reverse geocoding services for worldwide locations. The API uses machine learning and other advanced algorithms to provide accurate and relevant results for address searches. Mapbox Geocoder API can be used in a variety of applications, such as location-based services, logistics and delivery management, real estate, and more. It also offers various features such as autocomplete suggestions, batch geocoding, and custom matching parameters, making it a powerful tool for developers to build location-based applications.
|
||||
|
||||
## Create a request to Geocoder API
|
||||
|
||||
```js
|
||||
// Define the expected inputs for the script
|
||||
Script.Inputs = {
|
||||
Query: "string",
|
||||
};
|
||||
|
||||
// Define the expected outputs for the script
|
||||
Script.Outputs = {
|
||||
Items: "array",
|
||||
Searched: "signal",
|
||||
};
|
||||
|
||||
// Set the endpoint URL for the Mapbox geocoding API
|
||||
const ENDPOINT = "https://api.mapbox.com/geocoding/v5/mapbox.places";
|
||||
|
||||
// Define an asynchronous function to make the API request
|
||||
async function makeRequest() {
|
||||
// Get the Mapbox access token from Noodl project settings
|
||||
const access_token = Noodl.getProjectSettings().mapboxAccessToken;
|
||||
|
||||
// Encode the search query to be URL-safe
|
||||
const search_text = encodeURIComponent(Script.Inputs.Query);
|
||||
|
||||
// Define query parameters for the API request
|
||||
//
|
||||
// Playground by Mapbox to test out all the features:
|
||||
// https://docs.mapbox.com/playground/geocoding
|
||||
//
|
||||
// Here is a list of all the different possible types:
|
||||
// - address
|
||||
// - country
|
||||
// - region
|
||||
// - postcode
|
||||
// - district
|
||||
// - place
|
||||
// - neighborhood
|
||||
// - locality
|
||||
// - poi
|
||||
const queryParams = {
|
||||
access_token, // Provide the access token
|
||||
proximity: "ip", // Bias results towards user's location
|
||||
limit: 5, // Maximum number of results to return
|
||||
types: ["address"].join(","), // Filter results to include only addresses
|
||||
fuzzyMatch: true, // Enable approximate matching
|
||||
};
|
||||
|
||||
// Construct the query string from the query parameters
|
||||
const query = Object.keys(queryParams)
|
||||
.filter((key) => !!queryParams[key]) // Filter out empty values
|
||||
.map(
|
||||
(key) =>
|
||||
`${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`
|
||||
)
|
||||
.join("&");
|
||||
|
||||
// Make the API request and get the response as JSON
|
||||
const response = await fetch(`${ENDPOINT}/${search_text}.json?${query}`);
|
||||
const json = await response.json();
|
||||
|
||||
// Map the API response to an array of search results
|
||||
const items = json.features.map((x) =>
|
||||
Noodl.Object.create({
|
||||
text: x.text,
|
||||
place_name: x.place_name,
|
||||
// Convert the array of [latitude, longitude] to a Geopoint
|
||||
center: { latitude: x.center[0], longitude: x.center[1] },
|
||||
})
|
||||
);
|
||||
|
||||
Script.Outputs.Items = items;
|
||||
Script.Outputs.Searched();
|
||||
}
|
||||
|
||||
Script.Signals = {
|
||||
Search() {
|
||||
makeRequest();
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Improve the search result
|
||||
|
||||
While comparing the built in Geocoder in Mapbox and using this Script.
|
||||
There are a few differences and the result from the Mapbox Geocoder is getting better result.
|
||||
|
||||
The reason why the results are better is that the parameters are a little different, but in the end they are using the same API endpoints.
|
||||
|
||||
To make the parameters match, we can make a few changes in this code:
|
||||
|
||||
```js
|
||||
const queryParams = {
|
||||
access_token, // Provide the access token
|
||||
proximity: [Script.Inputs.lng, Script.Inputs.lat].join(','), // Bias results towards user's location
|
||||
limit: 5, // Maximum number of results to return
|
||||
language: 'en-GB'
|
||||
};
|
||||
```
|
||||
|
||||
The main change here is the `proximity` that we changed to a Geopoint instead of `ip`.
|
||||
This requires 2 new inputs to the Script node, `lng` and `lat`, connected from the Mapbox node center lng and lat position.
|
||||
111
library/modules/mapbox/guides/interacting/README.md
Normal file
111
library/modules/mapbox/guides/interacting/README.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: Interacting with the Mapbox Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Interacting with the Mapbox Module
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will teach you how to implement basic interactions with your Mapbox map using the Mapbox Module.
|
||||
|
||||
## Overview
|
||||
|
||||
If you haven't setup Mapbox, it is recommended to read [setting up Mapbox guide](/library/modules/mapbox/guides/setting-up) before continuing this guide.
|
||||
|
||||
We will go though the following steps:
|
||||
|
||||
- Getting the latitude and longitude of the position a user clicked on the map.
|
||||
- Detecting when a user moves the map.
|
||||
|
||||
## Getting the position that the user clicked
|
||||
|
||||
If we start out with the same super simple app as in the previous guide ([Setting up](/library/modules/mapbox/guides/setting-up) guide) we can start adding some interactions to it.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Let's first remove the "Hello World"-text. Instead we replace it with a panel. We will build it using a [Group](/nodes/basic-elements/group) node. So add a **Group** node at the bottom of the node hierarchy. Name it "Popup Panel" for readability.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We want it to float on top of the Mapbox Map so change it's **Position** to **Absolute**. Center it and dock it to the bottom using the **Layout** controls. Set a size of 300 pixels wide and 100 pixels high for now. Give it a bottom margin of 20 pixels to give it some space.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Also make it white, with rounded corners of 10 pixels and a 2 pixel outline of a dark grey color. Also tick `Shadow Enabled` to make it a little nicer visually.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now you should have a panel floating on top of the map.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We want to print out the geographical location in the panel, i.e. the latitude and longitude of the position the user clicks.
|
||||
|
||||
Add two text nodes in the panel. Adjust the padding (horizontally and vertically) of the "Popup Panel" to 10 pixels to give the text some space.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then connect the two outputs `Longitude` and `Latitude` to the respective text.
|
||||
|
||||
_Make sure it's the one under "Mapped Clicked" Section_ since there are two other similarly named outputs that holds the current panning position of the map.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now try clicking around in the map. You should see the two texts updating whenever you click.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Tracking Map Movement
|
||||
|
||||
Now let's add some behavior to the panel. We want it to appear from the bottom when the user clicks on the map. Then, when the user starts panning or zooming in the map. To do this we are going to use the `Click` and `Map Moved` output signals.
|
||||
|
||||
First add a [States](/nodes/utilities/logic/states) node that will hold the current state of the panel. Add the states "Off Screen" and "On Screen". Create a value to control in the state, lets call it "Y Position". This is the value that will control the Y position of the panel. It will be 120 when the panel is "Off Screen" (i.e. it will be below the screen). Then it will be 0 when the panel is "On Screen", i.e. it will be back at the bottom of the screen.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Finally hook up the outputs `Click` and `Map Moved` signal to change the state between "On Screen" and "Off Screen". Feed back the output "Y Position" to the **Pos Y** of the panel.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now you should be able to move around and click on the map, showing and hiding the panel printing the longitude and latitude.
|
||||
49
library/modules/mapbox/guides/polygon.md
Normal file
49
library/modules/mapbox/guides/polygon.md
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
WIP, would be nice to work with the nodes.
|
||||
|
||||
```js
|
||||
const mapbox = Inputs.MapboxObject;
|
||||
const draw = new MapboxDraw({
|
||||
displayControlsDefault: false,
|
||||
// Select which mapbox-gl-draw control buttons to add to the map.
|
||||
controls: {
|
||||
polygon: true,
|
||||
trash: true
|
||||
},
|
||||
// Set mapbox-gl-draw to draw by default.
|
||||
// The user does not have to click the polygon control button first.
|
||||
defaultMode: 'draw_polygon'
|
||||
});
|
||||
mapbox.addControl(draw);
|
||||
|
||||
|
||||
function updateArea(e) {
|
||||
const geometry = e.features[0].geometry;
|
||||
Outputs.Geometry = JSON.parse(JSON.stringify(geometry));
|
||||
Outputs.Coordinates = geometry.coordinates;
|
||||
|
||||
// const data = draw.getAll();
|
||||
// const answer = document.getElementById('calculated-area') = Outputs.calculatedarea;
|
||||
// if (data.features.length > 0) {
|
||||
// const area = turf.area(data);
|
||||
// // Restrict the area to 2 decimal points.
|
||||
// const rounded_area = Math.round(area * 100) / 100;
|
||||
// answer.innerHTML = `<p><strong>${rounded_area}</strong></p><p>square meters</p>`;
|
||||
// } else {
|
||||
// answer.innerHTML = '';
|
||||
// if (e.type !== 'draw.delete')
|
||||
// alert('Click the map to draw a polygon.');
|
||||
// }
|
||||
}
|
||||
|
||||
mapbox.on('draw.create', updateArea);
|
||||
mapbox.on('draw.delete', updateArea);
|
||||
mapbox.on('draw.update', updateArea);
|
||||
|
||||
// Add keydown event listener to the mapbox container
|
||||
mapbox.getCanvas().addEventListener('keydown', (event) => {
|
||||
if (event.keyCode === 13 || event.keyCode === 3) { // 13 is the keycode for the Enter key
|
||||
draw.changeMode('simple_select');
|
||||
}
|
||||
});
|
||||
```
|
||||
45
library/modules/mapbox/guides/screen-coordinates/README.md
Normal file
45
library/modules/mapbox/guides/screen-coordinates/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Getting Screen Coordinates of Markers
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Getting Screen Coordinates of Markers
|
||||
|
||||
:::caution
|
||||
|
||||
With the new Mapbox module you only need to place your nodes as children to the Mapbox Marker, and they will be visible instead.
|
||||
|
||||
:::
|
||||
|
||||
This snippet is useful if you want to position something, for example a Noodl Component, on top of a Marker on the Mapbox Map.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## How it works
|
||||
|
||||
Create a [Function](/nodes/javascript/function) node and paste in the code below
|
||||
|
||||
```javascript
|
||||
const markers = document.querySelectorAll(".mapboxgl-marker");
|
||||
|
||||
if (!markers) return;
|
||||
|
||||
for (let i = 0; i < markers.length; i++) {
|
||||
let m = markers[i];
|
||||
let markerId = m.getAttribute("data-ndl-marker-id");
|
||||
let rect = m.getBoundingClientRect();
|
||||
|
||||
Noodl.Object.get(markerId).setAll({
|
||||
posX: rect.left,
|
||||
posY: rect.top,
|
||||
});
|
||||
}
|
||||
|
||||
Outputs.done();
|
||||
```
|
||||
|
||||
When calling **Run** on the **Function** node the screen coordinates will be written to the Marker array, in the two properties `posX` and `posY`. After the operation is finished the **Done** output signal will be triggered.
|
||||
58
library/modules/mapbox/guides/screenshot.md
Normal file
58
library/modules/mapbox/guides/screenshot.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Take a screenshot
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Take a screenshot
|
||||
|
||||
Taking a screenshot of the map can be useful in many different scenarios,
|
||||
for example saving navigation, directions, planning, record-keeping, and research purposes.
|
||||
It can help visualize routes, distances, specific locations, and patterns in data.
|
||||
|
||||
:::info
|
||||
|
||||
This will not include Markers, to include Markers we have to take the screenshot in a different way.
|
||||
|
||||
:::
|
||||
|
||||
## Results
|
||||
|
||||
When taking the screenshot we will get an image the same size as the Mapbox element.
|
||||
|
||||
The output will be an image blob which can be passed into an Image node, upload as a file, or saved in the database.
|
||||
|
||||
Example of the screenshot/image data format:
|
||||
```
|
||||
data:image/png;base64,iVBORw0KGgoA...
|
||||
```
|
||||
|
||||
This is what the image looks like:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Steps
|
||||
|
||||
1. Create a Function node, with this code:
|
||||
```js
|
||||
const mapboxObject = Inputs.MapboxObject;
|
||||
if (!mapboxObject) return;
|
||||
|
||||
Outputs.ImageDataUrl = mapboxObject.getCanvas().toDataURL();
|
||||
```
|
||||
|
||||
2. Connect the Mapbox Output, `Mapbox Object` to the Function node.
|
||||
|
||||
3. Connect the `ImageDataUrl` output on the Function node to either an image or where you want to save it.
|
||||
This image can be saved in the database too, but keep in mind that it is not recommended to save a lot of data in a column.
|
||||
|
||||
Here is an example of how it might look in the end:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
66
library/modules/mapbox/guides/setting-up/README.md
Normal file
66
library/modules/mapbox/guides/setting-up/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: Setting up the Mapbox Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Setting up the Mapbox Module
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will show you how to include the Mapbox module in a project and set up an Mapbox API key to use for your application.
|
||||
|
||||
## Overview
|
||||
|
||||
We will go though the following steps:
|
||||
|
||||
- Install the Mapbox Module in a Noodl Project.
|
||||
- Create an Access Token on the Mapbox account
|
||||
- Create a minimal Mapbox App in Noodl
|
||||
|
||||
## Install the Mapbox Module
|
||||
|
||||
When in the project, open the "Module" tab in the Node Picker. Find the "Mapbox" module and click "Install".
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
After the module is imported, you should now be able to find the [Mapbox Map](library/modules/mapbox/nodes/v2/mapbox-map) node in the node picker. Right click in the node editor area to bring up the node picker. Look under "External libraries" to find the **Mapbox Map** node.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Add the node. Then put it as a child to your main App group. As you will see, you will immedieatly get a warning: _"No access token. Please specify one in the Project Settings and reload"_.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
So to use the Mapbox Module you need an access token from Mapbox. You can read more about Access tokens [here](https://docs.mapbox.com/help/getting-started/access-tokens/) and also follow instructions on how to create one. Among other things you will have to set up an account on Mapbox unless you already have one.
|
||||
|
||||
## Entering the Mapbox Access Token
|
||||
|
||||
Once you got the token (which will look like a long password) you open up the "Project Settings" panel by clicking the cogwheel in the main panel to the left. Copy/Paste the token into the field called "Mapbox Access Token"
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Once you've added in the token, reload the viewer, and you should now have a Mapbox map showing in your App, something like below.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You can play a little with the map. Pan and zoom.
|
||||
134
library/modules/mapbox/guides/styles.md
Normal file
134
library/modules/mapbox/guides/styles.md
Normal file
@@ -0,0 +1,134 @@
|
||||
---
|
||||
title: Mapbox Styles
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Mapbox Styles
|
||||
|
||||
Mapbox styles are a collection of rules that define how a map is displayed. They include information about the map's layout, colors, labels, and symbols. Mapbox styles are used to create maps that are visually appealing and easy to read.
|
||||
|
||||
They can be customized to meet the needs of different users and applications, and can be used with Mapbox's suite of mapping tools to create interactive maps for web and mobile applications. Mapbox styles are based on the Mapbox Style Specification, which is an open-source specification for designing and sharing map styles.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Prebuilt Styles
|
||||
|
||||
Mapbox have a few prebuilt styles, here are a few of them:
|
||||
|
||||
- Streets: A classic style that emphasizes roads, parks, and other features of urban areas.
|
||||
- Outdoors: Designed for outdoor enthusiasts, this style includes topographic lines, hiking trails, and other natural features.
|
||||
- Light: A minimalist style that focuses on the essentials of a map, with a light color scheme that's easy on the eyes.
|
||||
- Dark: A more dramatic version of the Light style, with a dark color scheme that's perfect for nighttime maps.
|
||||
- Satellite: This style uses satellite imagery to show real-world views of the Earth's surface, and is often used for mapping remote areas or monitoring changes in the environment.
|
||||
- Navigation: A style optimized for driving and navigation, with a focus on road networks and landmarks.
|
||||
|
||||
You can find them [here](https://docs.mapbox.com/api/maps/styles/#mapbox-styles). Here is the same list with the styles:
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Style | Source |
|
||||
| ----------------- | -------------------------------------------- |
|
||||
| Streets | mapbox://styles/mapbox/streets-v12 |
|
||||
| Outdoors | mapbox://styles/mapbox/outdoors-v12 |
|
||||
| Light | mapbox://styles/mapbox/light-v11 |
|
||||
| Dark | mapbox://styles/mapbox/dark-v11 |
|
||||
| Satellite | mapbox://styles/mapbox/satellite-v9 |
|
||||
| Satellite Streets | mapbox://styles/mapbox/satellite-streets-v12 |
|
||||
| Navigation Day | mapbox://styles/mapbox/navigation-day-v1 |
|
||||
| Navigation Night | mapbox://styles/mapbox/navigation-night-v1 |
|
||||
|
||||
</div>
|
||||
|
||||
## Custom Styles
|
||||
|
||||
You can also use [Mapbox Studio](https://www.mapbox.com/mapbox-studio) to create your own custom styles.
|
||||
|
||||
In Mapbox Studio you will get a link which should be passed into `Style`, and you will have the custom style.
|
||||
|
||||
## Style Object
|
||||
|
||||
Looking at the Mapbox "Add a video" example, which can be [here](https://docs.mapbox.com/mapbox-gl-js/example/video-on-a-map/).
|
||||
|
||||
In this example a Javascript object is used to create the style.
|
||||
|
||||
Here is how we can recreate this example in Noodl.
|
||||
|
||||
1. Create a Function node, with this code:
|
||||
|
||||
```js
|
||||
Outputs.MapStyle = JSON.stringify({
|
||||
version: 8,
|
||||
sources: {
|
||||
satellite: {
|
||||
type: "raster",
|
||||
url: "mapbox://mapbox.satellite",
|
||||
tileSize: 256,
|
||||
},
|
||||
video: {
|
||||
type: "video",
|
||||
urls: [
|
||||
"https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4",
|
||||
"https://static-assets.mapbox.com/mapbox-gl-js/drone.webm",
|
||||
],
|
||||
coordinates: [
|
||||
[-122.51596391201019, 37.56238816766053],
|
||||
[-122.51467645168304, 37.56410183312965],
|
||||
[-122.51309394836426, 37.563391708549425],
|
||||
[-122.51423120498657, 37.56161849366671],
|
||||
],
|
||||
},
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
id: "background",
|
||||
type: "background",
|
||||
paint: {
|
||||
"background-color": "rgb(4,7,14)",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "satellite",
|
||||
type: "raster",
|
||||
source: "satellite",
|
||||
},
|
||||
{
|
||||
id: "video",
|
||||
type: "raster",
|
||||
source: "video",
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
2. Connect the `MapStyle` output to the Mapbox `Style` input. And you will now have the style with a video.
|
||||
|
||||
3. To pause and play the video, like in the example.
|
||||
|
||||
We create another Function node with this code:
|
||||
|
||||
```js
|
||||
const mapboxObject = Inputs.Map;
|
||||
const playOrPause = Inputs.PlayOrPause;
|
||||
|
||||
if (!mapboxObject) return;
|
||||
|
||||
if (playOrPause) {
|
||||
mapboxObject.getSource("video").play();
|
||||
} else {
|
||||
mapboxObject.getSource("video").pause();
|
||||
}
|
||||
```
|
||||
|
||||
And connect it to a Switch node, like in this picture:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
4. Now we have replicated the example by Mapbox.
|
||||
189
library/modules/mapbox/guides/using-markers/README.md
Normal file
189
library/modules/mapbox/guides/using-markers/README.md
Normal file
@@ -0,0 +1,189 @@
|
||||
---
|
||||
title: Using Markers
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Using Markers in the Mapbox Module
|
||||
|
||||
## What you will learn in this guide
|
||||
|
||||
This guide will teach you how to add and remove markers to your Mapbox Map in Noodl.
|
||||
|
||||
## Overview
|
||||
|
||||
This guide will walk you through the following steps
|
||||
|
||||
- Adding markers to the map
|
||||
- Capturing when the user clicks a marker
|
||||
- Removing markers from the map
|
||||
|
||||
The guide will build on the two previous Mapbox guides, [Setting up Mapbox module](/library/modules/mapbox/guides/setting-up) and [Interacting with the Mapbox Module](/library/modules/mapbox/guides/interacting). It's recommended that you read those guides first.
|
||||
|
||||
## Markers
|
||||
|
||||
Markers are used to mark points in the map. They can be anywhere on the map.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
A marker can either be represented by the default icon, or any of the Noodl visual nodes.
|
||||
In this guide we will go with the default icon. The default icon can also have a color of your choice.
|
||||
|
||||
Markers are placed as children to the Mapbox Map node.
|
||||
To change the marker to any of the Noodl visual nodes, just place them as a children in the marker.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
In our case we would like to create the markers dynamically when you click somewhere on the map.
|
||||
To achieve this we will create a new component that can be used in a Repeater.
|
||||
|
||||
Since this component is going to used in a Repeater, lets also create the Component Inputs node with a few parameters.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Next we will create an array that is going to contain the information about each marker.
|
||||
Each [Object](/nodes/data/object/object-node) in the **Array** should be of the format:
|
||||
|
||||
```
|
||||
{
|
||||
"Lat":<the latitude>,
|
||||
"Lon":<the longitude>,
|
||||
"Color":<the color, e.g, "White" or as hex-string "#ffffff". Only used with the default icon.>
|
||||
}
|
||||
```
|
||||
|
||||
So it matches the properties we added in the component.
|
||||
|
||||
First we add an **Array** node. Give it the **id** `Map Markers`.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
This will feed the markers to a Repeater that is using our new marker component, so connect its output **Items** to the **Markers** input on the **Repeater** node.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Now we need to add new **Objects** to the **Array** whenever the user clicks on the map. Add a [Create New Object](/nodes/data/object/create-new-object) node and make sure you can set the three properties `Lon` (Number), `Lat` (Number) and `Color` (String) when you create it.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We want to set the `Lat` and `Lon` to the position the user clicks, so connect the `Latitude` and `Longitude` outputs in the group "Map Clicked" from the Mapbox to the them. We can hard code the color to `Black` for now, so just enter `Black` directly in the properties panel of the **Create New Object** node. Then we connect the **Click** event from the **Mapbox Map** node to the **Do** signal of the **Create New Object** node.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
The newly created **Object** need to be added to the **Array** that holds the markers. So by adding a [Insert Object Into Array](/nodes/data/array/insert-into-array) node, connecting the **Done** signal from the **Create new Object Node** to **Do** and also connecting the **Id** to **Object Id** we are almost done. We just need to make sure the insert happens in the correct **Array**. So either hardcode the **Array Id** to `Map Markers`, or connect the **Id** of the **Array** to the **Array Id** of the **Insert Object Into Array** node.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
If everything was done correctly, you should now be able to place black markers on the map.
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Capturing when the user clicks a marker
|
||||
|
||||
Next step is to be able to do something when the user clicks a marker. So we need to differentiate between clicking on the map and clicking on a marker.
|
||||
|
||||
Conveniently there is an additional outgoing signal on the **Mapbox Marker** node called **Click**.
|
||||
Lets connect the click signal to Component Outputs so we can use it in our main component.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
So let's change up the logic slightly, so the panel either shows the marker that was clicked, or the newly created marker if the user didn't click the marker but on the map instead.
|
||||
|
||||
Using [Variable](/nodes/data/variable/variable-node) and [Set Variable](/nodes/data/variable/set-variable) node and some logic around that, we make sure a **Variable** holds the current marker. See the [guide](/docs/guides/data/variables) on using **Variables** if you want to know more about how to use them.
|
||||
Also, the **Marker Click** signal now makes the panel visible as well. The full node design can be seen below.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Finally, let's update the panel logic. We want to make sure the latitude/longitude values comes from the marker and not from where you clicked on the map. It won't make a difference now, but we might want to capture more information in the marker to show in the panel, so this is a better design.
|
||||
|
||||
The `Current Marker` Variable holds the **Id** of the current marker, so just connect it to an **Object** and take out the `Lon` and `Lat` properties from it. The updated design is shown below.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Removing Markers
|
||||
|
||||
Finally we want to be able to remove markers. It's very easy, just remove them from the Marker **Array**.
|
||||
So let's add a [Button](/nodes/ui-controls/button) to the panel. Remove its label and instead add an icon that represents "delete". Also make it smaller by adapting its padding and size. Finally make it red so it's clear it's a destructive action.
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background s">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
We connect the functionality for the button. We add a [Remove Object From Array](/nodes/data/array/remove-from-array) node and make sure the **Object Id** is what's stored in the `Current Marker` **Variable** and the **Array Id** comes the same **Id** as the `Map Markers` **Array**.
|
||||
|
||||
The **Click** signal from the **Button** is connected to **Do** on the **Remove Object From Array** node. Finally we also close the panel when the removal is **Done**.
|
||||
|
||||
This is what the final node construct looks like. If you want to import the final project click the "Import" button:
|
||||
70
library/modules/mapbox/nodes/v1/mapbox-map.md
Normal file
70
library/modules/mapbox/nodes/v1/mapbox-map.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Mapbox Map
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Mapbox Map
|
||||
|
||||
This node adds a map to the visual tree, using [Mapbox](https://www.mapbox.com/). The map can be both interactive and static.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Markers can be placed on the map by sending an <span className="ndl-data">array</span> of marker <span className="ndl-data">objects</span> containing `Lat`, `Lon` and `Color` to the <span className="ndl-data">Markers</span> input. `Color` can be specified as a string, (e.g. "White") or as a hex string (e.g. "#ffffff").
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Longitude</span> | Sets the current active longitude. |
|
||||
| <span className="ndl-data">Latitude</span> | Sets the current active latitude. |
|
||||
| <span className="ndl-data">Zoom</span> | Sets the zoom level of the map. |
|
||||
| <span className="ndl-data">Markers</span> | An array of markers on the map. Every marker is defined as an object containing the properties `Lat`, `Lon `, and `Color`. |
|
||||
| <span className="ndl-data">Type</span> | Specifies the Marker type. Can be either `Default` or `Image` |
|
||||
| <span className="ndl-data">Source</span> | Specifies the source of the Marker image. Only available if the Marker is om `Image` type. |
|
||||
| <span className="ndl-data">Width</span> | Specifies the width of the Marker image (in pixels). Only available if the Marker is om `Image` type. |
|
||||
| <span className="ndl-data">Height</span> | Specifies the height of the Marker image (in pixels). Only available if the Marker is om `Image` type. |
|
||||
| <span className="ndl-data">Anchor</span> | Specifies the the anchor point of the Marker image in relation to the location on the map. Only available if the Marker is om `Image` type. |
|
||||
| <span className="ndl-data">Interactive</span> | Sets if users can interact with the map or not. |
|
||||
| <span className="ndl-data">Style</span> | A path to a [Mapbox Style](https://docs.mapbox.com/api/maps/styles/). |
|
||||
|
||||
| Signal | Description |
|
||||
| -------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| <span className="ndl-signal">Center on user</span> | Send a signal to this port to center the map to the current active latitude and longitude. |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| <span className="ndl-data">(Coordinates) Longitude</span> | The current active longitude. |
|
||||
| <span className="ndl-data">(Coordinates) Latitude</span> | The current active latitude. |
|
||||
| <span className="ndl-data">Zoom</span> | The current zoom level of the map. |
|
||||
| <span className="ndl-data">(Map Clicked) Longitude</span> | The longitude that where the user clicked last. To be used with the Click signal. |
|
||||
| <span className="ndl-data">(Map Clicked) Latitude</span> | The latitude that where the user clicked last. o be used with the Click signal. |
|
||||
| <span className="ndl-data">Marker Id</span> | If you have clicked a marker on the map, this port will send the `Id` of the clicked marker. |
|
||||
| <span className="ndl-data">Width</span> | The with of the map container. |
|
||||
| <span className="ndl-data">Height</span> | The height of the map container. |
|
||||
| <span className="ndl-data">Screen Position X</span> | The amount of pixels between the left side of the window and the left side of the map container. |
|
||||
| <span className="ndl-data">Screen Position Y</span> | The amount of pixels between the top of the window and the top side of the map container. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Click</span> | Sends a signal when the map is clicked. |
|
||||
| <span className="ndl-signal">Marker Click</span> | Sends a signal when a marker is cliked. |
|
||||
| <span className="ndl-signal">Map Loaded</span> | Sends a signal when the map has finished loading, after it has been mounted in the app. |
|
||||
| <span className="ndl-signal">Map Moved</span> | Sends a signal after the map in view has been moved. |
|
||||
| <span className="ndl-signal">Did Mount</span> | Sends a signal when the map has been rendered in the app, before the map has been loaded. |
|
||||
| <span className="ndl-signal">Will Unmount</span> | Sends a signal before the map will be removed from the visual tree. |
|
||||
149
library/modules/mapbox/nodes/v2/mapbox-map.md
Normal file
149
library/modules/mapbox/nodes/v2/mapbox-map.md
Normal file
@@ -0,0 +1,149 @@
|
||||
---
|
||||
title: Mapbox Map
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Mapbox Map
|
||||
|
||||
This node adds a map to the visual tree, using [Mapbox](https://www.mapbox.com/). The map can be both interactive and static.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
#### Options
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------- | --------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Style</span> | A path to a [Mapbox Style](https://docs.mapbox.com/api/maps/styles/). |
|
||||
|
||||
#### Other
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | --------------------------------- |
|
||||
| <span className="ndl-data">Interactive</span> | Enable / Disable any interactions |
|
||||
| <span className="ndl-data">Anti-alias</span> | Enable anti-alias |
|
||||
|
||||
#### Coordinates
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------- | ---------------------------------- |
|
||||
| <span className="ndl-data">Longitude</span> | Sets the current active longitude. |
|
||||
| <span className="ndl-data">Latitude</span> | Sets the current active latitude. |
|
||||
| <span className="ndl-data">Zoom</span> | Sets the current active zoom. |
|
||||
| <span className="ndl-data">Bearing</span> | Sets the current active bearing. |
|
||||
|
||||
#### Geolocate
|
||||
|
||||
| Signal | Description |
|
||||
| -------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Center on user</span> | Center the map on the user location, this only works with Geolocate enabled. |
|
||||
|
||||
#### Controls - Fullscreen
|
||||
|
||||
| Data | Description |
|
||||
| ----------------------------------------------------- | ------------------------------ |
|
||||
| <span className="ndl-data">Enable Fullscreen</span> | Enable the fullscreen control. |
|
||||
| <span className="ndl-data">Fullscreen Position</span> | Change the control position. |
|
||||
|
||||
#### Controls - Geocoder
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------- | -------------------------------------------- |
|
||||
| <span className="ndl-data">Enable Geocoder</span> | Enable the Geocoder control. |
|
||||
| <span className="ndl-data">Geocoder Position</span> | Change the control position. |
|
||||
| <span className="ndl-data">Placeholder</span> | Sets the placeholder in the search field. |
|
||||
| <span className="ndl-data">Show Marker</span> | Show a marker of the search result location. |
|
||||
|
||||
#### Controls - Geolocate
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------------------ | ---------------------------------------------- |
|
||||
| <span className="ndl-data">Enable Geolocate</span> | Enable the Geolocate control. |
|
||||
| <span className="ndl-data">Geolocate Position</span> | Change the control position. |
|
||||
| <span className="ndl-data">Show Accuracy Circle</span> | Show the accuracy circle of the user position. |
|
||||
| <span className="ndl-data">Show User Heading</span> | Show the user heading. |
|
||||
| <span className="ndl-data">Show User Location</span> | Show user location. |
|
||||
| <span className="ndl-data">Track User Location</span> | Track the user location. |
|
||||
|
||||
#### Controls - Navigation
|
||||
|
||||
| Data | Description |
|
||||
| ----------------------------------------------------- | ----------------------------------------------- |
|
||||
| <span className="ndl-data">Enable Navigation</span> | Enable the Navigation control. |
|
||||
| <span className="ndl-data">Navigation Position</span> | Change the control position. |
|
||||
| <span className="ndl-data">Show Compass</span> | Show the compass button in the control. |
|
||||
| <span className="ndl-data">Show Zoom</span> | Show the plus and minus buttons in the control. |
|
||||
| <span className="ndl-data">Visualize Pitch</span> | Visualize the pitch in the compass. |
|
||||
|
||||
#### Controls - Scale
|
||||
|
||||
| Data | Description |
|
||||
| ------------------------------------------------ | ----------------------------------------- |
|
||||
| <span className="ndl-data">Enable Scale</span> | Enable the Scale control. |
|
||||
| <span className="ndl-data">Scale Position</span> | Change the control position. |
|
||||
| <span className="ndl-data">Max Width</span> | Sets the max width of the control. |
|
||||
| <span className="ndl-data">Unit</span> | Sets the unit the control should display. |
|
||||
|
||||
#### Controls - Mapbox Draw
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------------- | ------------------------------- |
|
||||
| <span className="ndl-data">Enable Mapbox Draw</span> | Enable the Mapbox Draw control. |
|
||||
| <span className="ndl-data">Mapbox Draw Position</span> | Change the control position. |
|
||||
| <span className="ndl-data">Enable Draw Keybindings</span> | Enable Keybindings. |
|
||||
| <span className="ndl-data">Enable Draw Touch</span> | Enable Touch inputs. |
|
||||
| <span className="ndl-data">Enable Draw Box Select</span> | Enable Box Select. |
|
||||
| <span className="ndl-data">Display Draw Controls</span> | Show the Mapbox Draw controls. |
|
||||
|
||||
#### Controls - Mapbox Draw - Controls
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------- | ----------------------------------- |
|
||||
| <span className="ndl-data">Points</span> | Show the point button. |
|
||||
| <span className="ndl-data">Line String</span> | Show the line string button. |
|
||||
| <span className="ndl-data">Polygon</span> | Show the polygon button. |
|
||||
| <span className="ndl-data">Trash</span> | Show the trash button. |
|
||||
| <span className="ndl-data">Combine Features</span> | Show the combine features button. |
|
||||
| <span className="ndl-data">Uncombine Features</span> | Show the uncombine features button. |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| <span className="ndl-data">(Coordinates) Longitude</span> | The current active longitude. |
|
||||
| <span className="ndl-data">(Coordinates) Latitude</span> | The current active latitude. |
|
||||
| <span className="ndl-data">(Coordinates) Zoom</span> | The current zoom level of the map |
|
||||
| <span className="ndl-data">(Coordinates) Bearing</span> | The current active bearing. |
|
||||
| <span className="ndl-data">(Map Clicked) Longitude</span> | The longitude that where the user clicked last. To be used with the Click signal. |
|
||||
| <span className="ndl-data">(Map Clicked) Latitude</span> | The latitude that where the user clicked last. o be used with the Click signal. |
|
||||
| <span className="ndl-data">Width</span> | The with of the map container. |
|
||||
| <span className="ndl-data">Height</span> | The height of the map container. |
|
||||
| <span className="ndl-data">Screen Position X</span> | The amount of pixels between the left side of the window and the left side of the map container. |
|
||||
| <span className="ndl-data">Screen Position Y</span> | The amount of pixels between the top of the window and the top side of the map container. |
|
||||
| <span className="ndl-data">Mapbox Object</span> | Get the Mapbox object. |
|
||||
| <span className="ndl-data">Mapbox Draw Object</span> | Get the Mapbox Draw object. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Click</span> | Sends a signal when the map is clicked. |
|
||||
| <span className="ndl-signal">Map Loaded</span> | Sends a signal when the map has finished loading, after it has been mounted in the app. |
|
||||
| <span className="ndl-signal">Map Moved</span> | Sends a signal after the map in view has been moved. |
|
||||
| <span className="ndl-signal">Did Mount</span> | Sends a signal when the map has been rendered in the app, before the map has been loaded. |
|
||||
| <span className="ndl-signal">Will Unmount</span> | Sends a signal before the map will be removed from the visual tree. |
|
||||
|
||||
</div>
|
||||
62
library/modules/mapbox/nodes/v2/mapbox-marker.md
Normal file
62
library/modules/mapbox/nodes/v2/mapbox-marker.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: Mapbox Marker
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Mapbox Marker
|
||||
|
||||
This node should be placed as a child in the Mapbox Map node, it can be used in a repeater.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Color</span> | Sets the color of the marker. |
|
||||
| <span className="ndl-data">z-Index</span> | Sets the z-Index of the marker. |
|
||||
| <span className="ndl-data">Draggable</span> | Make the marker draggable. |
|
||||
| <span className="ndl-data">Rotation</span> | Sets the rotation of the marker. |
|
||||
| <span className="ndl-data">Rotation Alignment</span> | Sets the rotation alignment marker. |
|
||||
| <span className="ndl-data">Pitch Alignment</span> | Sets the pitch alignment marker. |
|
||||
| <span className="ndl-data">Offset X</span> | Sets the marker x offset. |
|
||||
| <span className="ndl-data">Offset Y</span> | Sets the marker y offset. |
|
||||
| <span className="ndl-data">Longitude</span> | Sets the current active longitude. |
|
||||
| <span className="ndl-data">Latitude</span> | Sets the current active latitude. |
|
||||
| <span className="ndl-data">Tooltip</span> | Add a custom tooltip using the Mapbox tooltips, this will oonly work on the default markers. |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| <span className="ndl-data">Longitude</span> | The current active longitude. |
|
||||
| <span className="ndl-data">Latitude</span> | The current active latitude. |
|
||||
| <span className="ndl-data">Width</span> | The width of the marker container. |
|
||||
| <span className="ndl-data">Height</span> | The height of the marker container. |
|
||||
| <span className="ndl-data">Screen Position X</span> | The amount of pixels between the left side of the window and the left side of the map container. |
|
||||
| <span className="ndl-data">Screen Position Y</span> | The amount of pixels between the top of the window and the top side of the map container. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------------ | ----------------------------------------------------- |
|
||||
| <span className="ndl-signal">Click</span> | Sends a signal when the user clicks on the marker. |
|
||||
| <span className="ndl-signal">Drag Start</span> | Sends a signal when marker is starting to be dragged. |
|
||||
| <span className="ndl-signal">Drag</span> | Sends a signal when marker is being dragged. |
|
||||
| <span className="ndl-signal">Drag End</span> | Sends a signal when marker is dragged ended. |
|
||||
| <span className="ndl-signal">Did Mount</span> | Sends a signal when the marker have been loaded. |
|
||||
| <span className="ndl-signal">Will Unmount</span> | Sends a signal when the marker is unloaded. |
|
||||
|
||||
</div>
|
||||
68
library/modules/mapbox/nodes/v2/mapbox-polygon.md
Normal file
68
library/modules/mapbox/nodes/v2/mapbox-polygon.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Mapbox Polygon
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Mapbox Polygon
|
||||
|
||||
This node should be placed as a child in the Mapbox Map node, it can be used in a repeater.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Here is the code that is inside the "Get Polygon" Function node:
|
||||
|
||||
```js
|
||||
Outputs.Coordinates = [
|
||||
[
|
||||
[-118.446802, 34.061877],
|
||||
[-118.456802, 34.061877],
|
||||
[-118.456802, 34.051877],
|
||||
[-118.446802, 34.051877],
|
||||
[-118.446802, 34.061877],
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| --------------------------------------------- | ---------------------------------- |
|
||||
| <span className="ndl-data">Coordinates</span> | Sets the current coordinates. |
|
||||
| <span className="ndl-data">Enabled</span> | Enable / Disable user interaction. |
|
||||
|
||||
| Signal | Description |
|
||||
| ---------------------------------------- | --------------------------------------- |
|
||||
| <span className="ndl-signal">Edit</span> | Send a signal to start polygon editing. |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------- | ------------------------------- |
|
||||
| <span className="ndl-data">Mapbox Object</span> | The mapbox object. |
|
||||
| <span className="ndl-data">Mapbox Draw Object</span> | The mapbox draw object. |
|
||||
| <span className="ndl-data">Feature Id</span> | The feature id. |
|
||||
| <span className="ndl-data">Coordinates</span> | The coordinates of the polygon. |
|
||||
|
||||
| Signal | Description |
|
||||
| ------------------------------------------------ | ---------------------------------------------------- |
|
||||
| <span className="ndl-signal">Updated</span> | Sends a signal when the polygon is getting updated. |
|
||||
| <span className="ndl-signal">Selected</span> | Sends a signal when the polygon is getting selected. |
|
||||
| <span className="ndl-signal">Unselected</span> | Sends a signal when the polygon is unselected. |
|
||||
| <span className="ndl-signal">Did Mount</span> | Sends a signal when the polygon is loaded. |
|
||||
| <span className="ndl-signal">Will Unmount</span> | Sends a signal when the polygon is unloaded. |
|
||||
|
||||
</div>
|
||||
20
library/modules/mapbox/release-notes.md
Normal file
20
library/modules/mapbox/release-notes.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: Release Notes
|
||||
hide_title: true
|
||||
---
|
||||
# Release Notes
|
||||
|
||||
Version 2.0 [2023-03-01]
|
||||
* Support for Fullscreen Control
|
||||
* Support for Geocoder Control
|
||||
* Support for Navigation Control
|
||||
* Support for Scale Control
|
||||
* Support for Mapbox Draw
|
||||
- Added Mapbox Polygon node, draw a polygon on the map
|
||||
- Added API to listen for newly created polygons via the Mapbox Control
|
||||
* Improved support for markers and custom markers
|
||||
- Added Mapbox Marker node, when placed as a child inside the Mapbox Map it will become a marker on the map
|
||||
|
||||
Version 1.0 [2022-01-14]
|
||||
* Support for basic interactions, such as clicking and moving the map
|
||||
* Support for markers
|
||||
97
library/modules/markdown/README.md
Normal file
97
library/modules/markdown/README.md
Normal file
@@ -0,0 +1,97 @@
|
||||
---
|
||||
title: Markdown Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Markdown Module
|
||||
|
||||
Markdown in Noodl is a combination of the **Markdown** and **CSS Definition** nodes. The CSS enables styling of all the individual components of the resulting markdown, like headers, lists, images, links, and so on.
|
||||
|
||||
## Example
|
||||
|
||||
Let's recreate this example.
|
||||
|
||||

|
||||
|
||||
We'll need three nodes. A **Group**, the **Markdown** node, and a **CSS Definition** node.
|
||||
|
||||

|
||||
|
||||
This is the markdown:
|
||||
|
||||
```markdown
|
||||
# H1
|
||||
|
||||
## H2
|
||||
|
||||
### H3
|
||||
|
||||
Emphasis, aka italics, with _asterisks_ or _underscores_.
|
||||
Strong emphasis, aka bold, with **asterisks** or **underscores**.
|
||||
Combined emphasis with **asterisks and _underscores_**.
|
||||
|
||||
1. First ordered list item
|
||||
2. Another item
|
||||
|
||||
- Unordered sub-list.
|
||||
|
||||
1. Actual numbers don't matter, just that it's a number
|
||||
1. Ordered sub-list
|
||||
1. And another item.
|
||||
|
||||
- Unordered list can use asterisks
|
||||
|
||||
* Or minuses
|
||||
|
||||
- Or pluses
|
||||
|
||||
[Link to Google](https://www.google.com)
|
||||
|
||||
Image:
|
||||

|
||||
|
||||
> Blockquote
|
||||
|
||||
Iframe embed:
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/YQBndLl1phI" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
|
||||
```
|
||||
|
||||
To get the HTML to render we need to enable the **Allow HTML** input
|
||||
!()[/modules/markdown/markdown-allow-html.png]
|
||||
|
||||
The styling is done with the **CSS Definition** node. This node allows you to write regular CSS in your Noodl project.
|
||||
|
||||
In this example we'll use the following CSS:
|
||||
|
||||
```css
|
||||
/* Open Sans font added with the help of https://fonts.google.com */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,600;0,700;0,800;1,300;1,400;1,600;1,700;1,800&display=swap');
|
||||
|
||||
.markdown {
|
||||
font-family: 'Open Sans';
|
||||
font-size: 16px; /* default font size*/
|
||||
}
|
||||
|
||||
/* make all h1 blue */
|
||||
.markdown h1 {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
/* style the unordered lists */
|
||||
.markdown ul {
|
||||
list-style-type: circle;
|
||||
/* list-style-image: url('sqpurple.gif'); */ /* you can also use images in the project folder */
|
||||
}
|
||||
|
||||
/* style links */
|
||||
.markdown a {
|
||||
text-decoration: none;
|
||||
}
|
||||
```
|
||||
|
||||
The `.markdown` class is the default class name. This can be changed on the **Markdown** node with the _CSS Class_ input.
|
||||
|
||||
## Beind the scenes
|
||||
|
||||
This module enables you to use [Markdown](https://commonmark.org/help/) in Noodl. It's implemented with [react-markdown](https://github.com/remarkjs/react-markdown) which in turn uses [remark](https://github.com/remarkjs/remark).
|
||||
30
library/modules/markdown/markdown-node.md
Normal file
30
library/modules/markdown/markdown-node.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Markdown
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
# Markdown
|
||||
|
||||
This node enables you to use Markdown in Noodl.
|
||||
|
||||

|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
**CSS Class**
|
||||
The class name that'll be set on a wrapper `<div>` around the resulting HTML output. This is important for styling the Markdown with CSS.
|
||||
|
||||
**Source**
|
||||
The markdown source.
|
||||
|
||||
**Allow HTML**
|
||||
If this is enabled any HTML in the *Source* will be rendered as HTML. Be mindful of security risks if the markdown source originates in some type of end user input.
|
||||
|
||||
**Open links in tab**
|
||||
* `true` Links in the markdown open in a new tab
|
||||
* `false` Links in the markdown open in the same window
|
||||
|
||||
**Mounted**
|
||||
This property is used to completely remove the node from the DOM. If this property is set to false the node is removed from the DOM.
|
||||
47
library/modules/marquee/README.md
Normal file
47
library/modules/marquee/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Marquee Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Marquee
|
||||
|
||||
[](https://github.com/noodlapp/modules/tree/main/modules/marquee)
|
||||
|
||||
This module allows you to add a marquee to your Noodl App using any of the other visual nodes.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
:::tip
|
||||
|
||||
When developing components for the Marquee node, it is advisable to work on the component outside the Marquee node.
|
||||
This is because the Marquee node duplicates HTML elements and ceases to listen for hot-reload when the component is modified.
|
||||
To ensure consistent results, it is recommended to reload the page and observe the current appearance.
|
||||
|
||||
:::
|
||||
|
||||
### Getting started
|
||||
|
||||
After importing this module you will see one new nodes in the node picker called "Marquee" in the external libraries category.
|
||||
|
||||
We can start by placing the Marquee node into our visual tree.
|
||||
All the children placed in this node will be added into the marquee list and duplicated to fill the space.
|
||||
|
||||
For example when we add a Text node inside like this:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Then in the preview we will see this:
|
||||
|
||||
<div className="ndl-image-with-background">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
45
library/modules/marquee/nodes/v1/marquee.md
Normal file
45
library/modules/marquee/nodes/v1/marquee.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Marquee
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
<##head##>
|
||||
|
||||
# Marquee
|
||||
|
||||
This visual node adds a marquee container to the visual tree.
|
||||
|
||||
<div className="ndl-image-with-background l">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
<##head##>
|
||||
|
||||
## Inputs
|
||||
|
||||
<div className="ndl-table-35-65">
|
||||
|
||||
| Data | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-data">Auto Fill</span> | Whether to automatically fill blank space in the marquee with copies of the children or not. |
|
||||
| <span className="ndl-data">Speed</span> | The speed calculated as pixels/second. |
|
||||
| <span className="ndl-data">Delay</span> | The duration to delay the animation after render, in seconds. |
|
||||
| <span className="ndl-data">Loop</span> | The number of times the marquee should loop, 0 is equivalent to infinite. |
|
||||
| <span className="ndl-data">Direction</span> | The direction the marquee is sliding. |
|
||||
| <span className="ndl-data">Gradient Enabled</span> | Whether to show the gradient or not. |
|
||||
| <span className="ndl-data">Gradient Color</span> | The color of the gradient. |
|
||||
| <span className="ndl-data">Gradient Width</span> | The width of the gradient on either side in pixels. |
|
||||
|
||||
| Signal | Description |
|
||||
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <span className="ndl-signal">Pause</span> | Pause the marquee animation. |
|
||||
| <span className="ndl-signal">Play</span> | Play the marquee animation. |
|
||||
| <span className="ndl-signal">Toggle</span> | Toggle the marquee animation state. |
|
||||
|
||||
</div>
|
||||
|
||||
## Outputs
|
||||
|
||||
This node have no unique outputs.
|
||||
9
library/modules/marquee/release-notes.md
Normal file
9
library/modules/marquee/release-notes.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Release Notes
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
Version 1.0.0 [2023-06-13]
|
||||
* Add Marquee node
|
||||
22
library/modules/material-icons/README.md
Normal file
22
library/modules/material-icons/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Material Icons
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Material Icons
|
||||
|
||||
This module contains the latest material icon set. Add it to your project and you will have access to it in all core nodes that support icons. Most notably the [Icon](/nodes/basic-elements/icon) node.
|
||||
|
||||
<div className="ndl-image-with-background xl">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Simply add the module to your project and you will have the latest icon set available to you.
|
||||
|
||||
<div className="ndl-image-with-background xl">
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
605
library/modules/mqtt/README.mdx
Normal file
605
library/modules/mqtt/README.mdx
Normal file
@@ -0,0 +1,605 @@
|
||||
---
|
||||
title: MQTT Module
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import CopyToClipboardButton from '../../../src/components/copytoclipboardbutton'
|
||||
|
||||
# MQTT Module
|
||||
|
||||
This module contains basic nodes for communicating with an MQTT broker. This is for example useful when communicating with multiple devices or when building an IoT project.
|
||||
|
||||
In this guide we will create a small MQTT communication example using the _Send Message_ and _Receive Message_ nodes available in the MQTT module.
|
||||
|
||||
## Overview
|
||||
|
||||
MQTT is a very popular communication protocol between IoT devices. It's based on a simple publisher/subscriber architecture where all messages pass through an MQTT broker, who directs messages from publishers to subscribers. As a subscriber, you subscribe to _topics_, which are typically made up of different subpaths. As a publisher of messages, you publish your messages to these topics. A message can contain a _payload_, i.e. a data object with one or more pieces of data.
|
||||
|
||||
As an example, an IoT thermometer, called "thermometer1", may publish temperature and pressure data to "/thermometer1/thermometer" topic with a payload containing a time, a temperature and a pressure reading.
|
||||
|
||||
MQTT is a very capable protocol and we will only cover parts of it in this guide. You can read more about it [here](https://en.wikipedia.org/wiki/MQTT);
|
||||
|
||||
## Using the the MQTT module
|
||||
|
||||
First, let's create a new project using the minimal "Hello" template. Give the project a name, for example "MQTT Messaging".
|
||||
Since the MQTT nodes are not part of the default node set in Noodl, we need to enable the MQTT module. Find the module tab in the sidebar and add the "MQTT" module.
|
||||
|
||||
Now two more nodes are available in your project, the [**Send Message**](/library/modules/mqtt/send-message) and [**Receive Message**](/library/modules/mqtt/receive-message) nodes.
|
||||
|
||||

|
||||
|
||||
Try adding a **Send Message** and **Receive Message** node to the project, to see that they are now available.
|
||||
|
||||
## Connecting to an MQTT broker
|
||||
|
||||
For the MQTT messaging to work, we need to connect to an MQTT broker. Setting up and hosting a commercial, secure MQTT broker is a bit of a hassle. So for this guide we will instead use the open MQTT broker "Shiftr". It's being hosted in the cloud so we don't need to worry about hosting it. Another good alternative is the open source broker [Mosquitto](https://mosquitto.org/) that you can run locally or host yourself.
|
||||
|
||||
Go to [shiftr.io](http://shiftr.io) and sign up for an account if you don't already have one. Also create a new "Name space" and a "Token" for the namespace. In the end you should have created an MQTT endpoint to use, similar to the one below.
|
||||
|
||||

|
||||
|
||||
Now go into your project settings and paste in the URL (beginning with "mqtt:") into the "Broker URL" field.
|
||||
|
||||

|
||||
|
||||
## Testing our MQTT broker
|
||||
|
||||
Ok, now we have everything to get started to send MQTT messages. Let's try it!
|
||||
|
||||
Start by adding a "Send Message" node. Set its topic to "mytopic" and add a payload called "myvalue".
|
||||
|
||||

|
||||
|
||||
Now let's send our first message to the topic "mytopic". So we assign a value to the input "myvalue", using a **Number** node and connect the _Send_ signal to the click event of the background **Group**. Any value is fine, we just want to see if it's working.
|
||||
|
||||

|
||||
|
||||
When you start clicking the background rectangle, you should now be sending messages to the MQTT broker. If you bring up you web browser with your Shiftr name space topology you should be seeing some events entering the system everytime you click. Again, remember that the MQTT messages are being sent to a router hosted somewhere in the cloud, which means that any device with an internet connection can now connect to your Noodl app, or vice versa, by sending messages to the router.
|
||||
|
||||
<div className="ndl-images">
|
||||
<img
|
||||
src="mqtt-guide-img/mqtt-guide6.gif"
|
||||
className="ndl-image medium"
|
||||
></img>
|
||||
<CopyToClipboardButton
|
||||
json={{
|
||||
nodes: [
|
||||
{
|
||||
id: '3b093066-8241-2d44-8430-07b7e37b6977',
|
||||
type: 'Group',
|
||||
x: 177,
|
||||
y: 141.5,
|
||||
parameters: { backgroundColor: '#FFFFFF' },
|
||||
ports: [],
|
||||
children: [
|
||||
{
|
||||
id: 'ada2b412-3417-a23c-b4c2-86a5dfa1d480',
|
||||
type: 'Text',
|
||||
x: 197,
|
||||
y: 223.5,
|
||||
parameters: {
|
||||
sizeMode: 'contentSize',
|
||||
alignX: 'center',
|
||||
alignY: 'center',
|
||||
text: 'Hello',
|
||||
color: '#171717',
|
||||
fontFamily: 'Arial',
|
||||
position: 'absolute',
|
||||
fontSize: { value: 30, unit: 'px' },
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'f95cf4c6-2ad9-c84b-882d-865d015193c0',
|
||||
type: 'Send Message',
|
||||
x: -30.5,
|
||||
y: 139,
|
||||
parameters: { topic: 'mytopic', payload: 'myvalue' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'fb4aa28a-06fc-6b1b-128c-78cb989e1455',
|
||||
type: 'Number',
|
||||
x: 191.5,
|
||||
y: 298,
|
||||
parameters: { value: 25 },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
connections: [
|
||||
{
|
||||
fromId: '3b093066-8241-2d44-8430-07b7e37b6977',
|
||||
fromProperty: 'onClick',
|
||||
toId: 'f95cf4c6-2ad9-c84b-882d-865d015193c0',
|
||||
toProperty: 'Send',
|
||||
},
|
||||
{
|
||||
fromId: 'fb4aa28a-06fc-6b1b-128c-78cb989e1455',
|
||||
fromProperty: 'savedValue',
|
||||
toId: 'f95cf4c6-2ad9-c84b-882d-865d015193c0',
|
||||
toProperty: 'payload-myvalue',
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
You can inspect the messages in Shiftr and see the payload that's being sent. Also try opening a few browser windows running your simple Noodl app. As you can see, there are now multiple clients in Shiftr that can publish messages to the "mytopic" topic. Each browser window is a publisher in the broker, as well as your Noodl Editor.
|
||||
|
||||

|
||||
|
||||
Now let's change things up slightly as we are going to receive messages as well. We are going to assign each client a random color. When you click the background, that color will be sent out to all subscribers of the topic "mytopic". A circle in the middle of the screen will present any received value.
|
||||
|
||||
The random color is generated using a **Color Blend** node with 5 different base colors. By generating a random number, between 0 and 5, we randomly pick a color on that color scale. Each client will have their own random number and respective color.
|
||||
|
||||
The color is published once the background is clicked, or rather, the random number is published. When you receive a message which will include the random number, that number is translated back to a color through a **Color Blend** node with the same colors as before.
|
||||
|
||||
<div className="ndl-images">
|
||||
<img
|
||||
src="mqtt-guide-img/mqtt-guide8.png"
|
||||
className="ndl-image medium"
|
||||
></img>
|
||||
<CopyToClipboardButton
|
||||
json={{
|
||||
nodes: [
|
||||
{
|
||||
id: '6643149e-ba94-b26f-bc40-80b79bfc01cf',
|
||||
type: 'Group',
|
||||
x: 177,
|
||||
y: 141.5,
|
||||
parameters: { backgroundColor: '#FFFFFF' },
|
||||
ports: [],
|
||||
children: [
|
||||
{
|
||||
id: 'daadd5d9-073e-c3e7-0d4d-f5ec6ddcf190',
|
||||
type: 'Circle',
|
||||
x: 197,
|
||||
y: 243.5,
|
||||
parameters: {
|
||||
size: 200,
|
||||
position: 'absolute',
|
||||
alignY: 'center',
|
||||
alignX: 'center',
|
||||
strokeEnabled: true,
|
||||
strokeWidth: 5,
|
||||
strokeColor: '#FFFFFF',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '6c0a2207-03bd-835f-83a3-834b5a9548eb',
|
||||
type: 'Send Message',
|
||||
x: -39.46794686634766,
|
||||
y: 12.167608604511884,
|
||||
parameters: { topic: 'mytopic', payload: 'myvalue' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '00f5506c-2a41-7c97-d1ec-4c1f17f83542',
|
||||
type: 'Expression',
|
||||
x: 334.05517426052154,
|
||||
y: -157.0598440470801,
|
||||
parameters: { expression: 'random()*5' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '00f617a2-baf5-5e99-e1ac-714af2f765cf',
|
||||
type: 'Receive Message',
|
||||
x: 366.07566421792484,
|
||||
y: 486.0503305263981,
|
||||
parameters: { topic: 'mytopic', payload: 'myvalue' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '9888cd86-341e-cc47-62d0-aa18095daa2a',
|
||||
type: 'Color Blend',
|
||||
x: 399.4325313988179,
|
||||
y: 17.225848316195083,
|
||||
parameters: {
|
||||
'color 0': '#000000',
|
||||
'color 1': '#A7A04A',
|
||||
'color 2': '#E8423A',
|
||||
'color 3': '#C6C6C6',
|
||||
'color 4': '#006394',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'f82c3bf5-127e-6eba-20f1-397c8fd0b114',
|
||||
type: 'Color Blend',
|
||||
x: 387.8845576559488,
|
||||
y: 321.32249021174806,
|
||||
parameters: {
|
||||
'color 0': '#000000',
|
||||
'color 1': '#A7A04A',
|
||||
'color 2': '#E8423A',
|
||||
'color 3': '#C6C6C6',
|
||||
'color 4': '#006394',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
connections: [
|
||||
{
|
||||
fromId: '6643149e-ba94-b26f-bc40-80b79bfc01cf',
|
||||
fromProperty: 'onClick',
|
||||
toId: '6c0a2207-03bd-835f-83a3-834b5a9548eb',
|
||||
toProperty: 'Send',
|
||||
},
|
||||
{
|
||||
fromId: '00f5506c-2a41-7c97-d1ec-4c1f17f83542',
|
||||
fromProperty: 'result',
|
||||
toId: '6c0a2207-03bd-835f-83a3-834b5a9548eb',
|
||||
toProperty: 'payload-myvalue',
|
||||
},
|
||||
{
|
||||
fromId: '00f5506c-2a41-7c97-d1ec-4c1f17f83542',
|
||||
fromProperty: 'result',
|
||||
toId: '9888cd86-341e-cc47-62d0-aa18095daa2a',
|
||||
toProperty: 'blendValue',
|
||||
},
|
||||
{
|
||||
fromId: '9888cd86-341e-cc47-62d0-aa18095daa2a',
|
||||
fromProperty: 'result',
|
||||
toId: '6643149e-ba94-b26f-bc40-80b79bfc01cf',
|
||||
toProperty: 'backgroundColor',
|
||||
},
|
||||
{
|
||||
fromId: '00f617a2-baf5-5e99-e1ac-714af2f765cf',
|
||||
fromProperty: 'payload-myvalue',
|
||||
toId: 'f82c3bf5-127e-6eba-20f1-397c8fd0b114',
|
||||
toProperty: 'blendValue',
|
||||
},
|
||||
{
|
||||
fromId: 'f82c3bf5-127e-6eba-20f1-397c8fd0b114',
|
||||
fromProperty: 'result',
|
||||
toId: 'daadd5d9-073e-c3e7-0d4d-f5ec6ddcf190',
|
||||
toProperty: 'fillColor',
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Let's load a couple of browser windows running your app, and maybe your mobile phone as well, and click around in the different windows. If everything works as expected you should see that the inner circles in all clients will change color to the background you just clicked.
|
||||
|
||||

|
||||
|
||||
## Dynamic Topic names
|
||||
|
||||
We have now published and subscribed to messages on one single topic, basically broadcasting messages to all clients. You may want to identify yourself as a publisher, or be more selective on what messages you subscribe to. So let's divide the clients into five groups. You belong to a specific group (Group_1 - Group_5) depending on a random number (0-0.999... belong to first group, 1-1.999... to second, etc). We use some neat nodes, i.e. [**Expressions**](/nodes/math/expression) and [**String Formats**](/nodes/string-manipulation/string-format) to create the group names and determine which group you belong to.
|
||||
|
||||
Each group gets its own topic which is dynamically created using a _{}_ construct. Note that you have to be a bit careful when naming topics. For example, avoid whitespaces, hence we call the groups "Group_X".
|
||||
|
||||

|
||||
|
||||
There is also a **Receive Message** node that each group uses to subscribe to only its group messages. When they receive a message a **Transiton** node triggers an animation of the opacity of the **Text** node, causing it to flash in the circle.
|
||||
|
||||
{' '}
|
||||
|
||||
<div className="ndl-images">
|
||||
<img
|
||||
src="/modules/mqtt/mqtt-guide-img/mqtt-guide11.png"
|
||||
className="ndl-image large"
|
||||
></img>
|
||||
<CopyToClipboardButton
|
||||
json={{
|
||||
nodes: [
|
||||
{
|
||||
id: 'a961fe46-7861-9cd8-9d32-7eb2cfdccdbc',
|
||||
type: 'Group',
|
||||
x: 177,
|
||||
y: 141.5,
|
||||
parameters: { backgroundColor: '#FFFFFF' },
|
||||
ports: [],
|
||||
children: [
|
||||
{
|
||||
id: '986da408-b8ff-c64c-efd1-2931f14e31e1',
|
||||
type: 'Text',
|
||||
x: 197,
|
||||
y: 243.5,
|
||||
parameters: {
|
||||
sizeMode: 'contentSize',
|
||||
alignX: 'center',
|
||||
fontSize: { value: 20, unit: 'px' },
|
||||
fontFamily: 'Helvetica',
|
||||
color: '#FFFFFF',
|
||||
marginTop: { value: 10, unit: 'px' },
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'd6edd70a-aab6-bfa4-ff82-00878a4db77f',
|
||||
type: 'Circle',
|
||||
x: 197,
|
||||
y: 325.5,
|
||||
parameters: {
|
||||
size: 200,
|
||||
position: 'absolute',
|
||||
alignY: 'center',
|
||||
alignX: 'center',
|
||||
strokeEnabled: true,
|
||||
strokeWidth: 5,
|
||||
strokeColor: '#FFFFFF',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '1d1686ca-4d5f-b37c-6a22-400bffc1e179',
|
||||
type: 'Text',
|
||||
label: 'Text',
|
||||
x: 197,
|
||||
y: 407.5,
|
||||
parameters: {
|
||||
position: 'absolute',
|
||||
sizeMode: 'contentSize',
|
||||
alignX: 'center',
|
||||
alignY: 'center',
|
||||
text: '',
|
||||
fontFamily: 'Helvetica',
|
||||
fontSize: { value: 20, unit: 'px' },
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '3b7e73f7-dfe5-28cb-4d7e-9d0afecc48ad',
|
||||
type: 'Send Message',
|
||||
x: -99.46151025686125,
|
||||
y: 153.3218874905391,
|
||||
parameters: { topic: 'mytopic', payload: 'myvalue' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'b540b1ea-05a8-7977-2373-8904630a69e3',
|
||||
type: 'Expression',
|
||||
x: 258.55835369159354,
|
||||
y: -85.4680314386139,
|
||||
parameters: { expression: 'random()*5' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '0058cac0-940e-9b2a-481d-6cb26d8d2a24',
|
||||
type: 'Receive Message',
|
||||
x: 588.2558620795669,
|
||||
y: 323.1620374217247,
|
||||
parameters: {
|
||||
topic: 'mytopic',
|
||||
payload: 'myvalue',
|
||||
enabled: true,
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'c428146e-5701-dc82-551c-eae4971cd0a1',
|
||||
type: 'Color Blend',
|
||||
x: 399.4325313988179,
|
||||
y: 17.225848316195083,
|
||||
parameters: {
|
||||
'color 0': '#000000',
|
||||
'color 1': '#A7A04A',
|
||||
'color 2': '#E8423A',
|
||||
'color 3': '#C6C6C6',
|
||||
'color 4': '#006394',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '4a2bcae5-d62c-0d79-b6e5-cae995fe6e01',
|
||||
type: 'Color Blend',
|
||||
x: 399.0706330517986,
|
||||
y: 331.88202000987104,
|
||||
parameters: {
|
||||
'color 0': '#000000',
|
||||
'color 1': '#A7A04A',
|
||||
'color 2': '#E8423A',
|
||||
'color 3': '#C6C6C6',
|
||||
'color 4': '#006394',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '5c4cc0ea-720a-e042-9214-28a4fd4e343a',
|
||||
type: 'Receive Message',
|
||||
x: -102.71153493076321,
|
||||
y: 289.6270849236503,
|
||||
parameters: { topic: '{mygroup}/message', payload: 'text' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '25a3bbc9-a0a3-3a1f-d0dc-3120127352a5',
|
||||
type: 'String Selector',
|
||||
x: -107.85891325999646,
|
||||
y: -340.16310128056824,
|
||||
parameters: {
|
||||
'input 0': 'Group_1',
|
||||
'input 1': 'Group_2',
|
||||
'input 2': 'Group_3',
|
||||
'input 3': 'Group_4',
|
||||
'input 4': 'Group_5',
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'b298ebae-1c7a-427d-76ee-5811dd697dd7',
|
||||
type: 'Expression',
|
||||
x: 387.0563061618897,
|
||||
y: -256.65160955180494,
|
||||
parameters: { expression: 'floor(x)' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 'f2ae905b-d3f8-684e-5047-f9e756ba2c83',
|
||||
type: 'Send Message',
|
||||
x: -101.5613422950648,
|
||||
y: -88.57450240625224,
|
||||
parameters: { topic: '{mygroup}/message', payload: 'text' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '3bbebb1a-0fa1-d7dd-0b32-5251c7ee7c0a',
|
||||
type: 'Transition',
|
||||
x: -99.76801957568031,
|
||||
y: 450.15483129178,
|
||||
parameters: {
|
||||
targetValue: 0,
|
||||
'overrideCurrentValue.value': 1,
|
||||
duration: 2000,
|
||||
},
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '3a17439c-2747-cad3-69df-cb71063a8c40',
|
||||
type: 'String Format',
|
||||
x: -418.01393979063266,
|
||||
y: -88.14376143188795,
|
||||
parameters: { format: '{x} rulez!' },
|
||||
ports: [],
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
connections: [
|
||||
{
|
||||
fromId: 'a961fe46-7861-9cd8-9d32-7eb2cfdccdbc',
|
||||
fromProperty: 'onClick',
|
||||
toId: '3b7e73f7-dfe5-28cb-4d7e-9d0afecc48ad',
|
||||
toProperty: 'Send',
|
||||
},
|
||||
{
|
||||
fromId: 'b540b1ea-05a8-7977-2373-8904630a69e3',
|
||||
fromProperty: 'result',
|
||||
toId: '3b7e73f7-dfe5-28cb-4d7e-9d0afecc48ad',
|
||||
toProperty: 'payload-myvalue',
|
||||
},
|
||||
{
|
||||
fromId: 'b540b1ea-05a8-7977-2373-8904630a69e3',
|
||||
fromProperty: 'result',
|
||||
toId: 'c428146e-5701-dc82-551c-eae4971cd0a1',
|
||||
toProperty: 'blendValue',
|
||||
},
|
||||
{
|
||||
fromId: 'c428146e-5701-dc82-551c-eae4971cd0a1',
|
||||
fromProperty: 'result',
|
||||
toId: 'a961fe46-7861-9cd8-9d32-7eb2cfdccdbc',
|
||||
toProperty: 'backgroundColor',
|
||||
},
|
||||
{
|
||||
fromId: '0058cac0-940e-9b2a-481d-6cb26d8d2a24',
|
||||
fromProperty: 'payload-myvalue',
|
||||
toId: '4a2bcae5-d62c-0d79-b6e5-cae995fe6e01',
|
||||
toProperty: 'blendValue',
|
||||
},
|
||||
{
|
||||
fromId: '4a2bcae5-d62c-0d79-b6e5-cae995fe6e01',
|
||||
fromProperty: 'result',
|
||||
toId: 'd6edd70a-aab6-bfa4-ff82-00878a4db77f',
|
||||
toProperty: 'fillColor',
|
||||
},
|
||||
{
|
||||
fromId: '5c4cc0ea-720a-e042-9214-28a4fd4e343a',
|
||||
fromProperty: 'payload-text',
|
||||
toId: '1d1686ca-4d5f-b37c-6a22-400bffc1e179',
|
||||
toProperty: 'text',
|
||||
},
|
||||
{
|
||||
fromId: 'b540b1ea-05a8-7977-2373-8904630a69e3',
|
||||
fromProperty: 'result',
|
||||
toId: 'b298ebae-1c7a-427d-76ee-5811dd697dd7',
|
||||
toProperty: 'x',
|
||||
},
|
||||
{
|
||||
fromId: 'b298ebae-1c7a-427d-76ee-5811dd697dd7',
|
||||
fromProperty: 'result',
|
||||
toId: '25a3bbc9-a0a3-3a1f-d0dc-3120127352a5',
|
||||
toProperty: 'index',
|
||||
},
|
||||
{
|
||||
fromId: '25a3bbc9-a0a3-3a1f-d0dc-3120127352a5',
|
||||
fromProperty: 'currentValue',
|
||||
toId: '986da408-b8ff-c64c-efd1-2931f14e31e1',
|
||||
toProperty: 'text',
|
||||
},
|
||||
{
|
||||
fromId: '25a3bbc9-a0a3-3a1f-d0dc-3120127352a5',
|
||||
fromProperty: 'currentValue',
|
||||
toId: '5c4cc0ea-720a-e042-9214-28a4fd4e343a',
|
||||
toProperty: 'topic-mygroup',
|
||||
},
|
||||
{
|
||||
fromId: '25a3bbc9-a0a3-3a1f-d0dc-3120127352a5',
|
||||
fromProperty: 'currentValue',
|
||||
toId: 'f2ae905b-d3f8-684e-5047-f9e756ba2c83',
|
||||
toProperty: 'topic-mygroup',
|
||||
},
|
||||
{
|
||||
fromId: 'a961fe46-7861-9cd8-9d32-7eb2cfdccdbc',
|
||||
fromProperty: 'onClick',
|
||||
toId: 'f2ae905b-d3f8-684e-5047-f9e756ba2c83',
|
||||
toProperty: 'Send',
|
||||
},
|
||||
{
|
||||
fromId: '3bbebb1a-0fa1-d7dd-0b32-5251c7ee7c0a',
|
||||
fromProperty: 'currentValue',
|
||||
toId: '1d1686ca-4d5f-b37c-6a22-400bffc1e179',
|
||||
toProperty: 'opacity',
|
||||
},
|
||||
{
|
||||
fromId: '5c4cc0ea-720a-e042-9214-28a4fd4e343a',
|
||||
fromProperty: 'messageReceived',
|
||||
toId: '3bbebb1a-0fa1-d7dd-0b32-5251c7ee7c0a',
|
||||
toProperty: 'overrideCurrentValue.do',
|
||||
},
|
||||
{
|
||||
fromId: '25a3bbc9-a0a3-3a1f-d0dc-3120127352a5',
|
||||
fromProperty: 'currentValue',
|
||||
toId: '3a17439c-2747-cad3-69df-cb71063a8c40',
|
||||
toProperty: 'x',
|
||||
},
|
||||
{
|
||||
fromId: '3a17439c-2747-cad3-69df-cb71063a8c40',
|
||||
fromProperty: 'formatted',
|
||||
toId: 'f2ae905b-d3f8-684e-5047-f9e756ba2c83',
|
||||
toProperty: 'payload-text',
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
You can see that the new topics start popping up in the Shiftr topology once you start sending messages between the browser windows.
|
||||
|
||||

|
||||
|
||||
As you click around you in your browser windows you can see that messages are only sent within a group.
|
||||
|
||||

|
||||
|
||||
Now you know how to publish and subscribe to topics and how to connect to an MQTT broker. This can for example be used to connect to an Arduino or a Raspberry Pi, etc, if you want to play with some hardware. Find some software that can connect to an MQTT broker and start publishing and subscribing to messages. Best of luck!
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user