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:
Eric Tuvesson
2023-09-05 12:08:55 +02:00
commit 53f0d6320e
2704 changed files with 76354 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
---
title: Date Picker
hide_title: true
---
# Date Picker
A UI component for picking dates. It works both as a text input where you can type the date, and as a calendar drop down (or using the native date picker on mobile).
<div className="ndl-image-with-background">
![](/library/prefabs/date-picker/date-picker.png)
</div>
On desktop and tablets the text input present a calendar drop down when edited.
<div className="ndl-image-with-background">
![](/library/prefabs/date-picker/date-picker-drop-down.png)
</div>
After importing the module you will see a component called **Date Picker** in your project.
The example below shows how to hook the **Date Picker** up to data in a **Variable**, you can save the value back to the object with the **Set Variable** using the **Changed** signal.
<div className="ndl-image-with-background xl">
![](/library/prefabs/date-picker/date-picker-nodes.png)
</div>
The **Value** input and output have the Javascript **Date** type.

View File

@@ -0,0 +1,33 @@
---
title: Email Verification
hide_title: true
---
# Email Verification
This prefab contains a set of cloud functions that can help you add support for user email verification and a reset password flow by sending the user emails with links containing secret tokens. You can find a more thorough guide [here](/docs/guides/cloud-logic/email-verification).
When you clone the prefab your project will get the following cloud functions:
<div className="ndl-image-with-background l">
![](/library/prefabs/email-verification/email-verification-1.png)
</div>
## Settings
Before you can use the functions you must provide a few configuration parameters. These prefabs use [SendGrid](/library/prefabs/sendgrid) as an email service, to use them you need to sign up and get an account (it's free to test).
Look [here](/docs/guides/cloud-logic/email-verification#settings) for a description of how to prepare the configuration, and check out the [Config](/nodes/data/cloud-data/config) node for more information on config parameters.
## Sign up project template
The best way to learn more about email verification and password reset is to try the **Sign up project template** and read the [guide](/docs/guides/cloud-logic/email-verification)
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/email-verification/signup-template.png)
</div>

View File

@@ -0,0 +1,282 @@
---
title: Filters
hide_title: true
---
# Filters
This prefab can be used to dynamically create filter controls that connect to a [Query Records](/nodes/data/cloud-data/query-records) node.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-1.png)
</div>
This guide will show you how to use the filters prefab and the different controls plus how to connect it to [Query Records](/nodes/data/cloud-data/query-records). To use it, clone the prefab into your project this will create a `Filters` component in your default sheet.
## Basic usage
Below you can see a typical setup with the `Filters` component and a [Query Records](/nodes/data/cloud-data/query-records) together with a [Table](/library/prefabs/table/).
<div className="ndl-image-with-background xl">
![](/library/prefabs/filters/filters-nodes-1.png)
</div>
The `Filters` component have an output aptly named <span class="ndl-data">Filters</span> that has the same format as the [advanced filters](/nodes/data/cloud-data/query-records#advanced-filters). This means that you can connect it directly to a query records if you set it in **Javascript** filter mode and provide the following filter code.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-qr-props-1.png)
</div>
```javascript
where(Inputs.Filter)
```
The value on the <span class="ndl-data">Filters</span> output is a Javascript object with an [advanced filters](/nodes/data/cloud-data/query-records#advanced-filters) matching the expected input on the query records.
<div className="ndl-image-with-background xl">
![](/library/prefabs/filters/filters-filter-output.png)
</div>
When the filter has change a signal will be sent on the <span class="ndl-signal">Filter Changed</span> output. This is useful for triggering a fetch on the datasource you are using. In this example above it's connected to the <span class="ndl-signal">Do</span>
input of the query records node.
## Filter Controls
Now, to replace the default filters you need to edit the `Filters` property (of the `Filters` prefab component, phew lot of filters here...) or connect to the input if you want to dynamically create your filters.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-props-1.png)
</div>
The format for the property is an array where each entry in the array maps to a certain type of filter control. Common for all controls is that they need the following properties:
```javascript
[
{
Name:"xyz", // This is a unique identifier of the filter control
Type:"Range", // The type of filter control, see types below
// ... control sepecific properties
}
]
```
Lets dive into different types of filter controls.
### Slider
The **Slider** filter control can be used to create a filter for a **Number** property.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-slider-1.png)
</div>
To add a **Slider** to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"MinLevel", // A unique name for this filter control
Type:"Slider", // The slider type
Label:"Level", // A label for the slider
Max:5, // Max value
Min:0, // Min Value
Step:1, // The size in value for one "step" of the slider
Property:"Level", // This is the property of the class in query records that you want the filter to apply to
// The test property is the test that will be added to the filters output, this can be any of
// lessThan, lessThanOrEqualTo, greaterThan or greaterThanOrEqualTo
Test:"greaterThanOrEqualTo"
}
]
```
### Range
A **Range** filter control is similar to a slider except it has a start and end interval.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-range-1.png)
</div>
To add a **Range** control to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"MinMaxLevel", // A unique name for this filter control
Type:"Slider", // The slider type
Label:"Level", // A label for the slider
Max:5, // Max value
Min:0, // Min Value
Step:1, // The size in value for one "step" of the slider
Property:"Level", // This is the property of the records in query records that you want the filter to apply to
}
]
```
### Checkbox
The **Checkbox** control can be used to turn a filter test on and off. If the checkbox is checked the specific condition will be added to the filter, if not it will be removed.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-checkbox-1.png)
</div>
To add a **Checkbox** control to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"Remote", // A unique name for this filter control
Type:"Checkbox", // Type for the checkbox
Label:"Only remote workers", // A label shown above the control
Text:"Remote", // This is the text to the right of the checkbox
Property:"Remote", // The property of the records in the query records where the condition should be applied
Test:{equalTo:true} // The condition test, choose any from the advanced query section in query records
}
]
```
### Multi Choice
This control will allow you to filter on a string property of your record by giving a set of options to choose from.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-multi-choice-1.png)
</div>
To add a **Multi Choice** control to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"NameChoice", // A unique name for this filter control
Type:"Multi Choice", // The type for the multi choice
Label:"Show only names", // A label shown above the control
Labels:['Bart','Lisa','Marge','Homer','Maggie'], // The labels for the options (whats shown in the UI)
Options:['bart','lisa','marge','homer','maggie'], // The values that are used for the filter condition, this should match your db
Property:"Name", // The property of the records in the query records where the condition should be applied
}
]
```
### Single Choice
The **Single Choice** filter control allows you to provide a number of different choices where the user can only pick one and for each choice there is a corresponding **Test** that will be added to the filter if that choice is checked.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-single-choice-1.png)
</div>
To add a **Single Choice** control to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"SexSingleChoice", // A unique name for this filter control
Type:"Single Choice", // The type for the single choice
Label:"Pick one", // A label shown above the filter control
Labels:["Any","Female","Male"], // Labels for the different options
Options:["any","female","male"], // The values for the different options, this relates to the tests below
// This is the conditions that are added to the filter corresponding to the particular choice
// if the option is not listed below no condition will be added
Tests:{
"male":{Name:{containedIn:["Homer","Bart"]}},
"female":{Name:{containedIn:["Lisa","Marge","Maggie"]}}
}
},
]
```
### Date Filter
With the **Date Filter** control you can add a date input to your filter controls and the resulting filter can include a condition based on the selected date.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-date-filter-1.png)
</div>
To add a **Date Filter** control to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"MaxDate", // A unique name for this filter control
Type:"Date Filter", // The date filter type
Label:"Hired before", // A label shown above the date filter control
Property:"HireDate", // The property of the records in the query records where the condition should be applied
Test:"lessThan", // The test that makes up the condition for the filter
}
]
```
### Text Search
The **Text Search** filter control create a text input where the user can put a search string. It will create a condition on a given property, that should be a string, that will filter on records containing the text.
<div className="ndl-image-with-background l">
![](/library/prefabs/filters/filters-text-search-1.png)
</div>
To add a **Text Search** control to the filter controls use this entry format in the filters array:
```javascript
[
{
Name:"NameSearch", // A unique name for this filter control
Type:"Text Search", // The text search type
Label:"Filter names", // A label shown above the filter contorl
Property:"Name" // The name of the property on the record that should be searched in
}
]
```
## Filter Values
Sometimes you only need the filter values, this is available on the <span class="ndl-data">Filter Values</span> it is a regular javascript object with the values as properties with the names corresponding to the **Name** property in the filter controls. When the filter values changes a signal will be emitted on the <span class="ndl-signal">Filter Values Changed</span> output.
<div className="ndl-image-with-background xl">
![](/library/prefabs/filters/filters-filter-values.png)
</div>
This is also useful if you want to provide presents for your filters. You can provide them via the <span class="ndl-data">Filter Values</span> input on the `Filters` prefab component using the same format as the output.
## Reset
By setting a property in the **Filter Values** object to `null` the corresponding filter controll will be reset to default and the condition will be removed from the **Filter** output. If you want to reset all filter controls you can send a signal to the input <span class="ndl-signal">Reset</span> on the `Filters` prefab.
<div className="ndl-image-with-background xl">
![](/library/prefabs/filters/filters-reset.png)
</div>

View File

@@ -0,0 +1,282 @@
---
title: Form
hide_title: true
---
import useBaseUrl from '@docusaurus/useBaseUrl'
import CopyToClipboardButton from '/src/components/copytoclipboardbutton'
# Form
A component for creating dynamic forms with validation quickly. Use as is, or as basis to creating your own custom form types.
<div className="ndl-image-with-background l">
![](/library/prefabs/form/form-full.png)
</div>
There are guides on how to build forms using the simple approach, such as the [UI Controls and data](/docs/guides/data/ui-controls-and-data) guide. But this approach has it's limits, specifically if you want to build big forms, it becomes cumbersome, and if you want dynamic forms, that is forms that change with data. This component is a great starting point for building dynamic custom forms quicker.
## Basic usage
Simply dragging/adding the component to you UI will present the default form as shown above. First you need to know how to change which form controls to be shown. This is done by editing the **Controls** array of the **Form** component. This is what the default definition for the form controls looks like:
```javascript
[
{
Type: 'Text Input',
Label: 'Full Name',
Property: 'Name',
},
{
Type: 'Text Input',
Label: 'Password',
Property: 'Password',
InputType: 'password',
},
{
Type: 'Checkbox',
Label: 'Security',
Text: 'Keep me signed in?',
Property: 'KeepSignedIn',
},
];
```
The format is simply an array with an object for each control in the form. A control must have the following object fields:
- **Type** This is the type of form control that should be used, this value corresponds to a subcomponent of the **Form** component. So you can look at the sub components to figure out what type of controls are supported. Also, you can create your own types easily, more on this later.
- **Label** The label to be shown above the form control. You can of course change the appeareance of the controls completely by editing the corresponding sub component.
- **Property** This is important. Each form control will edit one property of the form values object, more on this later, but the property that this control will change is specified here.
Fields besides these ones are specific to the different form control types (you can take a look the different sub components on the **Form** to figure out what each type needs), this will also be important when we create our own types later.
## Default form control types
These are the default form control types in the prefab:
- `Text Input`, also accepts **InputType** which are the same as for the [Text Input](/nodes/ui-controls/text-input) node, as well as **Placeholder**.
- `Text Area`, also accepts **Placeholder**. This is a bigger version of text input.
- `Slider`, also accepts **Min**, **Max** and **Steps** and will produce a number form value.
- `Drop Down`, also accepts an array with strings **Options** and a corresponding array **Labels**. The options array represents the different values that can be picked, and the labels array contains the labels shown in the ui control corresponding to each option value.
- `Date Input`, shows a date picker.
- `Check Box`, also accepts **Text** as an extra label, it will product a boolean form value.
- `Single Choice`, also accepts **Options** and **Labels** as with the dropdown, this shows all options as radio buttons.
- `Multi Choice`, also accepts **Options** and **Labels** as with the dropdown, this shows all options as check boxes.
Below you can read how to create your own form controls to extend this prefab to anything use case your require.
## The Form Values Object
The **Form** does not have outputs for the values inputted, instead it uses an object that it fills with the values of the form controls. This is where the **Propetry** field above comes into play, as it is used to designate the property that particular form control will read from / write to. There are two ways to provide a form value object to the **Form** either you provide an **Id** to an object or record that you want the **Form** to use for values.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-1.png)
</div>
This is typically done if you want to edit an existing object or record. Here is a more complete setup for how to edit a **Record** using the form. A button is added at the bottom to save the result after editing. The **Set Record Properties** should have **Properties to store** set to **All** which will have it store the modified record to the cloud when the button is clicked.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-1-1.png)
</div>
If you don't provide a value to the **Object Id** input an object will be created automatically to host the form values and you can use the output **Object Id** to retrieve it, as shown below. When you edit the **Form** the object will be populated with the values.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-2.png)
</div>
This approach is best used if you are creating a new object. You can use this together with the **Source Object Id** on the **Create New Record** node to easily create a new record from the form, e.g. when a "create" button is clicked.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-2-1.png)
</div>
In both examples above the **Employee** record class is an example, you must make sure to provide correct **Controls** to your form for the type of object or record you are editing or creating. So you have appropriate type of form controls with matching **Property** values.
## Validation
Validating forms are important and can often be a bit tricky to get right, the **Form** component have some of that tricky stuff taken care of you. Your job when validating is simply to validate the form values object and provide an array of errors to the **Form** in the following format:
```javascript
[
...
{
Property:"Name",
Error:"Name is a required field"
},
...
]
```
One way to do this is to add a **Function** node that does the validation of the form values object and provides the **Errors** array as above. The example below:
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-3.png)
</div>
Has the following function for simply checking the **Name** property of the form values object. You could add more checks to this function.
```javascript
const errors = [];
if (Inputs.Name === undefined || Inputs.Name === '')
errors.push({
Property: 'Name',
Error: 'Name is a required field.',
});
Outputs.Errors = errors;
```
If you provide an empty error message it will not show. Also the **Form** keeps track on if the form controls have been touched by the user and does not show the error messsage before the user have attempted to edit.
There is an even better way to do validation of forms using the **Form Validation** module, you can find the documentation for that module [here](/library/modules/validation). In essense the module will give you a new node called **Validate** that can take the **Id** of your form values object and perfom validation on it.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-3-1.png)
</div>
The **Validate** node has a very handy output called **Errors** that provide the errors resulting from the validation (if any) that has the correct format and can be passed directly to the **Form** component. You can read more about exactly how to do validation using the **Validate** node in the [guide](/library/modules/validation) but in essance you provide a schema that the object must adhere to in order to be validate, and error messages if it does not pass. You can edit the schema from the properites of the **Validate** node, here is an example:
```javascript
schema({
Name: string().required('Must provide name.'),
Email: string().required('Must provide email.').email('Not valid email.'),
});
```
This will require both the **Name** and **Email** fields of the form values object, and also make sure that the **Email** property is actually correctly formatted.
When the user hits the **Submit** action, usually a button, you can trigger the **Submit** signal of the form which will make a final check and the emit the **Valid Submit** event if the form is validated.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/form-nodes-3-2.png)
</div>
That is everything you need to perform sophisticated validation of your forms. As with the form controls you can find and modify the **Error** sub component of the **Form** component you imported, if you want a different look or behaviour.
## Custom form controls
There are a couple of default form controls, **Text Input**, **Checkbox**, **Slider**, **Dropdown**, **Date Input**, but as always the power of Noodl is building your own custom components. The **Form** component will function as a framework for you to build your own custom forms.
As you can see the different form types that you can specify in the **Controls** input array via the **Type** property.
```javascript
[
...
{
Type:"Text Input",
Label:"Full Name",
Property:"Name",
},
...
]
```
You can add you own form conrols by simply adding another visual component child to the **Form** component, let's say we want to create a week day picker. We create a component called **Week Day Input** and as a child an **Item** component.
<div className="ndl-image-with-background l">
![](/library/prefabs/form/week-day-comps.png)
</div>
When these components are in place as child components to **Form** you can use them by modifying the **Controls** array.
```javascript
[
...
{
Type:"Text Input",
Label:"Full Name",
Property:"Name",
},
{
Type:'Week Day Input',
Label:'Choose a day of the week',
Property:'WeekDay'
}
...
]
```
All form control components must follow a similar pattern. Let's look at the content of the **Week Day Input** form control.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/week-day-comp-1.png)
</div>
A few important things to cover in this component. First all form controls can use the **Repeater Object** to access properties from the individual objects in the **Controls** array.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/week-day-comp-2.png)
</div>
Once you have added the form control to your **Controls** array and it is visible on screen, you can inspect the repeater object to see what it contains.
- **Value** This is the value for the form control, this will read from the form values object.
- **Label** The label to show for this form control.
- **Error** Any error in validation of the value for this form control will be available here, it's the responsibility of the form control to display the error as it sees fit.
Any other properties are simply copied from the corresponding object in the **Controls** array.
This particular input displays an array with all the week days, generated by the **Function** node.
```javascript
Outputs.Items = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].map((d) => ({
Label: d,
Value: d.toLowerCase(),
}));
```
The current selected week day value is stored in the **Component Object**, when an item is clicked the value for that day is written to the **Component Object** using the **Set Component Object Properties** node.
There is one important thing we left to cover. The **Form** component has a special action that should be used to set the value for a form control. The component is a child of the **Form** component and called **Set Form Value**. It's dragged it into the **Week Day Input** component and connected as follows:
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/week-day-comp-3.png)
</div>
This step is important as it is what actually writes the value of the form control to the form values object.
Below you can see the nodes for the **Item** child component of the **Work Day Input** component, it simply contains a button that is repeated for each day.
<div className="ndl-image-with-background xl">
![](/library/prefabs/form/week-day-comp-4.png)
</div>
It also checks the **SelectedValue** of the parent component (in the function node) and supply a different variant depending on if this instance is selected or not.
```javascript
if (Inputs.SelectedValue === Inputs.Value)
Outputs.Variant = 'Week Day Button Selected';
else Outputs.Variant = 'Week Day Button';
```
Having different variants for different "states" of a UI control like this is a handy pattern because you can always go in and change the variants (colors, transitions, behaviours) without having to modify the code.
Finally the **Value** of this week day item is sent with the **Click** signal from the button.

