Skip to content

Commit

Permalink
Merge pull request #572 from SoftwareBrothers/beta
Browse files Browse the repository at this point in the history
Beta
  • Loading branch information
wojtek-krysiak authored Aug 30, 2020
2 parents 2c991d3 + 6135030 commit a73e727
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 146 deletions.
Binary file removed docs/ layout1.png
Binary file not shown.
Binary file removed docs/layout2.png
Binary file not shown.
Binary file removed docs/layout3.png
Binary file not shown.
Binary file removed docs/layout4.png
Binary file not shown.
Binary file removed docs/layout5.png
Binary file not shown.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { flatten, unflatten } from './types/src/admin-bro'
export * from '@admin-bro/design-system'
export * from './types/src/frontend/store/store'
export * from './types/src/backend/utils/build-feature'
export * from './types/src/backend/utils/layout-element-parser'
export * from './types/src/frontend/utils/overridable-component'

export { default as Router } from './types/src/backend/router'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "admin-bro",
"version": "3.1.2",
"version": "3.2.0",
"description": "Admin panel for apps written in node.js",
"main": "index.js",
"types": "index.d.ts",
Expand Down
12 changes: 8 additions & 4 deletions src/backend/actions/action.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ViewHelpers from '../utils/view-helpers'
import BaseRecord from '../adapters/base-record'
import BaseResource from '../adapters/base-resource'
import ActionDecorator from '../decorators/action-decorator'
import { LayoutElement } from '../utils/layout-element-parser'
import { LayoutElement, LayoutElementFunction } from '../utils/layout-element-parser'
import RecordJSON from '../decorators/record-json.interface'
import { NoticeMessage } from '../../frontend/store/with-notice'
import { TranslateFunctions } from '../../utils/translate-functions.factory'
Expand Down Expand Up @@ -583,6 +583,7 @@ export default interface Action <T extends ActionResponse> {
*
* This is an example of defining a layout
*
* ```
* const layout = [{ width: 1 / 2 }, [
* ['@H3', { children: 'Company data' }],
* 'companyName',
Expand All @@ -596,13 +597,16 @@ export default interface Action <T extends ActionResponse> {
* ]],
* ],
* ]
* ```
*
* Alternatively you can pass a function taking {@link CurrentAdmin} as an argument.
* This will allow you to show/hide given property for restricted users.
* Alternatively you can pass a {@link LayoutElementFunction function} taking
* {@link CurrentAdmin} as an argument. This will allow you to show/hide
* given property for restricted users.
*
* To see entire documentation and more examples visit {@link LayoutElement}
*
* @see LayoutElement
* @see LayoutElementFunction
*/
layout?: ((currentAdmin?: CurrentAdmin) => Array<LayoutElement>) | Array<LayoutElement>;
layout?: LayoutElementFunction | Array<LayoutElement>;
}
293 changes: 152 additions & 141 deletions src/backend/utils/layout-element-parser.ts
Original file line number Diff line number Diff line change
@@ -1,148 +1,8 @@
/* eslint-disable max-len */
import { BoxProps, HeaderProps, TextProps, BadgeProps, ButtonProps, LinkProps, LabelProps, IconProps } from '@admin-bro/design-system'
import { PropsWithChildren } from 'react'
import { CurrentAdmin } from '../../current-admin.interface'

