Merge pull request #439 from lowdefy/docs-concepts

fix(docs): Add concepts pages for lists, secrets and deployment.
This commit is contained in:
Gervwyk 2021-02-16 18:54:59 +02:00 committed by GitHub
commit 3cb539b34a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 317 additions and 0 deletions

View File

@ -0,0 +1,80 @@
# Copyright 2020-2021 Lowdefy, Inc
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
_ref:
path: templates/general.yaml.njk
vars:
pageId: deployment
pageTitle: Deployment
section: Concepts
filePath: concepts/deployment.yaml
content:
- id: md1
type: MarkdownWithCode
properties:
content: |
Lowdefy apps can be deployed to the following hosting platforms:
- Netlify
## Deploy to Netlify
#### Step 1
Your project will need to be hosted as a Github repository.
#### Step 2
Link your Github project to Netlify.
- Once logged in to Netlify, click the "New site from git" button.
- Choose Github, and authorise Netlify to access your repositories.
- Select your repository.
> If your repository isn't found, click "Configure Netlify on Github", and give Netlify access to your repository.
#### Step 3
Configure your Netlify deployment.
- Set your build command to `npx @lowdefy/cli build-netlify`.
- Set your publish directory to `.lowdefy/publish`.
- Review the other settings, and deploy your site.
> Your site won't work yet. You first need to configure the Lowdefy backend server in the next step.
#### Step 4
Configure the Lowdefy backend server.
- Click the "Site settings" button.
- Choose the "Functions" section in the left menu.
- Edit the settings and set your functions directory to `.lowdefy/functions`.
#### Step 5
Redeploy your site.
- Go to the "Deploys" tab.
- Click the "Trigger deploy" button and deploy your site.
- Wait for you site to finish deploying.
On the "Site overview" tab you will find your site url.
- _ref:
path: templates/navigation_buttons.yaml
vars:
previous_page_title: Secrets
previous_page_id: secrets
next_page_title: Lists
next_page_id: lists

View File

@ -0,0 +1,154 @@
_ref:
path: templates/general.yaml.njk
vars:
pageId: lists
pageTitle: Lists
section: Concepts
filePath: concepts/lists.yaml
content:
- id: md1
type: MarkdownWithCode
properties:
content: |
List category blocks render multiple [`content areas`](/layout), based on data in the [`state`](/context-and-state) object.
Since the content area might contain input blocks, the block has an array value in state, with it's `block id` as key. For each item in the array, an content area (or set of content areas is rendered). Multiple list blocks can be nested.
### List indices and block ids
If a block is to be rendered in an list's content area, the block id should contain a list index placeholder (specified with the `$` symbol) for each list it is a part of. These placeholders will be populated with the blocks `list indices`. The `list indices` are a array of integers, indicating at which position in the list the block is, for each level of list blocks (zero indexed). The block id should be in valid dot-notation once the placeholders have been substituted.
This can be made more clear with a example. Suppose we have a list block with id `contacts`. Inside this list we have a text input block for the contact name. We would like our state to look like:
```yaml
contacts:
- name: Name 1
- name: Name 2
```
The id for the text input block should be `contacts.$.name`. Each text input block will be given an indexed id based on it's position in the contacts list (`contacts.0.name`, `contacts.1.name`, etc.).
Suppose we also want to add a emails array for each contact. To do this, we can add another list block in the `contacts` array, and add a text input inside the emails array. If we want the emails to be a array of strings, i.e. our `state` should look like:
```yaml
contacts:
- name: Name 1
emails:
- email1@example.com
- email2@example.com
- name: Name 2
emails: []
```
our config should look like:
```yaml
id: contacts
type: ControlledList
properties:
# ...
blocks:
- id: contacts.$.name
type: TextInput
properties:
# ...
- id: contacts.$.emails
type: ControlledList
properties:
# ...
blocks:
- id: contacts.$.emails.$
type: TextInput
properties:
# ...
```
Note that the id of the emails list block is `contacts.$.emails` and that it has one `$` placeholder since it is inside the `contacts` list, and the id of the email text input is `contacts.$.emails.$`, which has two `$` placeholders since it is in both the `contacts` and `contacts.$.emails` lists.
The ids of the `contacts.$.emails.$` text input blocks will look like `contacts.0.emails.3` or `contacts.2.emails.1`, and this will result in the `state` where the emails on a contact are an array of strings.
### List indices in operators
List indices are also supported in "getter" operators like `_state`. If the operator is given a key that contains `$` placeholders, and the operator is called from a block with list indices, the placeholders will be populated with the blocks list indices. These indices are populated on `actions` called by the block, and are even populated in `connections` and `requests` if the block that triggered the `Request` action has list indices. This can be used to get values from the `state` array the block is a part of, or even values from another array at the same index.
### List block methods
List blocks can provide methods to change their values. These are
#### `pushItem`
Add an item at the end of the list.
#### `unshiftItem`
Add an item at the start of the list.
#### `removeItem`
Remove an item at the specified index.
#### `moveItemDown`
Move the item at the specified index one position to the start of the list. If the item is at the start if the list, the item remains at position `0`.
#### `moveItemUp`
Move the item at the specified index one position to the end of the list. If the item is at the end if the list, the item remains at it's position.
#### Example
```yaml
id: page
type: PageHeaderMenu
blocks:
- id: add_item_at_start
type: Button
events:
onClick:
- id: add_item_at_start
type: CallMethod
params:
blockId: list
method: unshiftItem
- id: add_item_at_end
type: Button
events:
onClick:
- id: add_item_at_end
type: CallMethod
params:
blockId: list
method: pushItem
- id: list
type: List
blocks:
- id: list.$.move_item_down
type: Button
events:
onClick:
- id: move_item_down
type: CallMethod
params:
blockId: list
method: moveItemDown
args:
- _index: 0 # Get the first index in the indices array
- id: list.$.move_item_up
type: Button
events:
onClick:
- id: move_item_up
type: CallMethod
params:
blockId: list
method: moveItemUp
args:
- _index: 0
- id: list.$.remove_item
type: Button
events:
onClick:
- id: remove_item
type: CallMethod
params:
blockId: list
method: removeItem
args:
- _index: 0
```
### Lists and state
List blocks create a content area for each item in `state`. If `state` is updated, the list block will also update, creating or destroying content areas as necessary. Thus list blocks can also be manipulated by setting `state` directly using the [`SetState`](/SetState) operator.