View File

@@ -0,0 +1,76 @@
---
title: List With Icons
hide_title: true
---
import useBaseUrl from '@docusaurus/useBaseUrl'
import CopyToClipboardButton from '/src/components/copytoclipboardbutton'
# List With Icons
This is a very simple list component that you can use as starting point for building your own custom lists.
<div className="ndl-image-with-background l">
![](/library/prefabs/list-with-icons/list-with-icons.png)
</div>
## Basic usage
You specify the items of the list by editing the **Items** array in the **List With Icons** component. Below is the default value.
```javascript
[
{
// Icons are references to material icons,
// see https://fonts.google.com/icons?selected=Material+Icons
Icon:"account_circle",
Label:"List Item 1"
},
{
Icon:"account_circle",
Label:"List Item 2"
},
{
Icon:"account_circle",
Label:"List Item 3"
}
]
```
- **Icon** This is an icon identifier, you can find a list of all supported icons [here](https://fonts.google.com/icons?selected=Material+Icons).
- **Label** The label that should be shown for the list item.
## Item Clicked
The list has an output signal called **Item Clicked** when an item is clicked, and the output **Item Id** will contain the id of the object corresponding to that item.
<div className="ndl-image-with-background xl">
![](/library/prefabs/list-with-icons/list-with-icons-1.png)
</div>
The function node in the above example contains the following code:
```javascript
const clickedListItem = Noodl.Objects[Inputs.ItemId]
console.log("This item was clicked: " + clickedListItem.Label)
```
## Customizing
Like most UI Components in the library this is a great staring point for building your own lists. The best way is to look at the **Item** sub component of the **List With Icons** component. Here you can see how the **Label** and **Icon** are connected from the **Repeater Object**.
<div className="ndl-image-with-background xl">
![](/library/prefabs/list-with-icons/list-with-icons-2.png)
</div>
It's a starting point to build your own custom list items.

View File

@@ -0,0 +1,30 @@
---
title: Loading Spinner
hide_title: true
---
import useBaseUrl from '@docusaurus/useBaseUrl'
# Loading Spinner
The loading spinner is a useful prefab for when you need to indicate that data is loading or a task is being peformed and you want to prevent accidental input from the user while they are waiting.
It's very easy to use, simply drag the **Loading Spinner** component to your node editor and connect a signal to **Show** when you want to display it and **Hide** when you are done and want it hidden.
<div className="ndl-image-with-background xl">
![](/library/prefabs/loading-spinner/loading-spinner-nodes-1.png)
</div>
Above you can see a typical use case in combination with the **Query Records** node, trigger the **Show** signal when you start the request to the cloud services and then **Hide** when it finishes (remember to capture both successful and failed requests).
<div className="ndl-video">
<video width="100%" autoPlay muted loop src={useBaseUrl("/library/prefabs/loading-spinner/loading-spinner.mp4")}/>
</div>
A feature of the loading spinner is that you can do multiple consecutive **Show** signals and it will keep track of the count and then require the same amount of **Hide** signals to close. This is useful if you have parallel request to the backend and you want to make sure all requests have completed before you hide the spinner.

View File

@@ -0,0 +1,71 @@
---
title: MailGun
hide_title: true
---
# MailGun
This prefab will add a logic component to your cloud functions so you can send emails with [MailGun](https://mailgun.com), it will show up in the **MailGun** folder among your [cloud functions](/docs/guides/cloud-logic/introduction).
<div className="ndl-image-with-background l">
![](/library/prefabs/mailgun/mailgun-1.png)
</div>
## Settings
First you must provide a few settings, this is done in the **Config** part of the **Cloud Dashboard**. Launch your cloud services dashboard (if you don't have a cloud service you need to create and make it active for the project).
<div className="ndl-image-with-background s">
![](/library/prefabs/sendgrid/config-1.png)
</div>
<div className="ndl-image-with-background m">
![](/library/prefabs/sendgrid/config-2.png)
</div>
Then find the **Config** section in the sidebar of your dashboard. You can take a look at the [Config](/nodes/data/cloud-data/config) node for more details on how config parameters work. Create parameters for `MailGunAPIKey`and `MainGunDomainName`as the example below, make sure you make the **Master Key Only** so they are protected in your cloud service.
<div className="ndl-image-with-background xl">
![](/library/prefabs/mailgun/mailgun-2.png)
</div>
## Sending an email
Sending an email is done by adding a **Send Email** logic component to your cloud function and then sending a signal to the **Do** input.
<div className="ndl-image-with-background xl">
![](/library/prefabs/mailgun/mailgun-3.png)
</div>
There are a number of inputs to this node that is good to review:
- `To` This is the email for the recipients on your email.
- `CC` This is the email for the cc on your email.
- `BCC` This is the email for the bcc on your email.
The three above inputs can also accept an array of emails, such as:
```javascript
[
'example@email.com',
'another@email.com'
]
```
- `From` One string containing an email that should be the from email address.
- `Subject` The subject of your email.
- `Text` If you want to send a pure text email provide the content of the email on this input.
- `Html` If you want to send a html emal, provide the content of the email on this input.

View File

@@ -0,0 +1,30 @@
---
title: Media Queries
hide_title: true
---
# Media Queries
This prefab gives you a couple of components that allow you to easily work with media queries and responsive design.
<div className="ndl-image-with-background xl">
![](/library/prefabs/media-query/media-query.png)
</div>
## Included components
- **[Media Query Setup](components/media-query-setup)**: Sets up the global breakpoints. Needs to be placed in your projects home component.
- **[Match Media Query](components/match-media-query/)**: Checks all global media queries and outputs a boolean based on the current active breakpoint.
- **[Match Custom Media Query](components/match-custom-media-query/)**: Checks for a custom one-off media query. Only used for edge-cases outside of the breapoints in **Match Media Query**
- **[Media Query Debugger](components/media-query-debugger/)**: A visual component that renders the name of the currently active breakpoint.
## Quickstart
Place a **Media Query Setup** in your projects home component. Then use **Match Media Query** in every component where you need to check for the currently active breakpoint. **Match Media Query** paris nicely with the [States](/nodes/utilities/logic/states) node, or the [Mounted](/nodes/shared-props/inputs/visual-input-properties#other) property.
> To get the most out of this prefab it is recommended to read the [Responsive Design](/docs/guides/user-interfaces/responsive-design) guide, in addition to the prefab docs.

View File

@@ -0,0 +1,39 @@
---
title: Match Custom Media Query
hide_title: true
---
# Match Custom Media Query
This component is used to check for a custom media query. It is mostly used for one-off edge cases. For general media query usage it is recommended to use the **[Match Media Query](/library/prefabs/media-query/components/match-media-query)** component.
<div className="ndl-image-with-background xl">
![](/library/prefabs/media-query/match-custom.png)
</div>
## Media Query
Here's a few examples of media queries:
- `(max-width: 375px)`. This will match if the screen size is `375px` or smaller, like on an iPhone 8, or iPhone X.
- `(max-width: 768px)`. Typical size to check for tablets.
- `(max-width: 1224px)`. Typical size to check for desktop and laptops.
You can also create more complex media queries that check for multiple sizes, or a range:
- `(min-device-width: 320px) and (max-device-height: 640px)`. This will match any size that's above `320px`, and no larger than `640px`.
## Inputs
| Data | Description |
| --------------------------------------------- | --------------------------------------------- |
| <span className="ndl-data">Media Query</span> | The **Media Query String** you want to detect |
## Outputs
| Signal | Description |
| -------------------------------------------- | ---------------------------------------------------------------------- |
| <span className="ndl-signal">Match</span> | Sends a signal if the **Media Query String** matches the device |
| <span className="ndl-signal">No Match</span> | Sends a signal if the **Media Query String** does not match the device |

View File

@@ -0,0 +1,40 @@
---
title: Match Media Query
hide_title: true
---
# Match Media Query
This component is used to check what breakpoint is currently active. It has one output for every breakpoint that outputs either `true` or `false`.
> Please note that you need to place a **[Media Query Setup](/library/prefabs/media-query/components/media-query-setup)** component in your projects home component for the **Match Media Query** comoponent to work.
<br/>
<div className="ndl-image-with-background xl">
![](/library/prefabs/media-query/media-query.png)
</div>
## Breakpoints
The breakpoints are set in the **[Media Query Setup](/library/prefabs/media-query/components/media-query-setup)** component. If the built in default breakpoints don't fit you, you can change them there.
For edge cases where you need to use a one-off breakpoint, you can use the **[Match Custom Media Query](/library/prefabs/media-query/components/match-custom-media-query)** component.
## Common usage
The most common usecase is to use this node together with a [States](/nodes/utilities/logic/states) node, or the **Mounted** input, as pictured above.
## Outputs
| Data | Description |
| --------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| <span className="ndl-data">Matches Small Mobile</span> | _true_ if the viewport matches the **Small Mobile** breakpoint |
| <span className="ndl-data">Matches Regular Mobile</span> | _true_ if the viewport matches the **Regular Mobile** breakpoint |
| <span className="ndl-data">Matches Tablet</span> | _true_ if the viewport matches the **Tablet** breakpoint |
| <span className="ndl-data">Matches Regular Desktop</span> | _true_ if the viewport matches the **Regular Desktop** breakpoint |
| <span className="ndl-data">Matches Large Desktop</span> | _true_ if the viewport matches the **Large Desktop** breakpoint |
| <span className="ndl-data">Matches All Mobile</span> | _true_ if the viewport matches the **Small Mobile** or **Regular Mobile** breakpoints |
| <span className="ndl-data">Matches All Desktop</span> | _true_ if the viewport matches the **Regular Desktop** or **Large Desktop** breakpoints |

View File

@@ -0,0 +1,20 @@
---
title: Media Query Debugger
hide_title: true
---
# Media Query Debugger
This component shows the name of the currently active media query defined in the **[Media Query Setup](/library/prefabs/media-query/components/media-query-setup)** component.
<div className="ndl-image-with-background xl">
![](/library/prefabs/media-query/fixed-query-debugger.png)
</div>
## Inputs
| Data | Description |
| --------------------------------------------------- | ------------------------------------------------------------------------------------ |
| <span className="ndl-data">Debugger Position</span> | Wether the debugger should render **inline** or be **fixed** in the top right corner |

View File

@@ -0,0 +1,26 @@
---
title: Media Query Setup
hide_title: true
---
# Media Query Setup
This component sets up all media queries for your app. It should be placed in you home component. Your project should only include one **Media Query Setup** node.
<div className="ndl-image-with-background xl">
![](/library/prefabs/media-query/media-query-setup.png)
</div>
## Changing the breakpoints
This component comes with a prediefined set of commonly used breakpoints:
- **Small Mobile**: 400px and smaller
- **Regular Mobile**: 401px to 700px
- **Tablet**: 701px to 1200px
- **Regular Desktop**: 1201px to 1800px
- **Large Desktop**: 1801px and above
If you want to change the recommended defaults, this can be done at the top of the **Register media queries** Script node.

View File

@@ -0,0 +1,56 @@
---
title: Modal
hide_title: true
---
# Modal
This prefab contains a simple confirmation popup modal. You can use it to display a message to your user and request a confirmation on an action.
<div className="ndl-image-with-background l">
![](/library/prefabs/modal/modal-screen.png)
</div>
It's easy to use, simply drag the **Popup Modal** action component to your node editor and connect the **Show popup** input to a signal.
<div className="ndl-image-with-background xl">
![](/library/prefabs/modal/modal-nodes.png)
</div>
There are two **Output** signals that are emitted from the **Popup Modal**, one if the user clicked the confirm (primary) button and one if the user closed the popup or clicked the secondary button.
You can provide the labels for both message and buttons in the properties of the **Popup Modal** component instance.
<div className="ndl-image-with-background xl">
![](/library/prefabs/modal/modal-props.png)
</div>
Often you will want to customize the appearance of the popup or you want to extend it with more functionality. It is good practice to duplicate the **Popup Modal** component and rename it to something descriptive, then you can always clone the prefab again if you need another type of popup. As a child component to the **Popup Modal** you will find another component called **Modal Component**. This component contains the actual visual elements of the popup as well as the animation for showing and hiding it.
The **State** node is used to control the show and hide animation. You can read more about how to use **State** nodes in this [guide](/docs/guides/user-interfaces/states).
<div className="ndl-image-with-background xl">
![](/library/prefabs/modal/modal-nodes-2.png)
</div>
The **Component Inputs** is where the different labels are connected to the visual elements of the popup, and the **Close Popup** node contains the confirm action. You can read more about how popups work in this [guide](/docs/guides/navigation/popups).
<div className="ndl-image-with-background xl">
![](/library/prefabs/modal/modal-nodes-3.png)
</div>

View File

@@ -0,0 +1,28 @@
---
title: Multi Choice With Pills
hide_title: true
---
# Multi Choice With Pills
A simple component for multi choice selection comprising a drop down with all options and the selected options are shown as pills above the drop down.
<div className="ndl-image-with-background">
![](/library/prefabs/multi-choice-with-pills/multi-choice-with-pills.png)
</div>
After importing the module you will see a component called **Multi Choice With Pills** in your project.
The example below shows how to hook the **Multi Choice With Pills** up to data in an **Object**, you can save the value back to the object with the **Set Object Properties** using the **Selection Changed** signal.
<div className="ndl-image-with-background xl">
![](/library/prefabs/multi-choice-with-pills/multi-choice-with-pills-1.png)
</div>
As input it takes three arrays of strings, one containing all possible options, the **Options** input, this is the "value" of the options, it might differ from the labels, i.e. what is shown on screen. This you can specify with the **Labels** array input, it must have the same number of strings in the array, each one corresponding to a value in the **Options** array.
The final array is the **Selection** array, it contains all options that are selection. There is also an output from the component called **Selection** which is updated when the user interacts with the component, the **Selection Changed** event is triggered.

View File

@@ -0,0 +1,28 @@
---
title: Multi Choice
hide_title: true
---
# Multi Choice
A simple component for multi choice selection comprising a group of checkboxes.
<div className="ndl-image-with-background">
![](/library/prefabs/multi-choice/multi-choice.png)
</div>
After importing the module you will see a component called **Multi Choice** in your project.
The example below shows how to hook the **Multi Choice** up to data in an **Object**, you can save the value back to the object with the **Set Object Properties** using the **Selection Changed** signal.
<div className="ndl-image-with-background xl">
![](/library/prefabs/multi-choice/multi-choice-nodes.png)
</div>
As input it takes three arrays of strings, one containing all possible options, the **Options** input, this is the "value" of the options, it might differ from the labels, i.e. what is shown on screen. This you can specify with the **Labels** array input, it must have the same number of strings in the array, each one corresponding to a value in the **Options** array.
The final array is the **Selection** array, it contains all options that are selection. There is also an output from the component called **Selection** which is updated when the user interacts with the component, the **Selection Changed** event is triggered.

View File

@@ -0,0 +1,53 @@
---
title: Form
hide_title: true
---
import useBaseUrl from '@docusaurus/useBaseUrl'
import CopyToClipboardButton from '/src/components/copytoclipboardbutton'
# Navigation Menu
This is a nifty component that creates a navigation menu. Clicking an item will perform a navigation to the specified path and the correct item will be highlighted.
<div className="ndl-image-with-background l">
![](/library/prefabs/navigation-menu/navigation-menu.png)
</div>
## Basic usage
You specify the items of the menu by editing the **Items** array in the **Navigation Menu** component. Below is the default value.
```javascript
[
{
// Icons are references to material icons,
// see https://fonts.google.com/icons?selected=Material+Icons
Icon: 'home',
// The label to be shown on the nav item
Label: 'Home',
// The url to navigate to when clicked
Url: '/home',
// Setting this to true will indicate that this
// item should be selected if there is no path
// or if no other path matches
IsHome: true,
},
{
Icon: 'schedule',
Label: 'Calendar',
Url: '/calendar',
},
];
```
- **Icon** This is an icon identifier, you can find a list of all supported icons [here](https://fonts.google.com/icons?selected=Material+Icons).
- **Label** The label for the menu item.
- **Url** The path that should be navigated to when clicked.
- **IsHome** This specifies if this menu item is the "home" item. It will be shown as selected of there is no path or none of the others match the current path.

View File

@@ -0,0 +1,129 @@
---
title: OAuth2
hide_title: true
---
# OAuth2
**OAuth2** is a standard that allows, among other things, web applications to authorize (log in) users from external services like Facebook, Twitter, Microsoft or Google. This can make the sign up flow faster and you don't have to create a new user by signing up with your email and password. It can also be considered more secure as you as the application developer don't need to manage your users password.
This prefab provide a few simple cloud functions to get started, they will enable you to sign in users from other services that provide OAuth2 support, more specifically using something called **Authorization Code Flow**. It's done in a few steps and we will try to cover these steps below.
## Registering your app
The first step in this process is to register your application with the external auth service provider, this works slighly different but should give the same result in the end. In this guide we will use [Spotify](https://developer.spotify.com/dashboard) as an example, you can review the details of how the flow works [here](https://developer.spotify.com/documentation/general/guides/authorization/code-flow/). To follow along, first sign in to the developer dashboard and register your application.
<div className="ndl-image-with-background m">
![](/library/prefabs/oauth2/oauth2-1.png)
</div>
When you get to the dashboard of your application your should first look for the **Client ID** and **Client Secret**.
<div className="ndl-image-with-background l">
![](/library/prefabs/oauth2/oauth2-2.png)
</div>
- **Client ID** This is an identifier of your application towards the auhtorization provider.
- **Client Secret** This is a secret token that you should not share with your users, it must be kept on the backend, only use it in cloud functions.
With these to in hand you need to register a redirect url for your application this, for your spotify app this is done in the settings popup, click **Edit Settings**.
<div className="ndl-image-with-background l">
![](/library/prefabs/oauth2/oauth2-3.png)
</div>
- **Redirect Uri** This is URI to your application that the authorization provider will send the user to when the authorization (log in) is complete. So this needs to be a page in your application that will receive a special authorization code that is needed to complete the flow. For testing it's generally a good idea to user `http://localhost:8574/oauth` but once you deploy your application you need to use the domain you deploy to. Often you can whitelist many callbacks in your app.
You also need to retrieve three important HTTP endpoints from the authorization provider. An example of how to find the for Microsoft Azure is [here](https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints).
## Authorization
The first step is to perform the user authorization, for this we need to update the settings of the prefab you just cloned. When added to the project you will have two new cloud functions and some logic components. You should start by opening the **Settings** component.
<div className="ndl-image-with-background l">
![](/library/prefabs/oauth2/oauth2-cloud-functions.png)
</div>
In the **Settings** component first update these settings with the values you retrieved when registering the app. Use the testing `http://localhost:8574/oauth` redirect uri for now.
<div className="ndl-image-with-background m">
![](/library/prefabs/oauth2/oauth2-settings-1.png)
</div>
There are two more things we need as you can see and that is the authorization endpoint and scope.
- **Auhtorization Endpoint** This is where your application will redirect the user to sign in, they will click a button in your application and then be sent to e.g. Microsoft, Google or Spotify (or whichever auth provider you use) to sign in.
- **Scope** This tells the auth provider what functions and data our applications needs access to so the user can give their permission. It's different for each auth provider so you need to refer to the documentation for the provider you are using, for the sign in to work we only need access to the user profile. For spotify the scope is `user-read-email`.
These can sometimes be tricky to find for your service, looking at the guide [here](https://developer.spotify.com/documentation/general/guides/authorization/code-flow/) for instance we can find the authorization endpoint for the spotify auth service.
`https://accounts.spotify.com/authorize`
This is what you need to put in that last settings **String** node. Now we can start the log in process from the UI of our application. Let's say that we have a button called **Log In With Spotify**, when that button is clicked we should call the **OAuth2/Authorize** cloud function, it will return a URI that we should redirect the user to. We can do this with the **External Link** node.
<div className="ndl-image-with-background xl">
![](/library/prefabs/oauth2/oauth2-sign-in-button.png)
</div>
This will take the user to the log in screen of the auth provider, and when the user have signed in successfully the auth provider will redirect back to our application using the specified redirect uri that we put in the **Settings** component.
## Signing in
So if you put e.g. `http://localhost:8574/oauth` for testing, then you need to create a new page with the url slug **oauth** to receive the result. This page will get one very important **Page Input** and that is a query parameter called **Code**, this is an authorazation code we get with a successful sign in that we can use to log the user in to your app. When you install the prefab you will also get a logic component on the frontend called **Log In**.
<div className="ndl-image-with-background l">
![](/library/prefabs/oauth2/oauth2-log-in.png)
</div>
Here is an example of a **oauth** page that uses the **Log In** component to complete the log in flow using the **Code** from the **Page Inputs**. If it's successful you can navigate to some page in your app and the user will be logged in. If unsuccessful you should show some sort of message.
<div className="ndl-image-with-background xl">
![](/library/prefabs/oauth2/oauth2-oauth-page.png)
</div>
To complete this step we need another three settings in the **Settings** component for the cloud functions. The first one is the token endpoint.
- **Token Endpoint** Once the user successfully signs in, the auth provider will send them back to your application to the **Redirect Uri** that you provided above with a secret authorization code, the cloud functions will then use that to sign in the user via this endpoint.
Again you need to refer to the documentation of your auth provide to find the token, for spotify we can again find it at the bottom of this [page](https://developer.spotify.com/documentation/general/guides/authorization/code-flow/).
`https://accounts.spotify.com/api/token`
The next thing needed is to get some data on the user, namely the email of the user, so we can match it with a Noodl user in your database (or create a new one if needed). For that you first need the user endpoint.
- **User Endpoint** Once signed in, this endpoint is used to get information on the user such as the email of the user which is needed to complete the sign in with Noodl.
For spotify we can find it [here](https://developer.spotify.com/documentation/web-api/reference/#/operations/get-current-users-profile).
`https://api.spotify.com/v1/me`
Calling this endpoint with the correct credentials will return an object describing the user, we are looking for the field containg the email of the user and looking at the documentation above we can see the it is simply named **email**. The **Token Endpoing**, **User Endpoint** and the name of the **Email Field** need to be added to the **Settings** component before the flow can be completed.
<div className="ndl-image-with-background m">
![](/library/prefabs/oauth2/oauth2-settings-2.png)
</div>
That's it. With this flow in place you can sign in users with an external auth provider. A normal user will be created in your database or if a user already exists with the same email that user will be logged into.

View File

@@ -0,0 +1,169 @@
---
title: OpenAI
hide_title: true
---
import CopyToClipboardButton from '/src/components/copytoclipboardbutton'
# OpenAI
:::note
This prefab only works on Noodl hosted cloud services.
:::
The [OpenAI](https://openai.com) prefab is a great starting point for creating your own chat bots based on the ChatGPT API. This prefab includes a few cloud functions and logic components that can get you started quickly. Here is a quick guide on how to use the prefab to build a very simple chat bot.
To be able to follow this guide properly we recommend that you are well versed in a few Noodl concepts already.
- **Cloud Data**. You know how to set up cloud services and work with cloud data, start [here](/docs/guides/cloud-data/creating-a-backend).
- **Cloud Functions**, how to create logic that run in the cloud, take a look [here](/docs/guides/cloud-logic/introduction).
Make sure you have a cloud service active for your project. Next you need an account and API key for [OpenAI](https://openai.com).
# Setup
Start by cloning the prefab into your project, you can read more about how prefabs work [here](/docs/guides/user-interfaces/modules). After the prefab is cloned into your project you will see a warning. Don't worry we will sort this out next.
<div className="ndl-image-with-background l">
![](/library/prefabs/openai/warnings.png)
</div>
First you need to find and add the OpenAI API Key to your cloud services backend. Launch the cloud services dashboard for your project and find your way to the **Config** tab, here you will need to create a new config parameter called `OpenAIAPIKey` (case sensitive) where you need to put the **API Key** from your [OpenAI Account](https://platform.openai.com/account/usage). Then create the config in your cloud service, and make sure that access is restricted to **Master Key Only**. This will keep the API key safe in your cloud service.
<div className="ndl-image-with-background xl">
![](/library/prefabs/openai/config-param.png)
</div>
Completing this task should remove the warning.
# A basic chat
Let's take a look at a basic chat. With the setup above in place we can move to the frontend component of the prefab. It includes a very basic chat frontend that you can put into your project as a starting point.
:::note
The cloud functions of the prefab require the user to be logged in so for this very basic example we are expecting there to be a user with username `test` and password `test`. Either create a user with those credentials in your backend, or if you already have users in your app you can modify the example below.
:::note
You can find it in the `OpenAI` folder it's called `Basic Streaming Chat`. Drag it into your app and lets review how it works below.
First we keep the chat log in an array called `Messages`, in this example the array is only kept in memory on the client. The content of the array is displayed using a [Repeater](/nodes/ui-controls/repeater).
<div className="ndl-image-with-background xl">
![](/library/prefabs/openai/chatnodes-1.png)
</div>
The content of the array has the following format, for details please review the [OpenAI Documentation](https://platform.openai.com/docs/guides/gpt/chat-completions-api):
```javascript
[
{
Role:'system', // this can be any of system, user or assistant
Content:'the content of the message',
}
]
```
When starting up the array is initialized with just the system message.
<div className="ndl-image-with-background xl">
![](/library/prefabs/openai/chatnodes-2.png)
</div>
The meat of the chat is represented with these nodes, let's review them in detail.
<div className="ndl-image-with-background xl">
![](/library/prefabs/openai/chatnodes-3.png)
</div>
There are two UI components a [Text Input](/nodes/ui-controls/text-input) where the user can input the chat message, and a [Button](/nodes/ui-controls/button) that when clicked the message is sent to the OpenAI API. This is done with the cloud function (included in the prefab) `OpenAI/Create Chat Stream`, this function expects the full chat history on the `Messages` input in the format detailed above.
So we have simply connected the `Messages` array directly to the input. When the submit button is clicked a function node is called that add the message to the chat history, it has the following code:
```javascript
Noodl.Arrays.Messages = Noodl.Arrays.Messages.concat([{
Role:'user',
Content:Inputs.Content
}])
Outputs.Done();
```
:::note
Remember to always create a new array when modifying arrays. This is the only way it will be propagated as a change to the UI.
:::
When the array has been update the cloud function is called, now with the complete chat history. The cloud function will return with a chat stream session and an endpoint that can be used with the `Stream Session` logic component. This component will stream the reply from the AI and emit the content on the `Content` output along with a `Changed` signal when the outputs is updated.
In this simple chat example we simply feed it into another function node that appends the message from the AI assistant to the chat history. Here is the code:
```javascript
let last = Noodl.Arrays.Messages[Noodl.Arrays.Messages.length-1];
if(last.Role !== 'assistant') {
Noodl.Arrays.Messages = Noodl.Arrays.Messages.concat([{
Role:'assistant',
Content:Inputs.Content
}])
}
else last.Content = Inputs.Content;
```
It simply checks if the last message on the chat history is an `assistant` type message, if not a new message is added (just like we added user messages above). If there is an `assistant` message at the bottom of the chat history we simply change the content of the message.
Changing the chat message history in the `Messages` array will automatically update the user interface so we don't need any additional logic for that.
<div className="ndl-image-with-background l">
![](/library/prefabs/openai/chat-ui-1.png)
</div>
Thats basically it for the frontend of the basic chat. Let's review the cloud function as well.
## Create Chat Stream
The cloud function is very simple. It just uses the `Chat Completion Stream` logic component which requires a `Messages` input with the same format and an optional `User Id` (this can be used by OpenAI to track misuse of the AI).
<div className="ndl-image-with-background xl">
![](/library/prefabs/openai/chat-cf-1.png)
</div>
The `Chat Completion Stream` creates a stream session with the provided chat history and parameters that can later be used on the frontend with the `Stream Session` logic component. Besides the chat history you have a number of properties you can modify:
<div className="ndl-image-with-background l">
![](/library/prefabs/openai/chat-cf-2.png)
</div>
Please review the [OpenAI Documentation](https://platform.openai.com/docs/guides/gpt/chat-completions-api) for more details on these properties.
The prefab also includes a `Completion Stream` and an accompanying cloud function `Create Completion Stream`, this uses the completion OpenAI API that only accepts a single `prompt` input and now a full chat history. More information on the API [here](https://platform.openai.com/docs/guides/gpt/completions-api). It aslo has slightly different parameters.

View File

@@ -0,0 +1,14 @@
---
title: All prefabs
hide_title: true
---
import { PrefabListing } from '../../src/blocks/PrefabListing.tsx';
# Prefabs
Prefabs allow you to clone a pre-built component and use it in your project. The component can be used as is, or tweaked to your needs by opening it up and modifying its internal building blocks.
Learn how to import a prefabs to your project [here](/docs/guides/user-interfaces/modules).
<PrefabListing title="All prefabs" hasNoLink />

View File

@@ -0,0 +1,54 @@
---
title: Pages And Rows
hide_title: true
---
# Pages And Rows
This prefab contains a UI component that is very handy with queries and UIs that require pagination. That is when you want to fetch and show one page at a time and let the user navigate between the available pages.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagesandrows/pagesandrows-1.png)
</div>
This is can be used well together with [Query Records](/nodes/data/cloud-data/query-records) and the [Table](/library/prefabs/table) prefab. Here is a quick example. Don't forget to first clone the prefab into your project. You can simply add the component after a **Table** with the **Query Records** connected as shown below.
<div className="ndl-image-with-background xl">
![](/library/prefabs/pagesandrows/pagesandrows-nodes-1.png)
</div>
Then you simply connect the <span class="ndl-data">Skip</span> and <span class="ndl-data">Limit</span> outputs to the corresponding inputs on the **Query Records** and the <span class="ndl-signal">Changed</span> signal to the <span class="ndl-signal">Do</span> action on the query records. This will have the records fetch with the new **Skip** and **Limits** when the user clicks on one of the page controls, or changes the number of rows per page.
Note that we have also connected the <span class="ndl-data">Total Count</span> from the query node to the corresponding input on the **Pagination** component. This will let the component know home many total records/rows there are in the data set. Make sure it's enabled in the **Query Records** properties.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagination/pagination-total-count.png)
</div>
You may want to control the number of rows per page and the currently selected page via connections or provide a default value, you can do this via the <span class="ndl-data">Selected Page</span> and <span class="ndl-data">Rows Per Page</span> inputs, remember that **Selected Page** is zero based (the first page has index 0).
<div className="ndl-image-with-background l">
![](/library/prefabs/pagesandrows/pagesandrows-props-1.png)
</div>
Finally you can control the options in the **Rows Per Page** dropdown using the <span class="ndl-data">Options</span> property. You provide an array with numbers corresponding to the different options.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagesandrows/pagesandrows-props-2.png)
</div>
This is the default:
```javascript
[5,10,15,20,30,40,50]
```

View File

@@ -0,0 +1,66 @@
---
title: Pagination
hide_title: true
---
# Pagination
This prefab contains a UI component that is very handy with queries and UIs that require pagination. That is when you want to fetch and show one page at a time and let the user navigate between the available pages.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagination/pagination-1.png)
</div>
This is can be used well together with [Query Records](/nodes/data/cloud-data/query-records) and the [Table](/library/prefabs/table) prefab. Here is a quick example. Don't forget to first clone the prefab into your project. You can simply add the component after a **Table** with the **Query Records** connected as shown below.
<div className="ndl-image-with-background xl">
![](/library/prefabs/pagination/pagination-nodes-1.png)
</div>
Then you simply connect the <span class="ndl-data">Skip</span> output to the corresponding input on the **Query Records** and the <span class="ndl-signal">Changed</span> signal to the <span class="ndl-signal">Do</span> action on the query records. This will have the records fetch with the new **Skip** when the user clicks on a new page.
Note that we have also connected the <span class="ndl-data">Total Count</span> from the query node to the corresponding input on the **Pagination** component. This will let the component know home many total records/rows there are in the data set. Make sure it's enabled in the **Query Records** properties.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagination/pagination-total-count.png)
</div>
You also need to specify how many rows you want per page. This is done in the <span class="ndl-data">Page Size</span> property.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagination/pagination-props-1.png)
</div>
Finally you can set the currently <span class="ndl-data">Selected Page</span> by connecting to the correspinding input. Remeber that it is zero based.
<div className="ndl-image-with-background l">
![](/library/prefabs/pagination/pagination-props-2.png)
</div>
## Responsiveness
The pagination control will grow to fill the space it has available to it by setting the <span class="ndl-data">Width</span> property.
<div className="ndl-image-with-background m">
![](/library/prefabs/pagination/pagination-width.png)
</div>
If all pages fit inside the available space it will not keep growing instead you can control the alignment within the available space here.
<div className="ndl-image-with-background m">
![](/library/prefabs/pagination/pagination-inner-align.png)
</div>

View File

@@ -0,0 +1,116 @@
---
title: PDF Export
hide_title: true
---
# PDF Export
:::note
This prefab only works on Noodl hosted cloud services.
:::
It's recommended that you have a grasp of the following concepts before diving into this prefab:
* [Page Navigation](/docs/guides/navigation/basic-navigation) - How to create pages and navigate between them.
* [Cloud Functions](/docs/guides//cloud-logic/introduction) - How to create cloud functions and run logic on the backend.
Here is a nifty prefab for exporting / generating PDFs. Exporting a PDF involves two components:
* **A PDF Page** This needs to be a page in your applications that is accessible externally. This page will be turned into a PDF in the next step.
* **A PDF export cloud function** This is a cloud function that will perform the PDF export, the exported PDF will be uploaded as a file to the cloud service and you will receive a URL that can be send to the frontend and opened in a new tab.
Let's review the two components one by one:
## The PDF Page
First you need to create a Noodl page in a page router that will be accessible at a specific `url` when you deploy the application. This web page should contain the content pages of your PDF. We have found that you get the best result when simply stacking groups on top of each other as shown below:
<div className="ndl-image-with-background xl">
![](/library/prefabs/pdf/pages.png)
</div>
We also recommend setting the dimensions of each page to explicit values as shown below:
<div className="ndl-image-with-background m">
![](/library/prefabs/pdf/page-size.png)
</div>
In this way you can put the content of each page within these groups. You could also use a [Repeater](/nodes/ui-controls/repeater) to dynamically generate the pages with data. You need to make sure that the page is publicly available so it doesn't require a login for any data you put on the pages. Here is an example: `https://pdf-test.sandbox.noodl.app/pdf`.
## The PDF export cloud function
The second step is to create a cloud function that performs the PDF export and returns a URL with the ready PDF. After cloning the prefab into your project you will have
<div className="ndl-image-with-background m">
![](/library/prefabs/pdf/cloud-components.png)
</div>
The cloud function `Create PDF` will simply create a PDF from a prodived web page URL, upload the file and return the URL. The content of the cloud functions is very simple:
<div className="ndl-image-with-background xl">
![](/library/prefabs/pdf/create-pdf.png)
</div>
The request is connected to the `Generate PDF` logic component that does the PDF export and when it succeeds the url with the location of the PDF is returned in the request.
## Hooking it up
Here is a very simple example of to hook it up in your application. When the button is clicked the cloud function is called with a string with the URL of the web page that should be made into a PDF.
<div className="ndl-image-with-background xl">
![](/library/prefabs/pdf/hook-up-1.png)
</div>
When the cloud function completes the url to the exported PDF is sent to an [External Link](/nodes/navigation/external-link) node that opens the url in a new tab and the browser will show a preview of the PDF.
The PDF generation generally takes a second or two, so it's good to show something like a [Loading Spinner](/library/prefabs/loading-spinner) while processing.
## User sessions
Often the web page that has the content of the PDF requires access the cloud database to include data in the document. This data should generally be protected with [Access Control](/docs/guides/cloud-data/access-control) so only users with permissions can access. But the page used to export the PDF will not have a valid user session as it's only used in the export process. We can solve this by providing a session token as a query parameter to the page.
There is a second cloud function called `Create PDF With Session` that helps us do this, it works like the other but it first fetches a session for the user calling the cloud function (this cloud function requires authentication on the front end to be called). The session is appended to the provided page url, as seen below:
<div className="ndl-image-with-background xl">
![](/library/prefabs/pdf/create-pdf-session.png)
</div>
To use the session token on the frontend you need to extract it from the [Page Inputs](/nodes/navigation/page-inputs) and feed into a function node with this code:
```javascript
if(Inputs.SessionToken) {
try {
await Noodl.Users.become(Inputs.SessionToken);
}
catch(e) {
Outputs.Failure();
throw e;
}
Outputs.Success();
}
else {
Outputs.Failure();
throw Error("No session token provided");
}
```
This code will use the provided session token to authenticate and "become" the user that the session token is valid for. Here is an example of how you can add the user email address to the PDF content.
<div className="ndl-image-with-background xl">
![](/library/prefabs/pdf/hook-up-2.png)
</div>

View File

@@ -0,0 +1,26 @@
---
title: Progress Circle
hide_title: true
---
# Progress Circle
A UI component for visualizing progress in percentage where 100% match to 360 degrees. The component takes a minimum value, a maximum value and a target value for converting the number range into percentage.
By default the progress animates towards the target value.
<div className="ndl-image-with-background">
![](/library/prefabs/progress-circle/progress-circle.png)
</div>
After importing the module you will see a component called **Progress Circle** in your project.
The example below shows how to hook the **Progress Circle** up to minimum and maximum values, and give a target value to visualize in percentage.
<div className="ndl-image-with-background xl">
![](/library/prefabs/progress-circle/progress-circle-demo.png)
</div>

View File

@@ -0,0 +1,30 @@
---
title: Rating
hide_title: true
---
# Rating
A UI component for selecting a rating from 1 to 5 with stars. Adding more starts or a different scale can easily be modified in the component. This UI component uses the **Icon node** to show the stars, and can be changed to other icons as well like hearts, smileys, etc. if preferred.
<div className="ndl-image-with-background l">
![](/library/prefabs/rating/rating.png)
</div>
After cloning the prefab you will see a logic component called **Rating** in your project. Place it into the dom-tree to render it.
You can both set a rating to be displayed via the **Rating Input**, and get the selected rating from the **Rating Output** as shown on the image below.
The **Rating** output is a number between 1-5 by default.
<div className="ndl-image-with-background xl">
![](/library/prefabs/rating/rating_example.png)
</div>

View File

@@ -0,0 +1,48 @@
---
title: Selection Pills
hide_title: true
---
# Selection Pills
A simple prefab component displaying a set of "pills" given an array of **Options** (the pill values) and **Labels** (what should be shown in the pills). The user can make a selection, one or many pills. It works very similar to the [Multi Choice](/library/prefabs/multi-choice) prefab.
<div className="ndl-image-with-background l">
![](/library/prefabs/selection-pills/selection-pills.png)
</div>
There are a few important properties of the **Selection Pills** prefab component that we need to take a closer look at:
<div className="ndl-image-with-background l">
![](/library/prefabs/selection-pills/selection-pills-props-1.png)
</div>
First, you specify a set of pill values in the **Options** property / input.
```javascript
['one','two','three']
```
Optionally you can specify labels corresponding to each option value, if not the option value will be used as label. This is done via the **Labels** property / input.
```javascript
['One','Two','Three']
```
Finally the **Selection** property / input also contains an array of string, but this time you should have it contain the option values that you want selected. Most often this is connect to a variable or object property. See the example below.
<div className="ndl-image-with-background xl">
![](/library/prefabs/selection-pills/selection-pills-nodes-1.png)
</div>
The component also have a corresponding **Selection** output, here you can see it contains the option values that the user have selected.

View File

@@ -0,0 +1,71 @@
---
title: SendGrid
hide_title: true
---
# SendGrid
This prefab will add a logic component to your cloud functions so you can send emails with [SendGrid](https://sendgrid.com), it will show up in the **SendGrid** folder among your [cloud functions](/docs/guides/cloud-logic/introduction).
<div className="ndl-image-with-background l">
![](/library/prefabs/sendgrid/sendgrid-1.png)
</div>
## Settings
First you must provide a few settings, this is done in the **Config** part of the **Cloud Dashboard**. Launch your cloud services dashboard (if you don't have a cloud service you need to create and make it active for the project).
<div className="ndl-image-with-background s">
![](/library/prefabs/sendgrid/config-1.png)
</div>
<div className="ndl-image-with-background m">
![](/library/prefabs/sendgrid/config-2.png)
</div>
Then find the **Config** section in the sidebar of your dashboard. You can take a look at the [Config](/nodes/data/cloud-data/config) node for more details on how config parameters work. Create a parameter for `SendGridAPIKey`, make sure you make the **Master Key Only** so it is protected in your cloud service.
<div className="ndl-image-with-background xl">
![](/library/prefabs/sendgrid/config-3.png)
</div>
## Sending an email
Sending an email is done by adding a **Send Email** logic component to your cloud function and then sending a signal to the **Do** input.
<div className="ndl-image-with-background xl">
![](/library/prefabs/sendgrid/sendgrid-3.png)
</div>
There are a number of inputs to this node that is good to review:
- `To` This is the email for the recipients on your email.
- `CC` This is the email for the cc on your email.
- `BCC` This is the email for the bcc on your email.
The three above inputs can also accept an array of emails, such as:
```javascript
[
'example@email.com',
'another@email.com'
]
```
- `From` One string containing an email that should be the from email address.
- `Subject` The subject of your email.
- `Text` If you want to send a pure text email provide the content of the email on this input.
- `Html` If you want to send a html emal, provide the content of the email on this input.

View File

@@ -0,0 +1,391 @@
---
title: Stripe
hide_title: true
---
# Stripe
Accepting payments and managing subscriptions is an important part of many digital products and when building in Noodl this is best done using **Stripe**, to go-to service for integrating payment into apps. This prefab and this guide will cover some of the key aspects of enabling you to accept payments from your users.
First you need to create an account and make sure you have access to the [Stripe Dashboard](https://dashboard.stripe.com), you don't need a fully approved account to complete this guide, it's actually preferable that you start with the test version of your account.
To be able to follow this guide properly we recommend that you are well versed in a few Noodl concepts already.
- **Cloud Data**. You know how to set up cloud services and work with cloud data, start [here](/docs/guides/cloud-data/creating-a-backend).
- **Cloud Functions**, how to create logic that run in the cloud, take a look [here](/docs/guides/cloud-logic/introduction).
- **Pages and Navigation**, how to create pages and navigation, start [here](/docs/guides/navigation/basic-navigation).
- **User Management**, you need to have an app where you can create new users and log them in, start [here](/nodes/data/user/sign-up)
## Setup
After installing the prefab you will find a folder of components both on your frontend and in your cloud functions called **Stripe**, in these folders you will find the good stuff we will use in this guide. But first you must complete the setup.
Launch the cloud services dashboard for your project and find your way to the **Config** tab, here you will need to create a new config parameter called `StripeAPIKey` (case sensitive) where you need to put the **Secret Key** from your [Stripe Dashboard](https://dashboard.stripe.com). Look for this section in **Stripe**, important it's the **Secret Key** that you need.
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/stripe-key.png)
</div>
Then create the config in your cloud service, and make sure that access is restricted to **Master Key Only**. This will keep the API key safe in your cloud service.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/config-param.png)
</div>
## Accepting a one time payment
Let's start with the basic example of your user buying a product from your application with a one time payment. First you need to make sure you have [created the product in stripe](https://support.stripe.com/questions/how-to-create-products-and-prices) and that it has a one time price. Find the `Price Id` in your dashboard, it will look like this.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/stripe-price-id.png)
</div>
Copy it for we will use it in a bit. Let's say you are creating a game where you can buy virtual products, and you have a checkout screen that looks something like this:
<div className="ndl-image-with-background ">
![](/library/prefabs/stripe/game-checkout.png)
</div>
When the user clicks the **Checkout** button you will use the **Buy Products** logic component that is part of the prefab. It will redirect the user to a checkout page that is hosted by stripe where the user can provide credit card details and complete the purchase.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/buy-products-nodes.png)
</div>
You need to send a signal to **Do** when you want the redirect to happen and you need to provide an array of **Items** that Stripe should prompt the user to pay for. This is an array of objects, one for each product type to purchase (kind of like a checkout cart). The function node in the graph above have the following short code:
```javascript
Outputs.Items = [
{
PriceId: "your-price-id-from-stripe",
Quantity: 1,
},
];
```
You also need to provide a payment **Owner Id**, this is simply an **Id** that you will need later to fulfill the purchase. In this case we are going to assign a magic sword item to our user so we need to pass in the user as the owner of the payment. More on this later under the fulfilment topic.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/payment-owner-id.png)
</div>
This will open a new tab with the stripe checkout page where the user can complete the purchase. When the user succeeds, or if the payment is cancelled **Stripe** will redirect back to your application. This is done using two redirect urls. You will need to add these to the **Config** of your application, the exact values should match your domain when you have deployed the app, but for now you can just put in any value:
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/checkout-callbacks-config.png)
</div>
Actually when running locally (while developing your app in the editor) they will get a different value, to customize this value look in the **Stripe / Settings** component among your cloud functions.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/checkout-callbacks.png)
</div>
- The `Checkout Success Url` is overridden when working locally and set to `http://localhost:8574/checkout-success`
- The `Checkout Cancel Url` is overridden when working locally and set to `http://localhost:8574/checkout-cancel`
You need to create pages that map to these urls, or update the two urls to match your application. To learn more about how to use configurations in your app check out the [Config](/nodes/data/cloud-data/config) node.
:::note
If things don't work as expected (there are many things that can go wrong), the **Developer** part of the **Stripe Dashboard** is a good place to start looking. Here you can see all latest requests made and it will show you errors and might give you clues to what went wrong.
:::
## Fulfillment and webhooks
Now when the user has completed the checkout flow **Stripe** will notify your application that you can fulfill the request (in this case, give the user the magic sword). This is done using something called **Webhooks**, for us this means that **Stripe** will call a **Cloud Functions** of our choosing to let us know that the payment was successful. First you need to set up the webhook, and when developing **Stripe** has a neat tool that will let you test the entire flow in the Noodl editor before deploying.
Visit [this page](https://dashboard.stripe.com/test/webhooks/create?endpoint_location=local) of your **Stripe Dashboard** to install the tools needed on your computer and perform the setup. Now when starting the tool you should use the following command:
```bash
$ stripe listen --forward-to localhost:8577/functions/stripe-webhook
```
Next you will need to create a cloud function called `stripe-webhook` (small case), this is the function that will be called when the checkout session is completed. Start by adding a **Stripe / Events / Process Stripe Payment Event** logic component to your function like this:
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/stripe-webhook-1.png)
</div>
Make sure your cloud function can be called without authorization since it will be called by **Stripe** and not be a logged in user in your app, edit the properties of the **Request** node.
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/allow-unauth.png)
</div>
:::note
It's good practice to return a response to Stripe as quickly as possible. A few database updates or API calls are fine, but complex long running tasks can cause Stripe to fail with a ["timed out" error](https://support.stripe.com/questions/webhooks-how-to-investigate-and-fix-timed-out).
:::
When the payment is completed successfully a **Payment Completed** signal will be sent from the **Process Stripe Payment Event** node. We can use this to create our virtual magic sword and give it to our user. Here are a few important outputs that we get with the signal.
- `Payment Owner Id` This is the **Id** that we provided when starting the checkout session above with the **Buy Products** action. In this case it will point to the user making the purchase so we can use it when creating the sword.
- `Items` is an array with objects containing the items that was purchased (same as was sent into the **Buy Products** action) but augmented with some important data, this is what they look like:
```javascript
[
{
Quantity, // The number of this item
PriceId, // The price it was puchased at
ProductId, // The Id of the product from your stripe dashboard
},
];
```
Let's say that we have a class of record in our cloud service called **Product**, here we will create items that have a **productId** that we get from stripe (this will tell us what was purchased), and a pointer to a user called **ownerId** so that later we can query all products that a user has purchased. We can hook it up like this:
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/stripe-webhook-2.png)
</div>
The little function node is used to extract the first product id from the **Items** array with the following little snippet:
```javascript
if (Inputs.Items) Outputs.ProductId = Inputs.Items[0].ProductId;
```
That's it, now we can sell virtual magic swords to our users. You can test out the payment flow in your application when running on your desktop by opening a browser and navigating to `http://localhost:8574` where Noodl serves your application while running locally.
When you complete the payment flow you should see the cloud function light up as the signals is triggered and the data flows through the graph. You can also use this to find any problems by inspecting the data on the connections.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/inspect-webhook.png)
</div>
:::note
The **Product Id** from stripe (that you can find in your [Stripe Dashboard](https://dashboard.stripe.com)) is a unique identifier for the product, it's good to use this same **Id** in your app to identify items of purchase.
:::
When you deploy your application you need to make sure that the two redirect urls in your config above points to the correct domain, customer or sandbox. And most important you need to provide the deployed webhook function url to **Stripe**. First, you need to find the endpoint of your cloud services that you will use for your deployed app, go to the **Cloud Services** sidebar tab and then **Manage cloud service**.
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/cs-manage-1.png)
</div>
This will show the follow popup, here you are looking for the **Endpoint** url.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/cs-manage-2.png)
</div>
Now the endpoint for your **Webhook** function will be (replacing `xyz` and `123` with the values from your endpoint in the dialog above):
```bash
https://backend.noodl.cloud/xyz/123/functions/stripe-webhook
```
With that url in hand go to the [Stripe Dashboard](https://dashboard.stripe.com/test/webhooks/create) to add a new webhook endpoint. You also need to tell stripe what events you are interested in receiving. For one time payments you only need:
- `checkout.session.completed` you will find it under the **Checkout** tab.
## Storing the Customer Id
The way we have set it up now **Stripe** will create a new customer for every checkout session, although this works it will create a lot of customers in your stripe dashboard and the user will have to fill out credit card details every time they make a new purchase. To avoid this we can store the **Customer Id** from **Stripe** in our app database and in later checkouts, let **Stripe** know it's the same customer. In this case, a customer maps to a **User** in our database, so let's create a new property on our user record called **stripeCustomerId** make sure it has the **String** type.
Then in your **stripe-webhook** cloud function, hook it up so the `Customer Id`received along with the **Payment Completed** signal is stored in the user record (remember we used the **Payment Owner Id** to keep the user when starting the checkout process).
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/stripe-webhook-3.png)
</div>
Now after the user has made one purchase we can use the **stripeCustomerId** property when initiating new checkout sessions. Add these connections to where you initiate the session with the **Buy Products** action.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/customer-id-connect.png)
</div>
You can also provide a `Customer Name`and a `Customer Email` if you have them, in that case they will be prefilled in the form of the checkout session. With this hooked up, try the new flow two times and the second time you should see that it retains your details.
## Subscriptions
With this prefab you can also build applications that offer subscriptions or plans for your users. It works much similar to above so make sure you have completed all the steps for one time payments as we won't go into as much more detail here.
Like for one time payments you need products set up and you need prices for your products. A product with a recurring price corresponds to a plan type (so maybe one for Basic, Pro etc), and a product can have several prices and billing periods. If there is no plan, we assume that your are on the `free` plan initially. So to get the prefabs working properly you need to start by initializing the `Plans` array that should contain all your plans, this can be done e.g. in your home `App` component.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/init-plans.png)
</div>
You need the array to follow a certain schema, this is an example of what you could put in a function node as above:
```javascript
Outputs.Items = [
{
Name: "Free",
Desc: "Description",
id: "free",
},
{
ProductId: "xyz",
Name: "Basic",
Desc: "With the basic plan you get features A,B,C. Its billed monthly.",
id: "the-price-id-from-stripe-for-this-plan",
Period: "month",
Price: "$99",
Details: [
{
Text: "Sharing Tools",
InPlan: true,
},
{
Text: "Design Tools",
InPlan: true,
},
{
Text: "Private Messages",
InPlan: false,
},
// ... more details
],
},
// .... more plans
];
```
You need the `free` product in there (as this will be the default displayed if there is no current subscription) and then one entry for each subscription product and price. The prefabs supports filtering on `month` and `year` billing periods so you can tag your entries in the array. Some notes:
- `Details` is an array of features for your plan. You can supply this and it will be shown in the `Plan Picker` visual component that you can use if you like. You can provide a **Text** and **IsPlan** which is a boolean indicating if this specific feature is in the plan or not.
:::note
In the example below we are going to assume that the current **User** is the subscription owner, but in many cases maybe it will be a different record, such an **Orginization** or a **Team**. You would use the same pattern as below just with a different record class. In that case the **Orginization** or **Team** would be the customer so that is where you would store the **stripeCustomerId** and **plan**.
:::
First let's use a handy little visual component to show the current plan, it's called `Current Plan Badge` and can be found in the `Stripe/Subscriptions` folder on your frontend. You can put the badge on a page where you will show the current plan and hook it up as below, as an example.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/current-plan-badge-1.png)
</div>
The most important thing is to hook up the **stripeCustomerId** from your user (or whatever record you use as subscription owner). This is needed to fetch the current plan and show it. There are a few good to know signals sent from this component.
- **Upgrade** This is sent if the user clicks the upgrade button. In this case we navigate to new page where we will show all the plans you can upgrade to. More on that later.
- **Plan Canceled** A signal is sent here if the plan was canceled.
- **Plan Renewed** A signal is sent here if the plan was renewed.
- **Failure** A signal is sent here if an operation failed, the error can be found on the **Error** output.
This is what it looks like:
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/current-plan-badge-2.png)
</div>
However when you have a new user they will not have a plan, so it will display the free plan and ask to upgrade, in this example we navigate to a new page to show all options.
## Buying a plan
When buying a plan we can use another handy visual component on your frontend called `Stripe/Subscriptions/Plan Picker`. Simply put that on a page and hook it up as shown below:
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/plan-picker-1.png)
</div>
A few important notes on this. First we connect the **stripeCustomerId** like before, this allows the component to fetch the current plan and also to simply checkout by allowing **Stripe** to save customer info in the checkout process. Furthermore we need to provide a subscription owner id via the **Owner Id** input, just like above this will be used in the **Webhook** to assign the plan to the correct record. In this case we are using the **User** record as the subscription owner. This will result in something like this:
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/plan-picker-2.png)
</div>
When the **Upgrade** button is clicked, the user will be redirected to the **Stripe** checkout flow just like for one time payments, and redirected back to your application using the same process.
## Subscription fulfillment
Just like for one time payments stripe will alert us using the **Webhook** when we receive changes in subscriptions. This time we are going to use the `Stripe/Events/Process Stripe Subscription Event` component. This will emit signals on important events, namely when a subscriptions is started, updated or deleted.
First we create a new property on our **User** record in the cloud services dashboard. We call it `plan` and give it the **String** type, in this property we will store the current plan so we can use it to determine which features should be available in our application. Here is a simple way to hook it up so that we keep track of the current plan the user is subscribed to.
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/stripe-webhook-4.png)
</div>
Let's review the three signals a bit:
- **Subscription Created** This is emited when a subscription is successfully bought, here we store the **Customer Id** with the record pointed to by **Subscription Owner Id**, which in this case is a **User** record. We also store the **Product Id** of the plan. We can use this **Id** in our user to determine which features should be available in our application.
- **Subscription Updated** A signal is emitted here if the user updates a plan, so we do the same as when created. We store the **Product Id** of the plan, so we can serve the corresponding features in our application.
- **Subscription Deleted** Finally, a signal is sent here if the subscription ends. Here we should revert back to the free plan. We do this using the **Set Record Properties** node on the subscription owner (the user) and by specifying `free` for the plan.
<div className="ndl-image-with-background l">
![](/library/prefabs/stripe/stripe-webhook-5.png)
</div>
There you go, that is all needed to build a subscription purchase and management flow.
One final notice, when you register your deployed webhook with stripe (as described above, in the [Stripe Dashboard](https://dashboard.stripe.com/test/webhooks/create)), make sure to listen to these events, you find the under the **Customer** section:
- `customer.subscription.created`
- `customer.subscription.updated`
- `customer.subscription.deleted`
## Invoices
When your users are subscribed to plans and hopefully paying their bills they might need to viewer invoices and collect receipts. You can have **Stripe** email your customers when an invoice is successfully paid, but it might also be good to show a list in the billing part of your application. You can do this with the `Stripe/List Invoices` cloud function as shown below:
<div className="ndl-image-with-background xl">
![](/library/prefabs/stripe/list-invoices.png)
</div>
Make sure you provide the **Stripe Cusomter Id** that you should have stored in the previous steps. The array returned will have the following schema:
```javascript
{
id: "...";
Status: "paid"; // Check the stripe documentation for possible invoice statuses
ManageUrl: "https://..."; // An url where you can redirect the user to manage the invoice
PdfUrl: "https://..."; // An url where you can redirect the user to download the invoice as PDF
PeriodStart: "2022-12-08T14:38:50.000Z"; // Start of the invoice period
PeriodEnd: "2022-12-08T14:38:50.000Z"; // End of period
AmountDue: 3500;
AmountPaid: 3500;
Currency: "usd";
}
```
I hope you have enjoyed this guide and thay you have some tools to start building great payment capabilities to your apps using **Stripe**.

View File

@@ -0,0 +1,69 @@
---
title: Supabase
hide_title: true
---
# Supabase
This prefab gives you a few components that allows you to connect to Supabase and manage user authentication.
> This prefab is built by [Guillaume Maison](https://twitter.com/gmaison) and [Rico Trevisan](https://twitter.com/RicoTrevisan). Please show them some love if you find this prefab useful.
<div className="ndl-image-with-background l">
![](/library/prefabs/supabase/thumb.png)
</div>
## Included components
### Base Components
- **[Supabase - Setup Client](components/setup-client)**: Sets up the Supabse SDK client to access your supabase instance. Must be placed in your projects home component.
- **[Supabase - Example Request](components/supabase-request-example)**: An example on how to fetch data from a table in Supabase.
### User Components
- **[Supabase Sign Up](components/supabase-sign-up)**: Signs up a new user.
- **[Supabase Log In](components/supabase-log-in)**: Logs in a user.
- **[Supabase Log Out](components/supabase-log-out)**: Logs out a user.
- **[Supabase Send Password Reset](components/supabase-send-password-reset)**: Sends a link to reset user password.
- **[Supabase Send Magic Link](components/supabase-send-magic-link)**: Sends a login link without password.
- **[Supabase Resend Confirmation](components/supabase-resend-confirmation)**: Resend a signup confirmation email when validating sign up by email
- **[Supabase Fetch Current User Auth](components/supabase-fetch-current-user-auth)**: Retrieves the auth data of the currently logged in user and saves it to a global `currentUser` object.
- **[Supabase Fetch Current User Profile Data](components/supabase-fetch-current-user-profile-data)**: Retrieves the non-auth user data of the currently logged in user and saves it to a global `currentUser` object.
- **[Supabase Update Current User Auth](components/supabase-update-current-user-auth)**: Updates auth data for the currently logged in user, both in Supabase and the `currentUser` object.
- **[Supabase Update Current User Profile Data](components/supabase-update-current-user-profile-data)**: Updates user data for the currently logged in user, both in Supabase and the `currentUser` object.
### Pages
You will also find a couple of pages that allow you to quickly get up and running with all user features.
Set the `Supabase Example App Root` as your home component for a quick start on all routing.
## Quickstart
First, drop a **Supabase Setup Client** in your project home component and input your `Supabase URL` and `Supabase Anon Key` in its Property Panel. Then, open the **Projects Settings** sidebar and find the `Head Code` input. Add the following at the top:
```html
<script type="module">
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.22.0';
window.createClient = createClient;
</script>
```
Lastly, you need to connect the `Did Mount` output of your root Group node to the `Do` input of the `Supabase - Setup Client` like so:
<div className="ndl-image-with-background l">
![](/library/prefabs/supabase/setup.png)
</div>
This will set everything up and allow you to use all of the other Supabase components.
You can use an **[Object](/nodes/data/object/object-node)** node set to the id `currentUser` to get all the user data (if a user is logged in).
You can use the **[Supabase Fetch Current User Auth](components/supabase-update-current-user-auth)** component to check if the user is logged in. If the user is already authenticated from a previous session, this session is retrieved, the user is considered logged in, and the component outputs `true` on its `Logged In` output and in the `currentUser` Noodl object.
Use the **[Supabase - Fetch Current User Profile Data](components/supabase-update-current-user-profile-data)** to trigger a data fetch and refresh the non-auth data in the `currentUser` object.

View File

@@ -0,0 +1,83 @@
---
title: Setup Client
hide_title: true
---
# Setup Client
This component is used to initialize Supabase Client and set it up to query your Supabase backend.
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/setup-node.png)
</div>
> Please note that you need to place one instance of this component in your project home component, set the default values of the `Supabase URL` and `Supabase Anon Key`, and connect the the `Did Mount` output of your root Group node to the `Do` input like in the image above.
## Values from Supabase
You can find the required URL and Anon Key by logging into your Supabase instance, navigating to `Settings -> API`, and look for the Project URL and Project API Keys sections:
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/keys.png)
</div>
## Setup
First, drop a **Supabase Setup Client** in your project home component and input your `Supabase URL` and `Supabase Anon Key` in its Property Panel. Then, open the **Projects Settings** sidebar and find the `Head Code` input. Add the following at the top:
```html
<script type="module">
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.22.0';
window.createClient = createClient;
</script>
```
Lastly, you need to connect the `Did Mount` output of your root Group node to the `Do` input of the `Supabase - Setup Client` like so:
<div className="ndl-image-with-background l">
![](/library/prefabs/supabase/setup.png)
</div>
This will set everything up and allow you to use all of the other Supabase components.
## Global Variables
The Supabase prefab sets up a couple of global Noodl variables for you to work with:
### Supabase_userProfileTableName
This variable is a string and must be set to the name of the table containing the `user_profile` data in your Supabase instance. Its primary key must be named `id` and be of the same type as `auth.users.id`.
### currentUser
This variable contains all the data for the currently logged in user. It contains 4 fields:
- `currentUser.loggedIn`: a boolean containing the current logged in state
- `currentUser.auth`: an object with all the authentication data for current User
- `currentUser.session`: an object with all the session data for current User
- `currentUser.profile`: an object with all the data coming from the user profile
## Inputs
| Data | Description |
| --------------------------------------------------- | --------------------------------------------------------------------------------- |
| <span className="ndl-data">Supabase URL</span> | Found in your `Supabase Instance -> Settings -> API -> Project URL section`. |
| <span className="ndl-data">Supabase Anon Key</span> | Found in your `Supabase Instance -> Settings -> API -> Project API Keys section`. |
| Signals | Description |
| -------------------------------------- | --------------------------------------------- |
| <span className="ndl-signal">Do</span> | Starts the initialization of Supabase Client. |
## Outputs
| Signals | Description |
| ------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the Supabase client initialization succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when the Supabase client initialization failed with an error message in the console. |

View File

@@ -0,0 +1,32 @@
---
title: Fetch Current User Auth
hide_title: true
---
# Fetch Current User Auth
This component is used to send a request to Supabase and retrieve all authorisation data on the currently logged in user. After a success it updates the `auth`, `session` and `loggedIn` properties on the Noodl object with the id `currentUser`.
<div className="ndl-image-with-background">
![](/library/prefabs/supabase/fetchauth.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Signals | Description |
| -------------------------------------- | -------------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the fetch request call. |
## Outputs
| Data | Description |
| ------------------------------------------- | --------------------------------------------------- |
| <span className="ndl-data">Logged In</span> | A boolean that holds the users current login state. |
| Signals | Description |
| ---------------------------------------- | --------------------------------------------- |
| <span className="ndl-signal">Done</span> | Sends a signal when the request has finished. |

View File

@@ -0,0 +1,34 @@
---
title: Fetch Current User Profile Data
hide_title: true
---
# Fetch Current User Auth
This component is used to send a request to Supabase and retrieve all profile data on the currently logged in user. After a success it updates the `profile` property on the Noodl object with the id `currentUser`.
<div className="ndl-image-with-background">
![](/library/prefabs/supabase/fetchdata.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Signals | Description |
| -------------------------------------- | -------------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the fetch request call. |
## Outputs
| Data | Description |
| --------------------------------------- | ---------------------------------------------------- |
| <span className="ndl-data">Error</span> | Outputs the the error message if the request failed. |
| Signals | Description |
| ------------------------------------------------ | -------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal if the request is successful. |
| <span className="ndl-signal">Failure</span> | Sends a signal if the request has failed. |
| <span className="ndl-signal">No User Data</span> | Sends a signal if there is no user data to be retrieved. |

View File

@@ -0,0 +1,44 @@
---
title: Log In
hide_title: true
---
# Log In
This component is used to log a user in. Once email address and password are set, the sign up is triggered after a signal is sent to the `Do` input.
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/login.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## On success
When a user has successfully been logged in the **Log In** component will create a Noodl Object with the id `currentUser`. This object contains all the user data. You can use the **[Supabase - Fetch Current User Profile Data](/library/prefabs/supabase/components/supabase-update-current-user-profile-data)** to refresh all non-auth data for the user.
A successful login will also trigger a `Supabase User Logged In` event. You can hook into to this event anywhere in your app using a [Receive Event](/nodes/events/receive-event/) node.
## Inputs
| Data | Description |
| ------------------------------------------ | ------------------------------------------ |
| <span className="ndl-data">Email</span> | Sets the email used to log in the user. |
| <span className="ndl-data">Password</span> | Sets the password used to log in the user. |
| Signals | Description |
| -------------------------------------- | ------------------------ |
| <span className="ndl-signal">Do</span> | Triggers the login call. |
## Outputs
| Data | Description |
| --------------------------------------- | ---------------------------------------------------------- |
| <span className="ndl-data">Error</span> | The error sent back after a failed login call to Supabase. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,39 @@
---
title: Log In
hide_title: true
---
# Log In
This component is used to log a user out.
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/logout.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## On success
When a user has successfuly been logged out the **Log Out** component will empty the Noodl Object with the id `currentUser`.
A successful log out will also trigger a `Supabase User Logged Out` event. You can hook into to this event anywhere in your app using a [Receive Event](/nodes/events/receive-event/) node.
## Inputs
| Signals | Description |
| -------------------------------------- | ------------------------ |
| <span className="ndl-signal">Do</span> | Triggers the login call. |
## Outputs
| Data | Description |
| --------------------------------------- | ---------------------------------------------------------- |
| <span className="ndl-data">Error</span> | The error sent back after a failed logout call to supabase |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,28 @@
---
title: Request Example
hide_title: true
---
# Request Example
This demo component executes a request to your Supabase instance.
:::note
In itself, this component is not usable. It is just here to show you an example of how to create such a Request component based on the Supabase Client API.
:::
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/request-example.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly make requests to Supabase.
## Making requests
The advanced nature of Supabase means that you need to write some code to make requests to your backend. Luckily their API is well documented, and can even be generated using the Noodl AI `/Function` command.
No matter if you write the calls yourself or generate them, it could be good to familiarize youself with their simple database functions. You can find them [here](https://supabase.com/docs/reference/javascript/select).
It is also a good idea to familiarize yourself with building custom Components in Noodl, as this will increase the requests reusability and maintainability. [This guide](/docs/guides/user-interfaces/components) teaches you how to build visual components, but the same concepts apply to logic components (that will be the most useful for Supabase requests).

View File

@@ -0,0 +1,33 @@
---
title: Resend Confirmation
hide_title: true
---
# Resend Confirmation
This component is used to resend a signup confirmation email if the initial email was not received or expired.
<div className="ndl-image-with-background l">
![](/library/prefabs/supabase/resendconfirmation.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Data | Description |
| --------------------------------------- | -------------------------------------------- |
| <span className="ndl-data">Email</span> | The email to send the confirmation email to. |
| Signals | Description |
| -------------------------------------- | ------------------------------------ |
| <span className="ndl-signal">Do</span> | Triggers the send confirmation call. |
## Outputs
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,38 @@
---
title: Send Magic Link
hide_title: true
---
# Send Magic Link
This component is used to send a login link that doesnt require a password.
<div className="ndl-image-with-background l">
![](/library/prefabs/supabase/magic-link.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Data | Description |
| --------------------------------------- | ------------------------------------ |
| <span className="ndl-data">Email</span> | The email to send the magic link to. |
| Signals | Description |
| -------------------------------------- | ---------------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the magic link send call. |
## Outputs
| Data | Description |
| --------------------------------------- | ----------------------------------------------------------- |
| <span className="ndl-data">Data</span> | The response data from a successful request. |
| <span className="ndl-data">Error</span> | The error sent back after a failed logout call to Supabase. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,38 @@
---
title: Send Password Reset
hide_title: true
---
# Send Password Reset
This component is used to send a password reset email to the provided email.
<div className="ndl-image-with-background l">
![](/library/prefabs/supabase/send-password-reset.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Data | Description |
| --------------------------------------- | ---------------------------------------- |
| <span className="ndl-data">Email</span> | The email to send the password reset to. |
| Signals | Description |
| -------------------------------------- | --------------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the password reset call. |
## Outputs
| Data | Description |
| --------------------------------------- | ----------------------------------------------------------- |
| <span className="ndl-data">Data</span> | The response data from a successful request. |
| <span className="ndl-data">Error</span> | The error sent back after a failed logout call to Supabase. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,40 @@
---
title: Sign Up
hide_title: true
---
# Sign Up
This component is used to sign up a user into Supabase. Once email address and password are set, the sign up is triggered after a signal is sent to the `Do` input.
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/sign-up.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Data | Description |
| ------------------------------------------ | ------------------------------------------- |
| <span className="ndl-data">Email</span> | Sets the email used to sign up the user. |
| <span className="ndl-data">Password</span> | Sets the password used to sign up the user. |
| Signals | Description |
| -------------------------------------- | ------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the signup call. |
## Outputs
| Data | Description |
| ---------------------------------------------- | ------------------------------------------------------------------ |
| <span className="ndl-data">Data</span> | The data that is sent back by the supabase client. |
| <span className="ndl-data">Error</span> | The error sent back after a failed signup call to supabase. |
| <span className="ndl-data">Is Connected</span> | `true`/`false` depending on if the user is connected after signup. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,39 @@
---
title: Update Current User Auth
hide_title: true
---
# Update Current User Auth
This component is used to to update the current logged in users email and password.
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/updateauth.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Signals | Description |
| -------------------------------------- | -------------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the fetch request call. |
| Data | Description |
| ------------------------------------------ | ----------------------------------- |
| <span className="ndl-data">Email</span> | The email you want to update to. |
| <span className="ndl-data">Password</span> | The password you want to update to. |
## Outputs
| Data | Description |
| --------------------------------------- | -------------------------------------------------------------- |
| <span className="ndl-data">Data</span> | The response sent back after a successful request to Supabase. |
| <span className="ndl-data">Error</span> | The error sent back after a failed request to Supabase. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,37 @@
---
title: Update Current User Data
hide_title: true
---
# Update Current User Data
This component is used to to update the current logged in users profile data.
<div className="ndl-image-with-background xl">
![](/library/prefabs/supabase/updateprofile.png)
</div>
> Please note that [Supabase Client](/library/prefabs/supabase/components/setup-client/) needs to be set up in your app before you can properly use this component.
## Inputs
| Signals | Description |
| -------------------------------------- | -------------------------------- |
| <span className="ndl-signal">Do</span> | Triggers the fetch request call. |
| Data | Description |
| -------------------------------------- | --------------------------------------------------- |
| <span className="ndl-data">Data</span> | A JS object containing the data you want to update. |
## Outputs
| Data | Description |
| --------------------------------------- | ------------------------------------------------------- |
| <span className="ndl-data">Error</span> | The error sent back after a failed request to Supabase. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,58 @@
---
title: Tab Bar
hide_title: true
---
# Tab Bar
This prefab contains a tab bar component that you can use to create tab style navigation.
<div className="ndl-image-with-background l">
![](/library/prefabs/tab-bar/tab-bar.png)
</div>
The simple way to use it is to drag it into your project and specify the tabs using the **Items** input.
```javascript
[
{
Label:"Tab 1",
Value:"1"
},
{
Label:"Tab 2",
Value:"2"
},
{
Label:"Tab 3",
Value:"3"
},
]
```
You simply provide a **Label** and a **Value** for each tab. The output **Selected Tab** will contain the value of the currently selected tab, and you can use it to mount / unount the different tab pages.
<div className="ndl-image-with-background l">
![](/library/prefabs/tab-bar/tab-bar-nodes-1.png)
</div>
The example above uses a simple function node to create mount / unmount switches for each of the pages.
```javascript
Outputs.Tab1 = Inputs.SelectedTab==="1"
Outputs.Tab2 = Inputs.SelectedTab==="2"
Outputs.Tab3 = Inputs.SelectedTab==="3"
```
You can change the appearance of the tab bar by editing the child component **Tab Bar Item**.
<div className="ndl-image-with-background m">
![](/library/prefabs/tab-bar/tab-bar-item.png)
</div>

View File

@@ -0,0 +1,241 @@
---
title: Table
hide_title: true
---
import useBaseUrl from '@docusaurus/useBaseUrl'
import CopyToClipboardButton from '/src/components/copytoclipboardbutton'
# Table
A component for creating tables. This is also a great starting point for creating your own custom tables.
<div className="ndl-image-with-background l">
![](/library/prefabs/table/table.png)
</div>
## Basic usage
The most simple use case is to show an array of objects. This can be done by simply providing the array items as the **Items** input of the table component. Here is a simple example of just using the result from a **Query Records** and feeding it to a table.
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-nodes-1.png)
</div>
This will simply present all properties of the objects as columns, as show below:
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-screen-1.png)
</div>
The table will automatically show **String**, **Boolean**, **Number** and **Date** types. Other types will not be presented correctly. Now you might not want to show all properties of the objects. This can be easily achieved with the **Headers** innput of the table. There you can specify which columns to use.
Providing the following headers in this example:
```javascript
[
{
Field: 'Name',
Label: 'Name',
},
{
Field: 'Level',
Label: 'Security Level',
},
{
Field: 'HireDate',
Label: 'Hired at',
},
{
Field: 'Remote',
Label: 'Works remote',
},
];
```
You can also clear the default sample items of the table by editing the **Items** input in the property panel. Just put in an empty array.
```javascript
[];
```
Would instead produce the following table:
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-screen-2.png)
</div>
## Row clicked signal
When a row is clicked the **Item Clicked** signal will be emitted along with the **Item Id** of the object or record representing that row. You can for instance use that to show details for the object in a different panel. The example below sets the **Item Id** to a variable that could be used somewhere else to present the object in a different UI.
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-nodes-2.png)
</div>
## Editing columns
You can make a column editable by specifying the **Editable** property in the corresponding header item. Let's say we want to make the **Works remote** column editable, we would simply provide it in the **Headers** array.
```javascript
[
...{
Field: 'Remote',
Label: 'Works remote',
Editable: true,
},
];
```
This would allow the checkboxes in the column to be edited. The table will edit the actual object or record property, you can see this by inspecting the content of the **Items** array output of the **Query Records** node while editing the table.
<div className="ndl-video">
<video width="100%" autoPlay muted loop src={useBaseUrl("/library/prefabs/table/table-editable.mp4")}/>
</div>
When an item is edited the **Cell Changed** signal will be emitted from the table, along with the **Item Id** and the **Field**. You can, for instance, use this event to trigger a record save to the cloud.
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-nodes-3.png)
</div>
With this setup you have a very basic CRUD interface to a list of objects. Make sure to set the **Properties to store** to **All** on the **Set Record Properties** node.
<div className="ndl-image-with-background l">
![](/library/prefabs/table/set-record-props.png)
</div>
## Custom Cells
The table component is entierly built using Noodl core nodes which means you can rebuilt it to completely fit your needs. One setting you can provide in the **Headers** input is to set the column width in pixels. You can do this be specifying **Width**, as shown below:
```javascript
[
...{
Field: 'Remote',
Label: 'Works remote',
Editable: true,
Width: 50,
},
];
```
You can also customize the cells of the table by simply editing their individual subcomponents, or by creating completely new ones. The **Table** component have a number of subcomponents, one for each type of cell, and one default simply called **Cell**. You can duplicate this one to use as base for your own cell type.
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-duplicate-cell.png)
</div>
Next, rename the new copy to a good name for your new cell type, it must end with **Cell**, so we will call it **Security Level Cell**. Now you can edit the **Headers** array to make the column use your new cell type.
```javascript
[
...
{
Field:"Level",
Label:"Security Level",
Type:"Security Level"
},
...
]
```
Now let's get started editing our new cell type, here is a simple example of how to show the security level as a colored bar.
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-nodes-4.png)
</div>
In the example above we have created a **Group** that has a width in percentage, some nice rounded corners and padding. The **Function** node computes the width and a blend for the color with the following script.
```javascript
Outputs.Blend = (Inputs.Value / 5) * 2
Outputs.Width = Math.max( (Inputs.Value / 5) * 100, 20)
```
The color blend is creating the background color for the group with these settings:
<div className="ndl-image-with-background l">
![](/library/prefabs/table/table-color-blend-props.png)
</div>
Using this cell type will give you the following table.
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-screen-3.png)
</div>
We recommend inspecting the default cell types and see how the handle cell editing etc.
## Sorting
You can enable sorting by a column by setting the `Sortable` property in a header item. This will enable the header item to be clicked to switch between ascending and descending sorting.
<div className="ndl-image-with-background l">
![](/library/prefabs/table/table-sorting-3.png)
</div>
Here is an example for a table with two columns:
```javascript
[
{
Label:"Name",
Field:"Name",
Sortable:true
},
{
Label:"State",
Field:"State",
Sortable:true
}
]
```
The table doesn't sort the items automatically instead it provides an output called <span class="ndl-data">Sorting</span> that will contain the current selecting sorting field, and a signal <span class="ndl-data">Sorting Changed</span> that will be emitted when the user clicks on a header and the sorting is changed. This will need to be hooked up to your data source to trigger a fetch, it's very simple to do this with [Query Records](/nodes/data/cloud-data/query-records) as shown below:
<div className="ndl-image-with-background xl">
![](/library/prefabs/table/table-sorting-1.png)
</div>
The <span class="ndl-data">Sorting</span> output is a string containing the name of the selected sorting field with a prefix `-` if sorting is to be done descending. You can easily connect this to the **Query Records** node using [advanced filters](/nodes/data/cloud-data/query-records#sorting-in-advanced-filters). Here is the most simple example:
```javascript
where({ })
sort([Inputs.Sorting])
```
This will allow you to make the connection between the table **Sorting** output and the corresponding input on the **Query Records** node. Finally you can set the sorting via the <span class="ndl-data">Sorting</span> input on the table component. This can be used to provide a default sorting, make sure you use the same sorting as default on your data source.
<div className="ndl-image-with-background l">
![](/library/prefabs/table/table-sorting-2.png)
</div>

View File

@@ -0,0 +1,64 @@
---
title: Tags
hide_title: true
---
# Tags
This component can be used to display an array of objects with labels as tags. It can automatically create colors based on the label and you can receive click and optionally a remove signal (a small remove cross is displayed.)
<div className="ndl-image-with-background l">
![](/library/prefabs/tags/tags.png)
</div>
You simplye provide an array of objects containing at least the **Label** property to the **Items** input.
```javascript
[
{
"Label":"First"
},
{
"Label":"Second"
},
{
"Label":"Third"
}
]
```
You can customize the color used for the tags via a property.
<div className="ndl-image-with-background l">
![](/library/prefabs/tags/tags-props-1.png)
</div>
There are a couple of more options that is good to use. You can toggle if the the tags should be **Removable** (this will show a litte cross icon next to the label), and **Clickable**. By activating these you will also be able to receive the signals as shown later.
<div className="ndl-image-with-background l">
![](/library/prefabs/tags/tags-props-2.png)
</div>
Finally you can enable **Generate colors** which will automatically create unique colors for all tags depending on the label text.
You can use the **Tag Clicked** signal along with the **Tag Id** output as shown below to trigger an action when a tag is clicked.
<div className="ndl-image-with-background xl">
![](/library/prefabs/tags/tags-nodes-1.png)
</div>
You can in the same way use the **Remove Clicked** signal to trigger an action when the remove cross is clicked. In the example above the **MyTags** variable contains an array of tags, the following **Function** code removes the tag.
```javascript
Noodl.Variables.MyTags = Noodl.Variables.MyTags.filter(t => t.id !== Inputs.RemoveId)
```
It creates a new array, by filtering out the tag with the id equal to **Inputs.RemoveId**, which in turn is connected to the **Tag Id** output from the **Tags** component.

View File

@@ -0,0 +1,32 @@
---
title: Time Picker
hide_title: true
---
# Time Picker
A UI component for picking a time of the day, hours and minutes. It works both as a text input where you can type the time, and as a drop down of quick picks. On Mobile the native time picker can be used if the clock icon is clicked.
<div className="ndl-image-with-background">
![](/library/prefabs/time-picker/time-picker.png)
</div>
Below is a screenshot of the quick pick drop down.
<div className="ndl-image-with-background">
![](/library/prefabs/time-picker/time-picker-drop-down.png)
</div>
After importing the module you will see a component called **Time Picker** in your project.
The example below shows how to hook the **Time Picker** up to data in an **Object**, in this case a **Function** node is used to write back the hours and minutes to the object using the **Changed** signal.
<div className="ndl-image-with-background xl">
![](/library/prefabs/time-picker/time-picker-nodes.png)
</div>

View File

@@ -0,0 +1,57 @@
---
title: Toast
hide_title: true
---
# Toast
A UI component for displaying Toast messages. This UI component comes with four Toast variations; A **Warning**, **Error**, **Success**, and a **Neutral** variation. This component utilizes the **Show Popup** node to display the toast from a Signal input, you can read more about popups in this [guide](/docs/guides/navigation/popups).
<div className="ndl-image-with-background l">
![](/library/prefabs/toast/toast_variations.png)
</div>
After cloning the prefab you will see a logic component called **Show Toast** in your project. The example below demonstrates how to show the Toast with a click event from a Button node, by connecting a Signal to the **Do** Input of the **Show Toast** node. In the Sidebar you can select what Toast type to show.
<div className="ndl-image-with-background xl">
![](/library/prefabs/toast/toast-inuse.png)
</div>
You can modify the appearence of the toast by editing the sub components of the **Show Toast** parent component. Each type of toast has its own component with its unique styling, and the **Toast Component** contains animations and logic that are shared between all types of toasts.
<div className="ndl-image-with-background">
![](/library/prefabs/toast/toast-components.png)
</div>
In the **Toast Component** you can modify the show and hide transition using the **State** node. You can read more about how to use the **State** node in this [guide](/docs/guides/user-interfaces/states). A **Delay** node is used to control the time the toast is visible, and the **Close Popup** is triggered after the close transition is completed (important).
<div className="ndl-image-with-background xl">
![](/library/prefabs/toast/toast-nodes.png)
</div>
The content of a toast component for a specific type is faily straight forward. It contains the visual elements of the toast and the message as a **Component Input**.
<div className="ndl-image-with-background xl">
![](/library/prefabs/toast/toast-nodes-2.png)
</div>
If you want to add additional types of toast you will need to modify the **State** node in the **Show Toast** logic parent component. It contains a state for each type of toast. You will then need to create a child component with the corresponding name (simply duplicate one of the existing components, such as **Normal** and rename it).
<div className="ndl-image-with-background xl">
![](/library/prefabs/toast/toast-nodes-3.png)
</div>

View File

@@ -0,0 +1,22 @@
---
title: Toggle Switch
hide_title: true
---
# Toggle Switch
A UI component containing a simple toggle switch. You can use it as you would a **Checkbox** UI element.
<div className="ndl-image-with-background">
![](/library/prefabs/toggle/toggle.png)
</div>
Here is an example of how it is connected to a variable, just like how you would connect a **Checkbox**.
<div className="ndl-image-with-background xl">
![](/library/prefabs/toggle/toggle-nodes.png)
</div>

View File

@@ -0,0 +1,141 @@
---
title: TOTP
hide_title: true
---
# TOTP
**Timebase One Time Password**s is a popular way to do 2-Factor Authentication (2FA) for users, that is, after the user signs in with username and password they need to provide a time based token to complete the login. [Google Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en&gl=US) is a commonly used app, and there are other apps that are compatible.
This prefab contains a couple of cloud functions and frontend logic functions that help you build a 2FA sign up / log in flow in Noodl.
After installing you will see two folders, one among your componets (the frontend) and one in your cloud functions called **TOTP**.
<div className="ndl-image-with-background m">
![](/library/prefabs/totp/totp-1.png)
</div>
<div className="ndl-image-with-background m">
![](/library/prefabs/totp/totp-2.png)
</div>
Let's review how we use these components to build the sign up and log in flow.
## Signing up
First the user needs to sign up normally using the [Sign Up](/nodes/data/user/sign-up) node. The **TOTP** prefabs can also be used on an existing user, that is, you can enable **TOTP** after the user has signed up or you can make it required as part of the sign up flow.
## Connecting
When you have a user signed up / logged in you can start the process of activating **TOTP**, this is a two step process. First you need to generate a secret that is attaced to your users, you then need to present the user with a QR Code that is used to add your application to the **TOTP** authentication device (e.g. Google Authenticator). Once that is successful the user can verify that it works by typing in a valid token.
The first step is simply calling the **TOTP/Start Connect** cloud function. The example below calls the function when the page is loaded on the **Did Mount** signal. When the function completes you will receive a **QR Code** that you can simply use as source for an image node to display it.
<div className="ndl-image-with-background xl">
![](/library/prefabs/totp/totp-connect-1.png)
</div>
When completed, you might have a screen like this:
<div className="ndl-image-with-background m">
![](/library/prefabs/totp/totp-connect-2.png)
</div>
You can customize what name is used when your application shows up in the authentication device / app by looking in the **TOTP/Start Connect** cloud function for the action node called **Generate Secret**, clicking that node will reveal a property called **Name** that you can edit.
<div className="ndl-image-with-background xl">
![](/library/prefabs/totp/totp-connect-3.png)
</div>
At this point the **TOTP** is not yet activated for the user. To activate the user must prove that the authentication device is working by entering a valid token. This token is sent to the cloud function **TOTP/Complete Connect**, when this function completes with **Sucess** the user can no longer log in with just username and password, more on this later. If it completes with **Failure** the token was not correct and you need to alert the user.
<div className="ndl-image-with-background xl">
![](/library/prefabs/totp/totp-connect-4.png)
</div>
When the **TOTP** connection is completed, you can have the user keep using your application as normal. But when it's time for login you need a different flow.
## Logging in
Logging in is now divided into two steps, the first will simply ask for the username / email and password like before.
<div className="ndl-image-with-background l">
![](/library/prefabs/totp/totp-login-1.png)
</div>
When the **TOTP** connect has completed you cannot use the [Log In](/nodes/data/user/log-in) node anymore, it will fail stating that log in is disabled. Instead you need to use the **TOTP / Start Log In** component that was installed in your project when cloning the prefab. You use it just like you would the good old **Log In** node, providing **Username** and **Password**.
<div className="ndl-image-with-background xl">
![](/library/prefabs/totp/totp-login-2.png)
</div>
There can be three possible output signals from this action node:
- **Success** The user is logged in, **TOTP** was not enabled, you can proceed to your application as normal.
- **Failure** The user did not provide the right username / password.
- **TOTP Needed** The username and password was correct but **TOTP** is enabled. You need to send the user to a new page where the **TOTP** can be entered and validated.
This next step simply need to ask the user to provide the **TOTP** from their authentication device.
<div className="ndl-image-with-background l">
![](/library/prefabs/totp/totp-login-3.png)
</div>
In this step we are going to use the **TOTP / Complete Log In** that was installed into the project when the prefab was cloned. The **TOTP** token along with the **Username** and **Password** from the previous step (in this example they were stored in variables) need to be provided.
<div className="ndl-image-with-background xl">
![](/library/prefabs/totp/totp-login-4.png)
</div>
If this action results in a **Success** signal the log in is completed and you can move the user on to your application. If **Failure** is sent then the token was not correct and you need to notify the user.
## Disconnecting
When the user is logged in you can disconnt the **TOTP**, this will remove the secret and the user can now log in the normal way again with just username and password.
<div className="ndl-image-with-background xl">
![](/library/prefabs/totp/totp-disconnect-1.png)
</div>
This is just a matter of calling the **TOTP / Disconnect** cloud function while the user is logged in. This will return a **Success** or **Failure** signal.

View File

@@ -0,0 +1,51 @@
---
title: Xano
hide_title: true
---
# Xano
This prefab gives you a few components that allows you to connect to Xano and manage user authentication.
> This prefab is built by [Guillaume Maison](https://twitter.com/gmaison). Please show him some love if you find this prefab useful.
<div className="ndl-image-with-background l">
![](/library/prefabs/xano/xano-thumb.png)
</div>
## Included components
### Base Components
- **[Xano - Setup XanoClient](components/setup-xanoclient)**: Sets up the Xano SDK client to access your instance and workspace. Must be placed in your projects home component.
- **[Xano - Request](components/xano-request)**: Does an API Call to a Xano Endpoint and returns the result.
### User Components
- **[Xano Sign Up](components/xano-sign-up)**: Signs up a new user.
- **[Xano Log In](components/xano-log-in)**: Logs in a user.
- **[Xano Log Out](components/xano-log-out)**: Logs out a user.
- **[Xano Current User](components/xano-current-user)**: Gets the user data of the currently logged in user and saves it to a global `currentUser` object.
- **[Xano Update Current User](components/xano-update-current-user)**: Updates user data for the currently logged in user, both in Xano and the `currentUser` object.
- **[Xano authToken Refresh](components/xano-authtoken-refresh)**: Triggers a refresh of the auth token. Mostly for internal use inside of the Xano prefab, but exposed for advanced users.
## Quickstart
First, drop a **Xano Setup XanoClient** in your project home component. Then set the `API Group Base URL` and the `Datasource`. Finally, open the Project Settings sidebar, find the **Head Code** input and paste the following at the top:
```html
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/@xano/js-sdk@latest/dist/xano.min.js"
></script>
```
To automatically refresh the users **authToken** and keep them logged in for longer periods of time, add this to your project home component:
<div className="ndl-image-with-background l">
![](/library/prefabs/xano/authrefresh.png)
</div>

View File

@@ -0,0 +1,49 @@
---
title: Setup XanoClient
hide_title: true
---
# Setup XanoClient
This component is used to configure the Xano Client, enabling your app to establish connections and query your endpoints.
This prefab will not work unless you place one instance of the Setup Xano Client component in your projects Home Component and set the `API Group Base URL` and `Datasource` values:
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/setupxanoclient.png)
</div>
The `API Group Base URL` can be found here in Xano:
<div className="ndl-image-with-background">
![](/library/prefabs/xano/xanobaseurl.png)
</div>
## Inputs
| Data | Description |
| ---------------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-data">API Group Base URL</span> | The base Request URL used to call all the endpoints of the API Groups. |
| <span className="ndl-data">Datasource</span> | The data environment to be used in your Xano workspace. Defaults to `live`. |
| <span className="ndl-data">Auth Login Path</span> | The path to the login endpoint. Defaults to `/auth/login`. |
| <span className="ndl-data">Auth Signup Path</span> | The path to the signup endpoint. Defaults to `/auth/signup`. |
| <span className="ndl-data">Auth Me Path</span> | The path to the endpoint containing the user information. Defaults to `/auth/me` |
After the Xano Client has been set up you can find all the input values in the following Noodl variables:
- `Noodl.Variables.xanoApiGroupBaseUrl`
- `Noodl.Variables.xanoDatasource`
- `Noodl.Variables.xanoAuthSignupPath`
- `Noodl.Variables.xanoAuthLoginPath`
- `Noodl.Variables.xanoAuthMePath`
## Outputs
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the Xano Client initilized successfully. |
| <span className="ndl-signal">Failure</span> | Sends a signal when the Xano Client failed initializing. Outputs the error message in the console. |

View File

@@ -0,0 +1,35 @@
---
title: authToken Refresh
hide_title: true
---
# authToken Refresh
This component is used to automatically refresh the user **authToken**.
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/auth.png)
</div>
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## Inputs
| Data | Description |
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| <span className="ndl-data">TTL</span> | Sets the duration before refreshing the authToken. It is commonly set to half of the token duration. |
| <span className="ndl-data">Endpoint Path</span> | Sets the API endpoint path (used with the `API Group Base URL`) to refresh the user authToken. |
| Signals | Description |
| ----------------------------------------- | ---------------------------- |
| <span className="ndl-signal">Start</span> | Starts the refresh sequence. |
| <span className="ndl-signal">Stop</span> | Stops the refresh sequence. |
## Outputs
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,38 @@
---
title: Current User
hide_title: true
---
# Current User
This component is used to fetch information from the current logged in users `/auth/me` path in Xano.
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/currentuser.png)
</div>
On a request it checks if the user is still logged in by looking for a valid **authToken**. The **authToken** is automatically generated when the user is logged in.
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## Inputs
| Signals | Description |
| ----------------------------------------- | ------------------------------------------------- |
| <span className="ndl-signal">Fetch</span> | Send a Signal to this input to retrieve the data. |
## Outputs
| Data | Description |
| ------------------------------------------- | -------------------------------------------------------------------------- |
| <span className="ndl-data">Logged In</span> | `true` if the user is logged in, `false` if not. |
| <span className="ndl-data">Xano ID</span> | The users ID. |
| <span className="ndl-data">Email</span> | The users email. |
| <span className="ndl-data">User Data</span> | All the data retrieved from the `/auth/me` endpoint of the logged in user. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, or if the **authToken** is expired, and logs an error message in the console. |