/**
* @typedef {String | Array} LayoutElement
*
* @description
* {@link LayoutElement} is used to change the default layout of edit and show {@link Action actions}.
* You define the layout as an {@link Array<LayoutElement>} and AdminBro renders it with React components.
*
* You don't have to know React to create usable Layout for you actions but be sure
* to take a look at the possible **Props** which can be used to style the components.
* The most often used props are {@link BoxProps}, because {@link Box} is the default wrapper.
*
* ### Available values for a {@link LayoutElement} type
*
* To {@link Action#layout } you have to pass an {@link Array<LayoutElement>}. Where each
* {@link LayoutElement} could have a different type defining its position and purpose.
*
* ### Type definition
*
* Those are available types of
*
* | Type | Purpose | Example |
* |---------------|--------------------------------------------------------------|------------------|
* | string | It will be changed to the property in vertical layout | `layout: ['name']` |
* | Array<string> | It will be changed to the properties in vertical layout | `layout: [['name', 'surname']]` |
* | [string, {@link BoxProps}] | property wrapped by {@link Box} component with {@link BoxProps} | `layout: [['name', {width: 1/2}]]` |
* | [{@link BoxProps}, Array<LayoutElement>] | Creates a Box and nest all the child LayoutElements inside. | `layout: [[{width: 1/2}, ['name', 'surname']]]` |
* | Array<LayoutElement> | For grouping LayoutElements inside a wrapper | `layout: [['name', {mt: 'xl'}], ['surname', , {ml: 'xl'}]]` |
* | [@ComponentName, PropsWithChildren<ComponentProps>] | if you precede first item with "@" it will create component of this name | `layout: [['@Header', {children: 'User Data'}]]` |
*
* ### Examples
*
* Let say you have following properties in your database: `companyName`, `email`, `address` and `companySize`
*
* 1. The simplest horizontal layout:
*
* ```
* const layout = [
* 'companyName',
* 'email',
* 'address',
* 'companySize',
* ]
* ```
*
* generates:
*
* <img src='./docs/layout1.png'>
*
* 2. Now Wrap everything with a {@link Box} of `2/3` max width and horizontal margin (mx)
* set to auto. This will center all inputs
*
* ```
* const layout = [
* [{ width: 2 / 3, mx: 'auto' }, [
* 'companyName',
* 'email',
* 'address',
* 'companySize',
* ]],
* ]
* ```
*
* > Hint: you can also pass an array to define how it will behave in a different responsive breakpoints.
*
* generates:
*
* <img src='./docs/layout2.png'>
*
* 3. Add headers between sections
*
* ```
* const layout = [
* [{ width: 2 / 3, mx: 'auto' }, [
* ['@H3', { children: 'Company data' }],
* 'companyName',
* 'companySize',
* ['@H3', { children: 'Contact Info' }],
* 'email',
* 'address',
* ]],
* ]
* ```
*
* > To inject content inside the given Component pass children props to it.
*
* generates:
*
* <img src='./docs/layout3.png'>
*
* 4. Make email and address 50% width
*
* > We will wrap them with a Box (default component) which is a flex. Then we will have to wrap also each of them
* with extra box to define paddings.
*
* I will also align to left top section that by removing `{ mx: auto }` and changing width to `1 / 2`.
*
* const layout = [{ width: 1 / 2 }, [
* ['@H3', { children: 'Company data' }],
* 'companyName',
* 'companySize',
* ]],
* [
* ['@H3', { children: 'Contact Info' }],
* [{ flexDirection: 'row', flex: true }, [
* ['email', { pr: 'default', flexGrow: 1 }],
* ['address', { flexGrow: 1 }],
* ]],
* ],
* ]
*
* generates:
*
* <img src='./docs/layout4.png'>
*
* 5. Lastly, take a look at the example with a function instead of {@link LayoutElement}.
*
* ```
* const layout = currentAdmin => ([
* ['@MessageBox', {
* message: `Welcome ${currentAdmin && currentAdmin.email}`,
* children: 'On this page yo can do whatever you like',
* variant: 'info',
* mb: 'xxl',
* }],
* [
* 'companyName',
* 'companySize',
* 'email',
* 'address',
* ],
* ])
* ```
*
* * generates following Show page:
*
* <img src='./docs/layout5.png'>
*
* @memberof Action
*/

// spacer for jsdoc
export type LayoutElement =
string |
Array<string> |
Expand All @@ -163,6 +23,15 @@ export type LayoutElement =
['@Icon', PropsWithChildren<IconProps>] |
[string, PropsWithChildren<any>]

/**
* Function returning Array<LayoutElement> used by {@link Action#layout}
*
* @return {Array<LayoutElement>}
* @memberof Action
* @alias LayoutElementFunction
*/
export type LayoutElementFunction = (currentAdmin?: CurrentAdmin) => Array<LayoutElement>

