Skip to content

Commit

Permalink
[Sidebar] Add ability to add form fields to a sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
mauricewijnia committed May 13, 2019
1 parent 0bca945 commit fa53d22
Show file tree
Hide file tree
Showing 15 changed files with 919 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/vendor
/node_modules
/node_modules
/.vscode
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ Laraberg aims to provide an easy way to integrate the Gutenberg editor with your
- [Registering Blocks](#registering-blocks)
- [Registering Categories](#registering-categories)
- [Events](#events)
- [Sidebar](#sidebar)
- [Checkbox](#checkbox)
- [Radio](#radio)
- [Select](#select)
- [Text](#text)
- [Textarea](#textarea)
- [Missing Blocks](#missing-blocks)
- [Updating from 0.0.1 to 0.0.2-or-later](#updating-from-001-to-002-or-later)
- [Contributors](#contributors)
Expand Down Expand Up @@ -273,6 +279,77 @@ Laraberg implements Laravel events that you can use to implement your own listen
- VanOns\Laraberg\Events\ContentRendered
- VanOns\Laraberg\Events\ContentUpdated

## Sidebar

Laraberg provides a way to put your form fields in a seperate sidebar in the Gutenberg editor. This way you can let the editor take the entire screen while still having a place for your form fields. This is done by putting the input element in a parent element with the `.laraberg-sidebar` class. This is currently supported for the following input types:
- Checkbox
- Radio
- Select
- Text
- Textarea

For the labels Laraberg first checks if there is a label assigned to the element and will try to use that. If there is no label assigned it will check if there is a placeholder and use that as the label.

To enable the sidebar set the `sidebar` option to true when initializing Laraberg:
```js
Laraberg.init('[id_here]', { sidebar: true })
```

## Checkbox
```HTML
<div class="laraberg-sidebar">
...
<label for="article-public">Public</label>
<input id="article-public" name="public" type="checkbox">
</div>
```

## Radio

```HTML
<div class="laraberg-sidebar">
...
<label for="letter-a">A</label>
<input type="radio" name="letter" id="letter-a" value="a" checked>
<label for="letter-b">B</label>
<input type="radio" name="letter" id="letter-b" value="b">
<label for="letter-c">C</label>
<input type="radio" name="letter" id="letter-c" value="c">
</div>
```

## Select
```HTML
<div class="laraberg-sidebar">
...
<label for="article-month">Month</label>
<select id="article-month" name="month" class="uk-select uk-form-large ">
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
...
</select>
</div>
```

## Text
```HTML
<div class="laraberg-sidebar">
...
<input id="article-title" type="text" name="title" placeholder="Title" />
</div>
```

## Textarea
```HTML
<div class="laraberg-sidebar">
...
<textarea name="excerpt" id="article-excerpt" placeholder="Excerpt"></textarea>
</div>
```


# Missing Blocks

Since we have disabled direct file uploading, some of the media blocks require a media library to operate.
Expand Down
6 changes: 6 additions & 0 deletions public/css/laraberg.css
Original file line number Diff line number Diff line change
Expand Up @@ -20583,6 +20583,9 @@ body.toolbar-tray-open.toolbar-vertical.toolbar-fixed {
.laraberg__editor iframe {
border: 0;
max-width: 100%; }
.laraberg__editor .laraberg-sidebar-content {
padding: 15px;
margin: unset; }

.gutenberg__content .alignleft {
float: left;
Expand Down Expand Up @@ -20626,5 +20629,8 @@ body.toolbar-tray-open.toolbar-vertical.toolbar-fixed {
display: block;
padding-top: 50%; }

.laraberg-sidebar {
display: none; }


/*# sourceMappingURL=laraberg.css.map*/
2 changes: 1 addition & 1 deletion public/css/laraberg.css.map

Large diffs are not rendered by default.

572 changes: 569 additions & 3 deletions public/js/laraberg.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/js/laraberg.js.map

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion src/resources/js/lib/configure-editor.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { data } from '@frontkom/gutenberg-js'
import { editorSettings } from '../gutenberg/settings'
import { elementRendered } from './element-ready'
import sidebar from '../sidebar/sidebar'
import setupLaravelFilemanager from '../laravel-filemanager/laravel-filemanager'

/**
* Configures the editor according to the provided options object
* @param {Object} options
*/
export default function configureEditor (options) {
setupSubmit(editorSettings.target)
setupMedia(options)
setupSidebar(options)
setupSubmit(editorSettings.target)
if (options.maxHeight) { setMaxHeight(options.maxHeight) }
if (options.minHeight) { setMinHeight(options.minHeight) }
if (options.height) { setHeight(options.height) }
Expand Down Expand Up @@ -67,6 +69,12 @@ function setupMedia (options) {
}
}

function setupSidebar (options) {
if (options.sidebar) {
sidebar()
}
}

/**
* Makes sure the textarea value gets set to the editor content on submit
* @param {string} target the textarea to set the value of
Expand Down
26 changes: 26 additions & 0 deletions src/resources/js/sidebar/checkbox-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Input from './input'
const Checkbox = window.wp.components.CheckboxControl

export default class CheckboxInput extends Input {
constructor (props) {
super(props)
this.state = {
checked: this.props.element.checked
}
}

onChange (checked) {
this.props.element.checked = checked
this.setState({ checked: checked })
}

render () {
return (
<Checkbox
label={this.getLabel()}
value={this.props.element.value}
checked={this.state.checked}
onChange={this.onChange} />
)
}
}
24 changes: 24 additions & 0 deletions src/resources/js/sidebar/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const { element } = window.wp
const { Component } = element

export default class Input extends Component {
constructor (props) {
super(props)

this.getLabel = this.getLabel.bind(this)
this.onChange = this.onChange.bind(this)

this.state = {
value: this.props.element.value
}
}

getLabel () {
return (this.props.element.labels[0] || {}).innerText || this.props.element.placeholder
}

onChange (content) {
this.props.element.value = content
this.setState({ value: content })
}
}
67 changes: 67 additions & 0 deletions src/resources/js/sidebar/radio-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const { element } = window.wp
const { Component } = element
const Radio = window.wp.components.RadioControl

export default class RadioInput extends Component {
constructor (props) {
super(props)

this.getLabel = this.getLabel.bind(this)
this.getOptions = this.getOptions.bind(this)
this.getSelected = this.getSelected.bind(this)
this.onChange = this.onChange.bind(this)

this.state = {
options: this.getOptions(),
selected: this.getSelected()
}
}

onChange (option) {
this.props.options.forEach(radio => {
if (radio.value === option) radio.checked = true
})

this.setState({ selected: option })
}

getLabel (option) {
if (option.labels && option.labels[0]) {
return option.labels[0].innerText
} else {
return null
}
}

getOptions () {
return this.props.options.map(option => {
return {
label: this.getLabel(option),
value: option.value
}
})
}

getSelected () {
const options = this.props.options

let selected = null
Object.keys(options).some(key => {
if (options[key].checked) {
selected = options[key].value
return true
}
})

return selected
}

render () {
return (
<Radio
options={this.state.options}
selected={this.state.selected}
onChange={this.onChange} />
)
}
}
29 changes: 29 additions & 0 deletions src/resources/js/sidebar/select-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Input from './input'
const Select = window.wp.components.SelectControl

export default class SelectInput extends Input {
constructor (props) {
super(props)
this.getOptions = this.getOptions.bind(this)
}

getOptions () {
const element = this.props.element
return Object.keys(element.options).map(key => {
return {
label: element[key].text,
value: element[key].value
}
})
}

render () {
return (
<Select
label={this.getLabel()}
options={this.getOptions()}
value={this.state.value}
onChange={this.onChange} />
)
}
}
73 changes: 73 additions & 0 deletions src/resources/js/sidebar/sidebar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import CheckboxInput from './checkbox-input'
import RadioInput from './radio-input'
import SelectInput from './select-input'
import TextInput from './text-input'
import TextareaInput from './textarea-input'

const { registerPlugin } = window.wp.plugins
const { PluginSidebar } = window.wp.editPost
const el = window.wp.element.createElement

export default function () {
registerPlugin('laraberg-sidebar', {
render: () => {
return el(PluginSidebar, {
name: 'laraberg-sidebar',
icon: 'media-text',
title: 'Laraberg'
}, renderElements())
}
})
}

function getElements (selector) {
return Array.from(document.querySelectorAll(`.laraberg-sidebar ${selector}`))
}

function renderInputCheckbox (element, index) {
return <CheckboxInput key={index} element={element} />
}

function renderInputRadio (elements) {
return <RadioInput key={elements[0].name} options={elements} />
}

function renderInputSelect (element, index) {
return <SelectInput key={index} element={element} />
}

function renderInputText (element, index) {
return <TextInput key={index} element={element} />
}

function renderInputTextarea (element, index) {
return <TextareaInput key={index} element={element} />
}

function getRadios () {
const radios = getElements('input[type="radio"]')
let result = radios.reduce((object, radio) => {
if (!object[radio.name]) {
object[radio.name] = []
}
object[radio.name].push(radio)
return object
}, {})
return result
}

function renderElements () {
const elements = []
elements.push(getElements('input[type="text"]').map(renderInputText))
elements.push(getElements('input[type="checkbox"]').map(renderInputCheckbox))
elements.push(getElements('textarea').map(renderInputTextarea))
elements.push(getElements('select').map(renderInputSelect))

const radios = getRadios()
elements.push(Object.keys(radios).map(key => renderInputRadio(radios[key])))

return el('div',
{ className: 'plugin-sidebar-content laraberg-sidebar-content' },
elements
)
}
13 changes: 13 additions & 0 deletions src/resources/js/sidebar/text-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Input from './input'
const Text = window.wp.components.TextControl

export default class TextInput extends Input {
render () {
return (
<Text
label={this.getLabel()}
value={this.state.value}
onChange={this.onChange} />
)
}
}
Loading

0 comments on commit fa53d22

Please sign in to comment.