View File

@@ -0,0 +1,50 @@
---
title: Log In
hide_title: true
---
# Log In
This component is used to log in a user.
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/login.png)
</div>
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## On success
When a user has successfully been logged in the **Log In** component will create a Noodl Object with the id `currentUser`. This object contains all the user data retrieved from Xanos `/auth/me` endpoint.
A successful signup will also trigger a `Xano User Logged In` event. You can hook into to this event anywhere in your app using a [Receive Event](/nodes/events/receive-event/) node.
## Keeping the user logged in
To keep the user logged in for longer periods of time you need to refresh the **authToken**. This can be done by placing the following nodes in the **home component**:
<div className="ndl-image-with-background l">
![](/library/prefabs/xano/authrefresh.png)
</div>
## Inputs
| Data | Description |
| ------------------------------------------ | -------------------------------------------- |
| <span className="ndl-data">Email</span> | The email of the user you want to log in. |
| <span className="ndl-data">Password</span> | The password of the user you want to log in. |
| Signals | Description |
| -------------------------------------- | ------------------------------------------------------ |
| <span className="ndl-signal">Do</span> | Send a Signal to this input to send the login request. |
## Outputs
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,44 @@
---
title: Log Out
hide_title: true
---
# Log Out
This component is used to log in a user.
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/logout.png)
</div>
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## On success
When a user has successfuly been logged out the **Log Out** component will empty the Noodl Object with the id `currentUser`.
A successful signup will also trigger a `Xano User Logged Out` event. You can hook into to this event anywhere in your app using a [Receive Event](/nodes/events/receive-event/) node. This event can be used to stop the **authToken** refresh.
## If you are refreshing the authToken
Don't forget to turn off the **authToken** refresh if you have added that to your app. This can be done by placing the following nodes in the **home component**:
<div className="ndl-image-with-background l">
![](/library/prefabs/xano/authrefresh.png)
</div>
## Inputs
| Signals | Description |
| -------------------------------------- | ------------------------------------------------------- |
| <span className="ndl-signal">Do</span> | Send a Signal to this input to send the logout request. |
## Outputs
| Signals | Description |
| ------------------------------------------- | ------------------------------------------ |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |

View File

@@ -0,0 +1,33 @@
---
title: Request
hide_title: true
---
# Request
This component is used to call Xano API endpoints.
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## Inputs
| Data | Description |
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| <span className="ndl-data">Endpoint</span> | The path of the endpoint to be called within the API Group, like `/auth/signup` or `/auth/login`. |
| <span className="ndl-data">Request Type</span> | The type of request you want send. Follows the HTTP standards `GET`, `POST`, `PUT`, `PATCH` and `DELETE`. |
| <span className="ndl-data">Data</span> | A JSON formatted payload that will be sent as Request Body. |
| Signals | Description |
| -------------------------------------- | -------------------------------------------------- |
| <span className="ndl-signal">Do</span> | Sends a Signal to this input to start the request. |
## Outputs
| Data | Description |
| ------------------------------------------ | --------------------------------------------- |
| <span className="ndl-data">Response</span> | The JSON formatted response from the request. |
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,40 @@
---
title: Sign Up
hide_title: true
---
# Sign Up
This component is used create a new user in Xano.
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/signup.png)
</div>
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## On success
When a new user has successfully been registered the **Sign Up** component will create a Noodl Object with the id `currentUser`. This object contains all the user data retrieved from Xanos `/auth/me` endpoint.
A successful signup will also trigger a `Xano User Logged In` event. You can hook into to this event anywhere in your app using a [Receive Event](/nodes/events/receive-event/) node.
## Inputs
| Data | Description |
| ------------------------------------------ | --------------------------------------------- |
| <span className="ndl-data">Email</span> | The email of the user you want to sign up. |
| <span className="ndl-data">Password</span> | The password of the user you want to sign up. |
| Signals | Description |
| -------------------------------------- | ------------------------------------------------------- |
| <span className="ndl-signal">Do</span> | Send a Signal to this input to send the signup request. |
## Outputs
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |

