diff --git a/packages/docs/README.md b/packages/docs/README.md index 87b0d0f97..a59376e1d 100644 --- a/packages/docs/README.md +++ b/packages/docs/README.md @@ -1,21 +1,31 @@ -Lowdefy was designed to solve the need for businesses to manage their internal data. Businesses need internal tools to connect to a variety of data sources. They need to be able to take actions on that data, and be able to have a view on what is happening in their business. +Lowdefy simplifies creating software that helps manage internal data - think web apps, admin panels, BI dashboards, CRUD and workflow apps. Within most companies the need exist to connect to a variety of data sources and execute actions on such data. This must be done without compromising data security while respecting complex data integrity rules. -Lowdefy allows you to connect to data sources and build internal tools and dashboards. These tools are easy to build and change. This means you get real value quickly, and the tools can grow and change with your business. +Lowdefy aims to enable companies to better control and monitor business data, by simplifying the process of creating internal tools. Lowdefy makes these tools easy to build, change and maintain. -### Only your own business logic +### Create internal tools by only writing simple, readable YAML -Using Lowdefy means all the complicated parts of developing your own web app are taken care of, allowing you to to focus on the business logic. This is what allows you to move so quickly, while still having an app that conforms to industry best practices. +Using Lowdefy means all the complicated parts of developing your own web app are taken care of, allowing you to focus on the pure business logic. This allows you to move quickly, while still having an app that conforms to industry best practices. -### Tutorial +The Lowdefy config schema is easy to learn, understand and remember. In order to achieve this, we aim to be consistent in how things work so that you predict how an app will behave by simply reading the config. -The easiest way to get started with Lowdefy is to follow the tutorial. In this tutorial we will be building a app that allows you to book meeting rooms and manage those bookings. +### Work with your data where it is stored -- How Lowdefy works +Lowdefy apps can connect to multiple data bases, APIs and apps. Day to day business requires people working with data which is stored in a variety of different data bases and applications. - - server, config, +Too often data is exported, duplicated and lost, creating additional risk. Lowdefy only runs your application config, and does not store any data, but rather connects to your data sources. -- Schema -- Blocks -- Deployment options (Netlify, Docker) -- Custom blocks -- responsive layouts +### Build future proof web applications on a open-source platform + +Lowdefy is a open-source Apache-2 licensed project, free from vendor lock-in. Our business model is to build optional "nice-to-have" services best suited for Lowdefy applications, enriching the Lowdefy ecosystem. + +Since Lowdefy apps are easy to manage in a Git repository, we hope to see many community open-source Lowdefy apps in the future. + +### Deploy your Lowdefy app as you like + +Host your Lowdefy app in your own environment as a docker image or even on Netlify using serverless functions. Serving a Lowdefy app, requires a the Lowdefy graphQl server and hosting the Lowdefy React app and blocks. + +The Lowdefy front-end makes use of Webpack module federation to serve blocks and assemble your Lowdefy app as a micro-front-end solution. Developing your own custom front-end React blocks makes Lowdefy apps truly expandable. + +# Tutorial + +The easiest way to get started with Lowdefy is to follow the tutorial. In this tutorial we will be building a simple support ticketing app to get you started. diff --git a/packages/docs/concepts/actions.yaml b/packages/docs/concepts/actions.yaml deleted file mode 100644 index 1dcf9dea5..000000000 --- a/packages/docs/concepts/actions.yaml +++ /dev/null @@ -1,95 +0,0 @@ -# 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: actions - pageTitle: Actions - section: Concepts - content: - - id: md1 - type: Markdown - style: - '.markdown-body': - fontSize: 14px - properties: - content: | - `Actions` can be used to perform actions, like calling requests or linking to a new page, based on events in your app, like button clicks or page loads. - - Each block defines the events for which it will call actions. The actions to be executed can be defined as a list of action definitions, under that event's name in the actions object of a block. The event names usually start with the keyword "on", like `onClick`, `onChange`, or `onInit`. Each action definition has an `id` (which should be unique in that action chain), a `type`, and a `params` object, which has the parameters that specify how the action should execute. - - - ###### Actions definition example: - ```yaml - - id: block_with_actions - type: Block - properties: - # ... - actions: - onEvent1: - - id: action1 - type: ActionType1 - params: - # ... - - id: action2 - type: ActionType2 - params: - # ... - onEvent2: - - id: action3 - type: ActionType3 - params: - # ... - ``` - - # Context initialisation actions - - Four action events are always defined for [`context`](/context) type blocks: - - `onInit` - - `onEnter` - - `onInitAsync` - - `onEnterAsync` - - These actions can be used to initialise the context or page. - - The `onInit` action will execute the first time a context is create (for example if a page is loaded for the first time), before anything is rendered. It can be used to set up a context. Actions that take a long time to execute, like `Request`, should be used sparingly here. - - The `onEnter` action will execute every time a context is rendered again (for example if a user left a page, and returns to it), also before anything is rendered to the screen. It can be used to execute actions that should be run each time a page is loaded, like checking if an id is present in the url query parameters, and initialising the state based on that. - - The `onInitAsync` action will execute the first time a context is created, but after rendering has started. This is a good place to execute requests that might take longer to execute. - - The `onEnterAsync` action also executes after renderering starts, and executes every time a context is rendered. - - # Action types - - The following actions can be used: - - - [`CallMethod`](/CallMethod) - Call a method defined by another block. - - [`Link`](/Link) - Link to another page. - - [`Message`](/Message) - Show a message to the user. - - [`Notification`](/Notification) - Show a notification to the user. - - [`Request`](/Request) - Call a request. - - [`Reset`](/Reset) - Reset the context. - - [`ScrollTo`](/ScrollTo) - Scroll to a point on the page. - - [`SetGlobal`](/SetGlobal) - Set a value to the global object. - - [`SetState`](/SetState) - Set a value to the state. - - [`Validate`](/Validate) - Validate the inputs in the context.s - - _ref: - path: templates/navigation_buttons.yaml - vars: - previous_page_title: Context - previous_page_id: context - next_page_title: Connections - next_page_id: connections diff --git a/packages/docs/concepts/connections.yaml b/packages/docs/concepts/connections-and-requests.yaml similarity index 53% rename from packages/docs/concepts/connections.yaml rename to packages/docs/concepts/connections-and-requests.yaml index f5a61f500..926e20faf 100644 --- a/packages/docs/concepts/connections.yaml +++ b/packages/docs/concepts/connections-and-requests.yaml @@ -15,26 +15,31 @@ _ref: path: templates/general.yaml.njk vars: - pageId: connections + pageId: connections-and-requests pageTitle: Connections and Requests section: Concepts content: - id: md1 type: Markdown - style: - '.markdown-body': - fontSize: 14px properties: content: | - In a Lowdefy app you can integrate with other services like API's or databases using `connections` and `requests`. Connections configure the connection to the service, and often contain contain parameters like connection strings, urls and secrets like passwords or API keys. Requests are used to interact with the connection, like inserting a data record or executing a query. + ### TDLR; + - `connections` define links to other services, like connecting to a database, they are defined on the root of the lowdefy configuration. + - `requests` uses connections to make a call to an the connected external services. + - Use the [`_secret`](/_secret) operator to reference API keys or other secrets as required - do not code secreted into you config or commit secrets to your config source control. + + ----------- + In a Lowdefy app you can integrate with other services like API's or databases using `connections` and `requests`. Connections configure the connection settings to the service, and often contain contain parameters like connection strings, urls and secrets like passwords or API keys. Requests are used to interact with the connection, like inserting a data record, executing a query or calling a API end-point. + + > Sensitive information like passwords or API keys are often required to use external services. The [`_secret`](/_secret) operator should be used to reference these secrets, they should never be coded directly in your app, or committed to source control. # Connections - Connections are defined at the root of your Lowdefy configuration, in the connections array. Each connection should have an `id`, a `type`, and `properties` defining the connection. + Connections are defined at the root of your Lowdefy configuration, in the `connections` array. Each connection must have an `id`, a `type`, and `properties` defining the connection. ###### Connections definition example: ```yaml - version: LOWDEFY_VERSION + lowdefy: LOWDEFY_VERSION connections: - id: connection1 type: ConnectionType1 @@ -48,14 +53,16 @@ _ref: # ... ``` + Our goal is to make connections for everything, as the Lowdefy community grows, we will continue develop the most requested connections. If the connection you require are not supported yet, please head over to our [new connections voting board](https://github.com/lowdefy/lowdefy/discussions/309) to request and vote for new connections. + # Requests - Requests can be defined on any block, and the results of the request are available to any block in the context. Requests should have an `id`, a `type`, a `connectionId` specifying the connection to use, and `properties` defining the request. Requests can be called using the [`Request`](/Request) action. + Requests can be defined on any block, and the results of the request are available to any block in the same context. Requests must have an `id`, `type`, `connectionId` field specifying the connection to use, and `properties` defining the request settings. Requests can be called using the [`Request`](/Request) action. ###### Requests definition example: ```yaml id: block_with_requests - type: Block + type: BlockType requests: - id: request1 type: RequestType1 @@ -71,14 +78,11 @@ _ref: # ... ``` - # Secrets - - Sensitive information like passwords or API keys are often required to use other services. The [`_secret`](/_secret) operator should be used to reference these secrets, they should never be coded directly in your app, or commited to source control. - _ref: path: templates/navigation_buttons.yaml vars: - previous_page_title: Actions - previous_page_id: actions + previous_page_title: Events and Actions + previous_page_id: events-and-actions next_page_title: Layout next_page_id: layout diff --git a/packages/docs/concepts/context-and-state.yaml b/packages/docs/concepts/context-and-state.yaml new file mode 100644 index 000000000..db6cfc225 --- /dev/null +++ b/packages/docs/concepts/context-and-state.yaml @@ -0,0 +1,52 @@ +# 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: context-and-state + pageTitle: Context and State + section: Concepts + content: + - id: md1 + type: Markdown + properties: + content: | + #### TDLR; + - The first block on a page must be a `context` category. + - A page can have multiple `context` blocks. + - Every `context` has a single __state__ object. + - All input blocks writes their value to __state__, with the their `id` as the key in the __state__ object. + - Input blocks which are not visible is removed from __state__. + - The [`SetState`](/SetState) action can also modify the __state__ object. + + ------- + + A Lowdefy block with category `context` provides the environment for a part of a Lowdefy app to run in. More than one context can be placed on a page, but generally only one is need. The first block on a page must be a `context` category block. + + The standard page blocks like [`PageHeaderMenu`](/PageHeaderMenu) or [`PageSiderMenu`](/PageSiderMenu) are all `context` category blocks, and the [`Context`](/Context) block is a simple container that also provides a context. + + Each context provides encapsulation to the blocks inside it. It has it's own __state__ object as well as requests. + + Every `input` category block will have a value in the __state__ object, with the their `id` as the key in the __state__ object, unless the block is not visible, in which case the input value is removed the state object. + + The only other way to modify the __state__ object is to use a `SetState` action. See [`SetState`](/SetState) and [`actions`](/actions) for more details. + + - _ref: + path: templates/navigation_buttons.yaml + vars: + previous_page_title: Tutorial + previous_page_id: tutorial-setup + next_page_title: Events and Actions + next_page_id: events-and-actions diff --git a/packages/docs/concepts/context.yaml b/packages/docs/concepts/context.yaml deleted file mode 100644 index 5a1de13c5..000000000 --- a/packages/docs/concepts/context.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# 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: context - pageTitle: Context - section: Concepts - content: - - id: md1 - type: Markdown - style: - '.markdown-body': - fontSize: 14px - properties: - content: | - A Lowdefy block with category `context` provides the environment for a part of a Lowdefy app to run in. More than one context can be placed on a page, but generally only is need. The first block on a page should be a `context` category block. The standard page blocks like [`PageHeaderMenu`](/PageHeaderMenu) or [`PageSiderMenu`](/PageSiderMenu) are all `context` category blocks, and the [`Context`](/Context) block is a simple container that also provides a context. - - Each context provides encapsulation to the blocks inside it. It has it's own state object and requests. - - _ref: - path: templates/navigation_buttons.yaml - vars: - previous_page_title: Next Steps - previous_page_id: next-steps - next_page_title: Actions - next_page_id: actions diff --git a/packages/docs/concepts/events-and-actions.yaml b/packages/docs/concepts/events-and-actions.yaml new file mode 100644 index 000000000..20e3a8ca6 --- /dev/null +++ b/packages/docs/concepts/events-and-actions.yaml @@ -0,0 +1,105 @@ +# 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: events-and-actions + pageTitle: Events and Actions + section: Concepts + content: + - id: md1 + type: Markdown + properties: + content: | + ### TDLR; + - A list of actions are executed sequentially by a triggered events. + - Events are triggered when something happens on a page, like clicking a button or loading a page. + - Operators used in action `params` are evaluated right before the action is executed. + - `onInit` is triggered the first time a context is mounted and keeps the page in loading for all actions to finish. + - `onEnter` is triggered the every time a context is mounted and keeps the page in loading for all actions to finish. + - `onInitAsync` is triggered the first time a context is mounted and does not keeps the page in loading. + - `onEnterAsync` is triggered the every time a context is mounted and does not keeps the page in loading. + + ----------- + + Events triggered on a page will fire a list of actions. Blocks has predefined events for which it will call actions, like `onClick` on a [`Button`](/Button) or `onEnter` on a [`PageHeaderMenu`](/PageHeaderMenu) block. + + By defining a list of action to execute when a given event is triggered, a chain of tasks can be completed sequentially, like calling a request when a page is opened, or linking to a page when a button is clicked. + + Each action has an `id`, unique to that action chain, a `type`, and a `params` field for specifying input parameters when executing the action. Operators used in action `params` will be evaluated right before the action is executed. + + + ###### Events and actions definition example: + ```yaml + - id: block_with_actions + type: Block + properties: + # ... + events: + onEvent1: + - id: action1 + type: ActionType1 + params: + # ... + - id: action2 + type: ActionType2 + params: + # ... + onEvent2: + - id: action3 + type: ActionType3 + params: + # ... + ``` + + # Context initialisation events + + Four events are always defined for [`context`](/context) type blocks: + - `onInit` + - `onEnter` + - `onInitAsync` + - `onEnterAsync` + + These events can be used to initialise the context or page. + + The `onInit` event is triggered the first time a context is mounted, for example if a page is loaded for the first time. This event blocks page render, in other words, the page __will__ remain in a loading state until all the actions have completed execution. It can be used to set up a context. Actions that take a long time to execute, like `Request`, should be used sparingly here. + + The `onEnter` event is triggered every time a context is mounted to a page, for example if a user left a page, and returns to it. This event also blocks page render. It can be used to execute actions that should be run each time a page is loaded, like checking if an id is present in the [url query parameters](/_url_query), and initialising the [`state`](/context-and-state). + + The `onInitAsync` event is triggered the first time a context is mounted, but does not block page render. In other words, the page __will not__ remain in a loading state until all the actions have completed execution. This is a good place to execute non-blocking tasks or requests that might take longer to execute. + + The `onEnterAsync` event is triggered every time a context is mounted, but does not block page render. + + # Action types + + The following actions can be used: + + - [`CallMethod`](/CallMethod) - Call a method defined by another block. + - [`Link`](/Link) - Link to another page. + - [`Message`](/Message) - Show a message to the user. + - [`Notification`](/Notification) - Show a notification to the user. + - [`Request`](/Request) - Call a request. + - [`Reset`](/Reset) - Reset the context. + - [`ScrollTo`](/ScrollTo) - Scroll to a point on the page. + - [`SetGlobal`](/SetGlobal) - Set a value to the `global` variable object. + - [`SetState`](/SetState) - Set a value to the context `state`. + - [`Validate`](/Validate) - Validate the inputs in the context. + - _ref: + path: templates/navigation_buttons.yaml + vars: + previous_page_title: Context and State + previous_page_id: context-and-state + next_page_title: Connections and Requests + next_page_id: connections-and-requests diff --git a/packages/docs/concepts/layout.yaml b/packages/docs/concepts/layout.yaml index 2a2dd108e..59d4c36c4 100644 --- a/packages/docs/concepts/layout.yaml +++ b/packages/docs/concepts/layout.yaml @@ -21,20 +21,21 @@ _ref: content: - id: markdown_intro type: Markdown - style: - '.markdown-body': - fontSize: 14px properties: content: | - Containers are used to lay out other blocks on a page. Blocks of category `Container` or `Context` both function as container blocks. + Containers blocks are used to arrange blocks on a page. Blocks of category `Container`, `Context` and `List` all function as container blocks. Container blocks has content areas into which a list of blocks are rendered. `List` category blocks can render container areas for each element in the data array. + + Blocks on a page can be arranged using a __span__ or __flex__ layout. Blocks in __span__ layout is placed in a 24 column grid system, whereas blocks __flex__ dynamically grows or shrinks to fit content into a row depending on content size and screen size. + + Under the hood, Lowdefy layouts are based on the [Ant Design Grid System](https://ant.design/components/grid/). The content areas are implemented as a row, and blocks are implemented as a column. # Content areas - Each container has content areas - these are areas where other blocks can be placed. All container blocks have a primary content area. This area is called `content`. Container blocks might have other content areas, like `header`, `footer`, or `title`. These content areas are implemented specifically by the block. + Each container has content areas - these are areas where nested blocks can be placed. All container blocks have a primary content area. This area is called `content`. Container blocks might have other content areas, like `header`, `footer`, or `title`. These content areas are implemented specifically by the block. To place blocks in the primary content area of a container, the block definitions for those blocks can be placed inside the `blocks` array of the container block. - > In the following examples, blocks of type `Container` will represent a generic container block, and blocks of type `Block` will represent a generic block. The `Container` block might be a `Box`, a `Card`, a `PageHeaderMenu` or any other container or context block. The `Block` blocks could be any type of block, including other container blocks. + > In the following examples, blocks of type `Container` will represent a generic container block, and blocks of type `Block` will represent a generic block. The `Container` block might be a [`Box`](/Box), a [`Card`](/Card), a [`PageHeaderMenu`](/PageHeaderMenu) or any other container or context block. The `Block` blocks could be any type of block, including other container blocks. ###### Two blocks in the primary content area (`content`) of a container: @@ -77,8 +78,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | To place blocks in other content areas, the block definitions can be placed in the `blocks` array of the specific area in the `areas` object: @@ -160,8 +159,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | Placing blocks both in the `blocks` array, as well as under the `areas.content.blocks` array is an anti-pattern, and in this case the blocks under `blocks` will overwrite those under `areas.content.blocks`. @@ -198,27 +195,15 @@ _ref: html: |
Block 1
- - id: markdown_row_col - type: Markdown - style: - marginTop: 16px - '.markdown-body': - fontSize: 14px - properties: - content: | - > Lowdefy layouts are based on the [Ant Design Grid System](https://ant.design/components/grid/). The content areas are implemented as a `row`, and blocks are implemented as a `column`. - - id: markdown_grid_layout type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | # Layouts using span - Each content area has 24 columns. Blocks have a `span` property, which determines how may columns the block occupies. Blocks are laid out horizontally, until the sum of the spans would be more than 24, then the block is placed in the next row. + Each content area has 24 columns. Blocks have a `span` property, which determines how many columns the block occupies. Blocks are laid out horizontally, until the sum of the spans is more than 24, then the last block block is wrapped to the next row. By default a block is given a span of 24. This is what makes blocks lay out vertically below each other. @@ -307,25 +292,21 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | # Layouts using flex - Blocks can also be laid out using [CSS flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) properties. These properties are `grow` (`flex-grow`), `shrink` (`flex-shrink`), `size` (`flex-basis`) and `flex` (`flex`). If any of these properties are set, the default span of 24 or any span set in the configuration is not used. If one of `grow`, `shrink`, or `size` are set, the other properties take their default values. The `flex` property overwrites the `grow`, `shrink`, and `size` properties. + Blocks can also be laid out using [CSS flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) properties. These properties are `grow` (`flex-grow`), `shrink` (`flex-shrink`), `size` (`flex-basis`) and `flex` (`flex`). If any of these properties are set, the default span of 24 or any span set in the configuration is not applied. If one of `grow`, `shrink`, or `size` are set, the other properties take their default values. The `flex` property overwrites the `grow`, `shrink`, and `size` properties. - id: markdown_block_properties type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | # Block layout properties - Properties can be set on each block to control how it is placed. These properties are defined in the `layout` object. The properties that can be defined are: + The `layout` object on blocks can be used to control how a block is placed in the layout. The `layout` properties that can be defined are: - `align`: _Enum_ - Align block vertically in the area. Options are `top`, `middle`, and `bottom`. Default `top.` - `flex`: _String_ - Set the [`flex`](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) CSS property. This overwrites the `grow`, `shrink`, and `size` properties. @@ -420,8 +401,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Order example: @@ -469,8 +448,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Offset example: @@ -524,8 +501,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Pull example: @@ -582,8 +557,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Push example: @@ -640,8 +613,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | # Area layout properties @@ -798,8 +769,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Direction examples: @@ -985,8 +954,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Gutter examples: @@ -1110,8 +1077,6 @@ _ref: type: Markdown style: marginTop: 16px - '.markdown-body': - fontSize: 14px properties: content: | ###### Justify examples: @@ -1401,7 +1366,7 @@ _ref: - _ref: path: templates/navigation_buttons.yaml vars: - previous_page_title: Connections - previous_page_id: connections + previous_page_title: Connections and Requests + previous_page_id: connections-and-requests next_page_title: Operators next_page_id: operators diff --git a/packages/docs/introduction.yaml b/packages/docs/introduction.yaml index e389626e0..480dd57ff 100644 --- a/packages/docs/introduction.yaml +++ b/packages/docs/introduction.yaml @@ -28,6 +28,9 @@ _ref: _ref: README.md - id: start_tutorial_button type: Button + style: + marginTop: 40px + marginBottom: 80px properties: block: true hideActionLoading: true diff --git a/packages/docs/lowdefy.yaml b/packages/docs/lowdefy.yaml index 69ae4043c..34ab12278 100644 --- a/packages/docs/lowdefy.yaml +++ b/packages/docs/lowdefy.yaml @@ -85,19 +85,19 @@ menus: title: Concepts icon: BulbOutlined links: - - id: context + - id: context-and-state type: MenuLink - pageId: context + pageId: context-and-state properties: - title: Context - - id: actions + title: Context and State + - id: events-and-actions type: MenuLink - pageId: actions + pageId: events-and-actions properties: - title: Actions - - id: connections + title: Events and Actions + - id: connections-and-requests type: MenuLink - pageId: connections + pageId: connections-and-requests properties: title: Connections and Requests - id: layout @@ -267,9 +267,9 @@ pages: - _ref: tutorial/tutorial-requests.yaml - _ref: tutorial/next-steps.yaml - - _ref: concepts/context.yaml - - _ref: concepts/actions.yaml - - _ref: concepts/connections.yaml + - _ref: concepts/context-and-state.yaml + - _ref: concepts/events-and-actions.yaml + - _ref: concepts/connections-and-requests.yaml - _ref: concepts/layout.yaml - _ref: concepts/operators.yaml diff --git a/packages/docs/templates/navigation_buttons.yaml b/packages/docs/templates/navigation_buttons.yaml index 3ff06d348..1fda6aaf8 100644 --- a/packages/docs/templates/navigation_buttons.yaml +++ b/packages/docs/templates/navigation_buttons.yaml @@ -15,7 +15,7 @@ id: nav_buttons type: Box style: - marginTop: 60px + marginTop: 40px marginBottom: 80px layout: contentGutter: 16 diff --git a/packages/renderer/src/page/block/Context.js b/packages/renderer/src/page/block/Context.js index 5bd8a32dc..b137636c1 100644 --- a/packages/renderer/src/page/block/Context.js +++ b/packages/renderer/src/page/block/Context.js @@ -21,10 +21,8 @@ import getContext from '@lowdefy/engine'; import OnEnter from './OnEnter'; -const contexts = {}; - const Context = ({ block, contextId, pageId, render, rootContext }) => { - const [loading, setLoading] = useState(true); + const [context, setContext] = useState({}); const [error, setError] = useState(null); useEffect(() => { @@ -38,8 +36,7 @@ const Context = ({ block, contextId, pageId, render, rootContext }) => { rootContext, }); if (mounted) { - contexts[contextId] = ctx; - setLoading(false); + setContext(ctx); } } catch (err) { setError(err); @@ -51,7 +48,7 @@ const Context = ({ block, contextId, pageId, render, rootContext }) => { }; }, [block, pageId, rootContext, contextId]); - if (loading) + if (context.id !== contextId) return ( { if (error) throw error; - return ; + return ; }; export default Context;