View File

@ -33,3 +33,10 @@ _ref:
# Build time operators
The `_ref` and `_var` operators do not work like other operators. They are evaluated while an app is being built, and can thus be used anywhere in the app configuration. They are used to split a app into multiple files, and to reuse configuration. See [`_ref`](/_ref) for more details.
- _ref:
path: templates/navigation_buttons.yaml
vars:
previous_page_title: Events and Actions
previous_page_id: events-and-actions
next_page_title: Secrets
next_page_id: secrets

View File

@ -0,0 +1,56 @@
# Copyright 2020-2021 Lowdefy, Inc
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
_ref:
path: templates/general.yaml.njk
vars:
pageId: secrets
pageTitle: Secrets
section: Concepts
filePath: concepts/secrets.yaml
content:
- id: md1
type: Markdown
properties:
content: |
The `secrets` object is a object that can be used to securely store sensitive information like passwords and API keys. Secrets can be accessed using the [`_secret`](/_secret) operator.
The secrets object only exists on the backend server, and therefore the `_secret` operator can only be used in `connections` and `requests`.
We intend to support multiple secrets strategies in the future (for example AWS Secrets Manager or Docker secrets). Current secrets can only be set with environment variables.
## Environment variables strategy
Secrets can be set by creating an environment variable prefixed with `LOWDEFY_SECRET_`. The secret will then be available in the secrets object with the remaining part ot the name as key.
For example, if the environment variable `LOWDEFY_SECRET_MY_SECRET` is set to `supersecret`, then `_secret: MY_SECRET` will return `supersecret`.
Only strings can be set as environment variables. To store a object as a secret, the object can be JSON stringified, and parsed using the `_json.parse` operator.
To store secrets that contain newline characters, the secret can be base64 encoded, and decoded using the `_base64.decode` operator.
To use secrets in the local development environment, environment variables can be set using a `.env` file. Create a file called `.env` at the root of the project directory. Then set environment variables as:
```
# .env
LOWDEFY_SECRET_MY_SECRET=supersecret
```
- _ref:
path: templates/navigation_buttons.yaml
vars:
previous_page_title: Operators
previous_page_id: operators
next_page_title: Deployment
next_page_id: deployment

View File

@ -130,6 +130,22 @@ menus:
pageId: operators
properties:
title: Operators
- id: secrets
type: MenuLink
pageId: secrets
properties:
title: Secrets
- id: deployment
type: MenuLink
pageId: deployment
properties:
title: Deployment
- id: lists
type: MenuLink
pageId: lists
properties:
title: Lists
- id: blocks_input
type: MenuGroup
properties:
@ -628,6 +644,10 @@ pages:
- _ref: concepts/connections-and-requests.yaml
- _ref: concepts/events-and-actions.yaml
- _ref: concepts/operators.yaml
- _ref: concepts/deployment.yaml
- _ref: concepts/secrets.yaml
- _ref: concepts/deployment.yaml
- _ref: concepts/lists.yaml
- _ref: blocks/input/AutoComplete.yaml
- _ref: blocks/input/ButtonSelector.yaml