View File

@@ -0,0 +1,49 @@
---
title: Update Current User
hide_title: true
---
# Update Current User
This component is used to update information in the current logged in users `/auth/me` path in Xano.
<div className="ndl-image-with-background xl">
![](/library/prefabs/xano/updatecurrentuser.png)
</div>
> Please note that [Xano Client](/library/prefabs/xano/components/setup-xanoclient/) needs to be set up in your app before you can properly use this component.
## Setting up endpoint
Xano does not create this endpoint by default for the user table. You have to create it manually, with a POST verb:
<div className="ndl-image-with-background">
![](/library/prefabs/xano/postverb.png)
</div>
## On success
When the data has successfully been updated the **Update Current User** component will also update the Noodl Object with the id `currentUser`.
A successful update will also trigger a `Xano currentUser Updated` event. You can hook into to this event anywhere in your app using a [Receive Event](/nodes/events/receive-event/) node.
## Inputs
| Data | Description |
| -------------------------------------- | ---------------------------- |
| <span className="ndl-data">Data</span> | The data you want to update. |
| Signals | Description |
| -------------------------------------- | ----------------------------------------------- |
| <span className="ndl-signal">Do</span> | Send a Signal to this input to update the data. |
## Outputs
| Signals | Description |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <span className="ndl-signal">Success</span> | Sends a signal when the request succeeded. |
| <span className="ndl-signal">Failure</span> | Sends a signal when an error occurred, and logs an error message in the console. |