/**
* It is generated from {@link Array<LayoutElement>} passed in {@link Action#layout}
*
Expand Down Expand Up @@ -268,3 +137,145 @@ const layoutElementParser = (layoutElement: LayoutElement): ParsedLayoutElement
}

export default layoutElementParser


/**
* {@link LayoutElement} is used to change the default layout of edit and show {@link Action actions}.
* You define the layout as an {@link Array<LayoutElement>} and AdminBro renders it with React components.
*
* You don't have to know React to create usable Layout for you actions but be sure
* to take a look at the possible **Props** which can be used to style the components.
* The most often used props are {@link BoxProps}, because {@link Box} is the default wrapper.
*
* ### Available values for a {@link LayoutElement} type
*
* To {@link Action#layout } you have to pass an {@link Array<LayoutElement>}. Where each
* {@link LayoutElement} could have a different type defining its position and purpose.
*
* ### Type definition
*
* Those are available types for {@link LayoutElement}
*
* | Type | Purpose | Example |
* |---------------|--------------------------------------------------------------|------------------|
* | string | It will be changed to the property in vertical layout | `layout: ['name']` |
* | {@link Array<string>} | It will be changed to the properties in vertical layout | `layout: [['name', 'surname']]` |
* | [string, {@link BoxProps}] | property wrapped by {@link Box} component with {@link BoxProps} | `layout: [['name', {width: 1/2}]]` |
* | [{@link BoxProps}, {@link Array<LayoutElement>}] | Creates a Box and nest all the child LayoutElements inside. | `layout: [[{width: 1/2}, ['name', 'surname']]]` |
* | {@link Array<LayoutElement>} | For grouping LayoutElements inside a wrapper | `layout: [['name', {mt: 'xl'}], ['surname', , {ml: 'xl'}]]` |
* | [@ComponentName, PropsWithChildren<ComponentProps>] | if you precede first item with "@" it will create component of this name | `layout: [['@Header', {children: 'User Data'}]]` |
*
* ### Examples
*
* Let say you have following properties in your database: `companyName`, `email`, `address` and `companySize`
*
* #### 1. The simplest horizontal layout:
*
* ```
* const layout = [
* 'companyName',
* 'email',
* 'address',
* 'companySize',
* ]
* ```
*
* generates:
*
* <img src='./images/layout1.png' style="margin-bottom: 20px">
*
* #### 2. Now Wrap everything with a {@link Box} of `2/3` max width and horizontal margin (mx) set to auto. This will center all inputs
*
* ```
* const layout = [
* [{ width: 2 / 3, mx: 'auto' }, [
* 'companyName',
* 'email',
* 'address',
* 'companySize',
* ]],
* ]
* ```
*
* generates:
*
* <img src='./images/layout2.png'>
*
* > Hint: you can also pass an array to `width` to define how it will behave in a different responsive breakpoints.
*
* #### 3. Add headers between sections
*
* ```
* const layout = [
* [{ width: 2 / 3, mx: 'auto' }, [
* ['@H3', { children: 'Company data' }],
* 'companyName',
* 'companySize',
* ['@H3', { children: 'Contact Info' }],
* 'email',
* 'address',
* ]],
* ]
* ```
*
* generates:
*
* <img src='./images/layout3.png' style="margin-bottom: 20px" >
*
* > To inject content inside the given Component pass children props to it.
*
* #### 4. Make email and address 50% width
*
* We will wrap them with a {@link Box} (default component) which is a flex.
* Then we will have to wrap also each of them with extra box to define paddings.
*
* I will also align to left top section that by removing `{ mx: auto }` and changing width to `1 / 2`.
*
* ```
* const layout = [{ width: 1 / 2 }, [
* ['@H3', { children: 'Company data' }],
* 'companyName',
* 'companySize',
* ]],
* [
* ['@H3', { children: 'Contact Info' }],
* [{ flexDirection: 'row', flex: true }, [
* ['email', { pr: 'default', flexGrow: 1 }],
* ['address', { flexGrow: 1 }],
* ]],
* ],
* ]
* ```
*
* generates:
*
* <img src='./images/layout4.png' style="margin-bottom: 20px">
*
* #### 5. Lastly, take a look at the example with a function instead of {@link LayoutElement}.
*
* ```
* const layout = currentAdmin => ([
* ['@MessageBox', {
* message: `Welcome ${currentAdmin && currentAdmin.email}`,
* children: 'On this page yo can do whatever you like',
* variant: 'info',
* mb: 'xxl',
* }],
* [
* 'companyName',
* 'companySize',
* 'email',
* 'address',
* ],
* ])
* ```
*
* Generates following **Show** page:
*
* <img src='./images/layout5.png'>
*
* @name LayoutElement
* @typedef {String | Array} LayoutElement
* @memberof Action
* @alias LayoutElement
*/

0 comments on commit a73e727

Please sign in to comment.