Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Widget code added.
- Loading branch information
Showing
6 changed files
with
213 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
<div data-control="toolbar"> | ||
<a href="<?= Backend::url('october/test/users/create') ?>" class="btn btn-primary oc-icon-plus">New User</a> | ||
</div> | ||
<div class="toolbar-item toolbar-primary"> | ||
<a href="<?= Backend::url('october/test/users/create') ?>" class="btn btn-primary oc-icon-plus">New User</a> | ||
</div> | ||
<div class="toolbar-item toolbar-primary"> | ||
<?= $this->dropdownWidget->render() ?> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,9 @@ | ||
# Test Plugin | ||
# Dropdown Widget | ||
|
||
This is a UI test plugin for OctoberCMS. Extract this archive to `/plugins/october/test` and click on **Playground** in the back-end area. | ||
This is a mirror of [Playground for OctoberCMS](https://github.com/daftspunk/oc-test-plugin) to demonstrate the dropdown widget. | ||
|
||
The following sections are explored, tested and demonstrated along with a list of the features used: | ||
### Introduction | ||
You can make filters using the filter option in OctoberCMS. But this does not include a dropdown filter. I needed this functionality and so made this widget to help achieve this. I am using this widget as part of the [Mobile plugin](http://octobercms.com/plugin/mohsin-mobile). | ||
|
||
### Test 1: People | ||
|
||
A Person "Has One" Phone (One to one relationship) | ||
|
||
1. Relation Controller | ||
1. Record Finder | ||
1. Proxy Form fields | ||
1. Date pickers | ||
1. Context-based Form fields | ||
1. List search policies `@todo` | ||
|
||
### Test 2: Posts | ||
|
||
A Post "Has Many" Comments (One to many relationship) | ||
|
||
1. Relation Controller | ||
1. Popup-based Form fields | ||
1. Rich Editor | ||
1. Dual Form Controller and List Controller | ||
1. HTML in comments | ||
1. Custom Delete workflow | ||
1. Repeater fields in comments popup | ||
|
||
### Test 3: Users | ||
|
||
User "Belongs To Many" Roles (Many to many relationship) | ||
|
||
1. Relation Controller (Standard, Pivot data, Pivot model) | ||
1. Image Uploaders (Single, Multi, File, Image) | ||
1. Number field | ||
1. No click list column | ||
1. Custom File model | ||
1. Form field partial | ||
1. Tag List in relation mode | ||
|
||
### Test 4: Countries | ||
|
||
A Country "Has Many" Posts "Through" a User (Has many through relationship) | ||
|
||
1. Checkbox list | ||
1. Default form field values | ||
1. Field dependency and filtering | ||
1. Repeater fields | ||
1. Tabs empty with no fields | ||
|
||
### Test 5: Reviews | ||
|
||
1. Reviews "Morph To" Plugins and Themes as Product (Polymorphic relationships) | ||
1. Meta "Morph To" Plugins and Themes as Product (Polymorphic relationships) | ||
1. Plugins and Themes "Morph Many" Reviews | ||
1. Plugins and Themes "Morph One" Meta | ||
1. Plugins should not create when Meta validation fails. | ||
|
||
### Test 6: Galleries | ||
|
||
1. Galleries are "Morphed By Many" Posts | ||
1. Posts "Morph To Many" Galleries | ||
|
||
### Test 7: Trees | ||
|
||
1. A Member uses a simple tree (parent-child) structure. | ||
1. A Category uses a simple tree structure, with sorting. | ||
1. A Channel uses a nested set tree structure. | ||
|
||
### Test 8: Attributes | ||
|
||
An Attribute is a single generic model with many relationship types. | ||
|
||
1. Posts "Belong To" (Attribute) Status (`general.status`). | ||
1. Countries "Belong To Many" (Attribute) Types (`general.types`). | ||
|
||
## Tests that need attention | ||
|
||
- An attach relation when required inside a tab does not make the tab active. | ||
|
||
- Proxy fields throw a nasty error when the relation is non existant. | ||
|
||
- Deleting multiple Comments from a Post (deferred) only deletes one comment. | ||
|
||
- Constrained relations should not appear in RecordFinder (Phone:is_active) and Relation Controller lists (Comment:is_visible). | ||
|
||
- Record Finder does not incorporate deferred bindings. | ||
|
||
- HasOne relations acting as HasMany will break the list completely. | ||
|
||
- Pivot model with required field doesn't show the asterisk on the form. | ||
|
||
## Incorporating functional tests | ||
|
||
- All relation controllers | ||
|
||
- Test that input preset API works on fields | ||
|
||
- Test that trigger API works on fields | ||
### Demonstration | ||
[![Video Demonstration](http://img.youtube.com/vi/qbrnvjOFvPI/0.jpg)](http://www.youtube.com/watch?v=qbrnvjOFvPI) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
<?php namespace October\Test\Widgets; | ||
|
||
use Backend\Classes\WidgetBase; | ||
|
||
class Dropdown extends WidgetBase | ||
{ | ||
/** | ||
* @var constant The default error for empty items list | ||
*/ | ||
const DEFAULT_ERROR = 'Items list empty. First add items to the related model.'; | ||
|
||
/** | ||
* @var string A unique alias to identify this widget. | ||
*/ | ||
protected $defaultAlias = 'dropdown'; | ||
|
||
/** | ||
* @var string Default error for empty items list | ||
*/ | ||
protected $defaultError = self::DEFAULT_ERROR; | ||
|
||
/** | ||
* @var integer The first item of index that shows in button | ||
*/ | ||
protected $index = 1; | ||
|
||
/** | ||
* @var array Cache List of items to show in dropdown | ||
*/ | ||
protected $listItems = []; | ||
|
||
public function __construct($controller, $listItems = [], $defaultError = self::DEFAULT_ERROR) | ||
{ | ||
parent::__construct($controller); | ||
$this -> listItems = $listItems; | ||
$this->defaultError = $defaultError; | ||
} | ||
|
||
/** | ||
* Renders the widget. | ||
*/ | ||
public function render() | ||
{ | ||
$this->prepareVars(); | ||
return $this->makePartial('dropdown'); | ||
} | ||
|
||
/** | ||
* Prepares the view data | ||
*/ | ||
public function prepareVars() | ||
{ | ||
$this->vars['index'] = $this->getActiveIndex(); | ||
$this->vars['items'] = $this->getListItems(); | ||
$this->vars['error_message'] = $this->defaultError; | ||
} | ||
|
||
public function onItemChange() | ||
{ | ||
/* | ||
* Save or reset dropdown index in session | ||
*/ | ||
$this->setActiveIndex(post('index')); | ||
$widgetId = '#' . $this -> getId(); | ||
$listId = '#' . $this->controller->listGetWidget()->getId(); | ||
$listRefreshData = $this->controller->listRefresh(); | ||
|
||
return [ | ||
$listId => $listRefreshData[$listId], | ||
$widgetId => $this->makePartial('dropdown', ['index' => $this->getActiveIndex(), 'items' => $this->getListItems()]) | ||
]; | ||
} | ||
|
||
/** | ||
* Gets the list items array for this widget instance. | ||
*/ | ||
public function getListItems() | ||
{ | ||
return $this->listItems; | ||
} | ||
|
||
/** | ||
* Sets the list items array for this widget instance. | ||
*/ | ||
public function setListItems($listItems) | ||
{ | ||
$this->listItems = $listItems; | ||
} | ||
|
||
/** | ||
* Gets the error message for this widget instance. | ||
*/ | ||
public function getErrorMessage() | ||
{ | ||
return $this->defaultError; | ||
} | ||
|
||
/** | ||
* Sets the error message for this widget instance. | ||
*/ | ||
public function setErrorMessage($message) | ||
{ | ||
$this->defaultError = $message; | ||
} | ||
|
||
/** | ||
* Returns an active index for this widget instance. | ||
*/ | ||
public function getActiveIndex() | ||
{ | ||
return $this->index = $this->getSession('index', 1); | ||
} | ||
|
||
/** | ||
* Sets an active index for this widget instance. | ||
*/ | ||
public function setActiveIndex($index) | ||
{ | ||
if ($index) { | ||
$this->putSession('index', $index); | ||
} | ||
else { | ||
$this->resetSession(); | ||
} | ||
|
||
$this->index = $index; | ||
} | ||
|
||
/** | ||
* Returns a value suitable for the field name property. | ||
* @return string | ||
*/ | ||
public function getName() | ||
{ | ||
return $this->alias . '[index]'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<div id="<?= $this->getId() ?>" data-control="toolbar"> | ||
<?php if (count($items) == 0): ?> | ||
<div class="callout fade in callout-success"> | ||
<div class="content"> | ||
<p><?php echo e(trans($this->getErrorMessage())) ?></p> | ||
</div> | ||
</div> | ||
<?php else: ?> | ||
<div class="dropdown dropdown-fixed"> | ||
<button | ||
id="parentDropdown" | ||
type="button" | ||
class="btn btn-default oc-icon-mobile" | ||
data-toggle="dropdown"> | ||
<span id="initialItem"><?php echo $items[$this->getActiveIndex()] ?><?php if (count($items) > 1): ?></span> <span class="caret"><?php endif ?> | ||
</button> | ||
<?php if (count($items) > 1): ?> | ||
<ul id="dropdownList" class="dropdown-menu" role="menu"> | ||
<?php foreach ($items as $k => $item): ?> | ||
<?php if ($k != $index): ?> | ||
<li role="presentation"> | ||
<a | ||
name="<?= $this->getName() ?>" | ||
data-request="<?= $this->getEventHandler('onItemChange') ?>" | ||
data-request-data="index: <?= $k ?>" | ||
data-stripe-load-indicator | ||
role="menuitem" | ||
tabindex="-1" | ||
href="#" | ||
class="oc-icon-android"> | ||
<?= $item ?> | ||
</a> | ||
</li> | ||
<?php endif ?> | ||
<?php endforeach ?> | ||
</ul> | ||
<?php endif ?> | ||
</div> | ||
<?php endif ?> | ||
</div> |