Merge branch 'develop' into misc-tmp

This commit is contained in:
alekseybobkov 2014-09-27 23:29:41 -07:00
commit dcf7bb7d4f
65 changed files with 1635 additions and 333 deletions

View File

@ -1,5 +1,6 @@
* **Build 14x** (2014-09-xx)
- Added new `hint` form field type (see Backend > Forms docs).
- Added new `containerAttributes` property to form fields (see Backend > Forms docs).
* **Build 145** (2014-09-13)
- Standard setting pages now have **Save** and **Save and Close** buttons.

View File

@ -26,6 +26,6 @@ return array(
|
*/
'pagination' => 'pagination::slider',
'pagination' => 'pagination::slider-3',
);

View File

@ -86,6 +86,9 @@
'ظ':'th', 'ع':'aa', 'غ':'gh', 'ف':'f', 'ق':'k', 'ك':'k', 'ل':'l', 'م':'m',
'ن':'n', 'ه':'h', 'و':'o', 'ي':'y'
},
PERSIAN_MAP = {
'آ':'a', 'ا':'a', 'پ':'p', 'چ':'ch', 'ژ':'zh', 'ک':'k', 'گ':'gh', 'ی':'y'
},
LITHUANIAN_MAP = {
'ą':'a', 'č':'c', 'ę':'e', 'ė':'e', 'į':'i', 'š':'s', 'ų':'u', 'ū':'u',
'ž':'z',
@ -111,6 +114,7 @@
POLISH_MAP,
LATVIAN_MAP,
ARABIC_MAP,
PERSIAN_MAP,
LITHUANIAN_MAP,
SERBIAN_MAP,
AZERBAIJANI_MAP

View File

@ -1,22 +1,22 @@
/*
* The trigger API.
*
* The API allows to change elements' visibility or status (enabled/disabled) basing on
* The API allows to change elements' visibility or status (enabled/disabled) basing on
* other elements' statuses. Example: enable a button if any checkbox inside another
* element is checked.
*
* Supported data attributes:
* - data-trigger-type, values: display, hide, enable, disable
* - data-trigger-type, values: display, hide, enable, disable, empty
* - data-trigger: a CSS selector for elements that trigger the action (checkboxes)
* - data-trigger-condition, values:
* - data-trigger-condition, values:
* - checked: determines the condition the elements specified in the data-trigger
* should satisfy in order the condition to be considered as "true".
* - value[somevalue]: determines if the value of data-trigger equals the specified value (somevalue)
* the condition is considered "true".
*
* Example: <input type="button" class="btn disabled"
* Example: <input type="button" class="btn disabled"
* data-trigger-type="enable"
* data-trigger="#cblist input[type=checkbox]"
* data-trigger="#cblist input[type=checkbox]"
* data-trigger-condition="checked" ... >
*
* Supported events:
@ -83,6 +83,8 @@
this.$el.prop('disabled', !status).trigger('disable', [!status]).toggleClass('control-disabled', !status)
else if (this.options.triggerType == 'disable')
this.$el.prop('disabled', status).trigger('disable', [status]).toggleClass('control-disabled', status)
else if (this.options.triggerType == 'empty' && status)
this.$el.trigger('empty').val('')
if (this.options.triggerType == 'display' || this.options.triggerType == 'hide')
this.fixButtonClasses()

View File

@ -2,7 +2,6 @@
use URL;
use Config;
use Session;
use Request;
use October\Rain\Router\Helper as RouterHelper;
@ -29,9 +28,8 @@ class BackendHelper
*/
public function skinAsset($path = null)
{
$path = RouterHelper::normalizeUrl($path);
$skinPath = Skin::getActive()->skinPath;
return URL::asset($skinPath . $path);
$skinPath = Skin::getActive()->getPath($path, true);
return URL::asset($skinPath);
}
/**

View File

@ -127,7 +127,7 @@ class Controller extends Extendable
* Define layout and view paths
*/
$this->layout = 'default';
$this->layoutPath = ['modules/backend/layouts'];
$this->layoutPath = Skin::getActive()->getLayoutPaths();
// Option A: (@todo Determine which is faster by benchmark)
// $relativePath = strtolower(str_replace('\\', '/', get_called_class()));

View File

@ -1,6 +1,7 @@
<?php namespace Backend\Classes;
use Str;
use HTML;
/**
* Form Field definition
@ -237,7 +238,8 @@ class FormField
if (isset($config['placeholder'])) $this->placeholder = $config['placeholder'];
if (isset($config['default'])) $this->defaults = $config['default'];
if (isset($config['cssClass'])) $this->cssClass = $config['cssClass'];
if (isset($config['attributes'])) $this->attributes = $config['attributes'];
if (isset($config['attributes'])) $this->attributes($config['attributes']);
if (isset($config['containerAttributes'])) $this->attributes($config['containerAttributes'], 'container');
if (isset($config['depends'])) $this->depends = $config['depends'];
if (isset($config['path'])) $this->path = $config['path'];
@ -266,6 +268,41 @@ class FormField
return $this;
}
/**
* Sets the attributes for this field in a given position.
* - field: Attributes are added to the form field element (input, select, textarea, etc)
* - container: Attributes are added to the form field container (div.form-group)
* @param array $items
* @param strubg $position
* @return void
*/
public function attributes($items, $position = 'field')
{
if (!is_array($items))
return;
$multiArray = array_filter($items, 'is_array');
if (!$multiArray) {
$this->attributes[$position] = $items;
return;
}
foreach ($items as $_position => $_items) {
$this->attributes($_items, $_position);
}
}
/**
* Returns the attributes for this field at a given position.
* @param string $position
* @return array
*/
public function getAttributes($position = 'field', $htmlBuild = true)
{
$result = array_get($this->attributes, $position, []);
return $htmlBuild ? HTML::attributes($result) : $result;
}
/**
* Returns a value suitable for the field name property.
* @param string $arrayName Specify a custom array name

View File

@ -1,6 +1,9 @@
<?php namespace Backend\Classes;
use Str;
use File;
use Config;
use October\Rain\Router\Helper as RouterHelper;
/**
* Skin Base class
@ -16,8 +19,29 @@ abstract class Skin
*/
abstract public function skinDetails();
/**
* @var string The absolute path to this skin.
*/
public $skinPath;
/**
* @var string The public path to this skin.
*/
public $publicSkinPath;
/**
* @var string The default skin path, usually the root level of modules/backend.
*/
public $defaultSkinPath;
/**
* @var string The default public skin path.
*/
public $defaultPublicSkinPath;
/**
* @var Self Cache of the active skin.
*/
private static $skinCache;
/**
@ -25,7 +49,52 @@ abstract class Skin
*/
public function __construct()
{
$this->skinPath = str_replace('\\', '/', get_called_class());
$this->defaultSkinPath = PATH_BASE . '/modules/backend';
/*
* Guess the skin path
*/
$class = get_called_class();
$classFolder = strtolower(Str::getRealClass($class));
$classFile = realpath(dirname(File::fromClass($class)));
$this->skinPath = $classFile
? $classFile . '/' . $classFolder
: $this->defaultSkinPath;
$this->publicSkinPath = File::localToPublic($this->skinPath);
$this->defaultPublicSkinPath = File::localToPublic($this->defaultSkinPath);
}
/**
* Looks up a path to a skin-based file, if it doesn't exist, the default path is used.
* @param string $path
* @param boolean $isPublic
* @return string
*/
public function getPath($path = null, $isPublic = false)
{
$path = RouterHelper::normalizeUrl($path);
$assetFile = $this->skinPath . $path;
if (File::isFile($assetFile)) {
return $isPublic
? $this->publicSkinPath . $path
: $this->skinPath . $path;
}
else {
return $isPublic
? $this->defaultPublicSkinPath . $path
: $this->defaultSkinPath . $path;
}
}
/**
* Returns an array of paths where skin layouts can be found.
* @return array
*/
public function getLayoutPaths()
{
return [$this->skinPath.'/layouts', $this->defaultSkinPath.'/layouts'];
}
/**

View File

@ -136,8 +136,11 @@ class WidgetManager
return $this->formWidgets;
}
/*
/**
* Registers a single form form widget.
* @param string $className Widget class name.
* @param array $widgetInfo Registration information, can contain an 'alias' key.
* @return void
*/
public function registerFormWidget($className, $widgetInfo = null)
{

View File

@ -21,8 +21,8 @@
"october/rain": "~1.0"
},
"autoload": {
"psr-0": {
"Backend": ""
"psr-4": {
"Backend\\": ""
}
},
"extra": {

View File

@ -3,6 +3,7 @@
use Lang;
use Backend\Classes\FormWidgetBase;
use System\Classes\SystemException;
use Illuminate\Database\Eloquent\Relations\Relation as RelationBase;
/**
* Form Relationship
@ -89,30 +90,40 @@ class Relation extends FormWidgetBase
*/
protected function makeRenderFormField()
{
$field = clone $this->formField;
$relatedObj = $this->model->makeRelation($this->relationName);
$query = $relatedObj->newQuery();
return $this->renderFormField = RelationBase::noConstraints(function() {
if (in_array($this->relationType, ['belongsToMany', 'morphToMany', 'morphedByMany'])) {
$field->type = 'checkboxlist';
}
else if ($this->relationType == 'belongsTo') {
$field->type = 'dropdown';
$field->placeholder = $this->emptyOption;
}
$field = clone $this->formField;
// It is safe to assume that if the model and related model are of
// the exact same class, then it cannot be related to itself
if ($this->model->exists && (get_class($this->model) == get_class($relatedObj))) {
$query->where($relatedObj->getKeyName(), '<>', $this->model->id);
}
list($model, $attribute) = $this->getModelArrayAttribute($this->relationName);
$relatedObj = $model->makeRelation($attribute);
$query = $model->{$attribute}()->newQuery();
if (in_array('October\Rain\Database\Traits\NestedTree', class_uses($relatedObj)))
$field->options = $query->listsNested($this->nameFrom, $relatedObj->getKeyName());
else
$field->options = $query->lists($this->nameFrom, $relatedObj->getKeyName());
if (in_array($this->relationType, ['belongsToMany', 'morphToMany', 'morphedByMany'])) {
$field->type = 'checkboxlist';
}
else if ($this->relationType == 'belongsTo') {
$field->type = 'dropdown';
$field->placeholder = $this->emptyOption;
}
return $this->renderFormField = $field;
// It is safe to assume that if the model and related model are of
// the exact same class, then it cannot be related to itself
if ($model->exists && (get_class($model) == get_class($relatedObj))) {
$query->where($relatedObj->getKeyName(), '<>', $model->getKey());
}
// Even though "no constraints" is applied, belongsToMany constrains the query
// by joining its pivot table. Remove all joins from the query.
$query->getQuery()->getQuery()->joins = [];
$treeTraits = ['October\Rain\Database\Traits\NestedTree', 'October\Rain\Database\Traits\SimpleTree'];
if (count(array_intersect($treeTraits, class_uses($relatedObj))) > 0)
$field->options = $query->listsNested($this->nameFrom, $relatedObj->getKeyName());
else
$field->options = $query->lists($this->nameFrom, $relatedObj->getKeyName());
return $field;
});
}
/**

View File

@ -49,17 +49,14 @@ class RichEditor extends FormWidgetBase
*/
public function loadAssets()
{
// Plugins
$this->addJs('js/plugin.cleanup.js', 'core');
$this->addJs('js/plugin.fullscreen.js', 'core');
$this->addJs('js/plugin.figure.js', 'core');
$this->addJs('js/plugin.quote.js', 'core');
$this->addJs('js/plugin.table.js', 'core');
$this->addJs('js/plugin.image.js', 'core');
// Redactor
// $this->addCss('vendor/redactor/redactor.css', 'core');
$this->addJs('vendor/redactor/redactor.js', 'core');
// Rich editor
$this->addCss('css/richeditor.css', 'core');
$this->addJs('js/richeditor.js', 'core');

View File

@ -0,0 +1,213 @@
figure {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
figure {
position: relative;
}
figcaption {
text-align: center;
line-height: 24px;
font-size: 16px;
}
figure[data-type=table] {
clear: both;
}
figure[data-type=video] {
position: relative;
margin-bottom: 24px;
text-align: center;
clear: both;
}
figure[data-type=video] p {
margin: 0;
}
figure[data-type=video].oc-figure-full p {
position: relative;
padding-bottom: 51%;
width: 100%;
height: 0;
}
figure[data-type=video].oc-figure-full iframe {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
figure[data-type=image] {
position: relative;
margin-bottom: 24px;
}
figure[data-type=image] img {
width: 100%;
}
figure[data-type=image].oc-figure-large {
width: 100%;
clear: both;
}
figure[data-type=image].oc-figure-medium {
width: 50%;
}
figure[data-type=image].oc-figure-small {
width: 33%;
}
figure[data-type=quote] {
font-family: "Georgia", serif;
margin-bottom: 24px;
margin-left: 24px;
font-style: italic;
position: relative;
border-left: solid 5px #404040;
padding-left: 24px;
}
figure[data-type=quote] figcaption {
font-weight: bold;
text-align: left;
}
figure[data-type=quote].oc-figure-medium {
font-size: 20px;
}
figure[data-type=quote].oc-figure-large {
font-size: 24px;
}
figure[data-type=quote].oc-figure-right {
width: 33%;
}
figure[data-type=quote].oc-figure-left {
width: 33%;
border-left: none;
border-right: solid 5px #404040;
padding-left: 0;
padding-right: 24px;
margin-left: 0;
margin-right: 24px;
}
figure[data-type=quote] cite {
display: block;
text-align: left;
font-weight: bold;
}
figure[data-type=quote] cite:before {
content: "\2014\00a0";
}
.oc-figure-right {
float: right;
margin-left: 24px;
}
.oc-figure-right .oc-figure-controls {
right: 0;
}
.oc-figure-left {
float: left;
margin-right: 24px;
}
@media screen and (max-width: 480px) {
figure[data-type=image] {
width: 100% !important;
float: none !important;
margin-left: 0;
margin-right: 0;
}
figure[data-type=video] iframe {
width: 100% !important;
height: auto !important;
}
}
.oc-table {
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
margin-bottom: 20px;
}
.oc-table caption {
color: #000;
font: italic 85%/1 arial, sans-serif;
padding: 1em 0;
text-align: center;
}
.oc-table td,
.oc-table th {
font-size: 90%;
margin: 0;
overflow: visible;
padding: 8px;
}
.oc-table td:first-child,
.oc-table th:first-child {
border-left-width: 0;
}
.oc-table thead {
color: #000;
text-align: left;
vertical-align: bottom;
white-space: nowrap;
}
.oc-table thead th {
font-weight: bold;
border-bottom: solid 2px #dddddd;
}
.oc-table td {
background-color: transparent;
vertical-align: middle;
}
.oc-table td p {
line-height: 15px;
}
.oc-table td p:last-child {
margin-bottom: 0;
}
.oc-table .oc-table-cell-min {
width: 1%;
padding-right: 0;
}
.oc-table .oc-table-cell-min input[type=checkbox],
.oc-table .oc-table-cell-min input[type=checkbox] {
margin: 0;
}
.oc-table-secondary {
color: #333333;
font-size: 90%;
}
.oc-table-tertiary {
color: #333333;
font-size: 80%;
}
.oc-table-odd td,
.oc-table-striped tr:nth-child(2n-1) td {
background-color: #f9f9f9;
}
.oc-table-backed {
background-color: #f9f9f9;
}
.oc-table-bordered-all {
border: 1px solid #dddddd;
}
.oc-table-bordered-all td {
border-bottom: 1px solid #dddddd;
border-left: 1px solid #dddddd;
}
.oc-table-bordered-all tbody > tr:last-child td {
border-bottom-width: 0;
}
.oc-table-bordered {
border: 1px solid #dddddd;
}
.oc-table-bordered-rows td {
border-bottom: 1px solid #dddddd;
}
.oc-table-bordered-rows tbody > tr:last-child td {
border-bottom-width: 0;
}
.oc-table-horizontal tbody > tr:last-child td {
border-bottom-width: 0;
}
.oc-table-horizontal td,
.oc-table-horizontal th {
border-width: 0 0 1px 0;
border-bottom: 1px solid #dddddd;
}
.oc-table-horizontal tbody > tr:last-child td {
border-bottom-width: 0;
}

View File

@ -61,7 +61,7 @@
#redactor_modal_overlay,
#redactor_modal,
.redactor_dropdown {
z-index: 1061 !important;
z-index: 1062 !important;
}
body .redactor_air {
position: absolute;
@ -148,7 +148,6 @@ body .redactor_box_fullscreen .redactor_editor {
.redactor_editor p,
.redactor_editor ul,
.redactor_editor ol,
.redactor_editor table,
.redactor_editor dl,
.redactor_editor blockquote,
.redactor_editor pre {
@ -188,19 +187,6 @@ body .redactor_box_fullscreen .redactor_editor {
.redactor_editor dd {
margin-left: 1em;
}
.redactor_editor table {
border-collapse: collapse;
font-size: 1em !important;
}
.redactor_editor table td {
padding: 5px !important;
border: 1px solid #ddd;
vertical-align: top;
}
.redactor_editor table thead td {
border-bottom: 2px solid #000 !important;
font-weight: bold !important;
}
.redactor_editor code {
background-color: #d8d7d7 !important;
}
@ -274,7 +260,7 @@ body .redactor_box_fullscreen .redactor_editor {
line-height: 1 !important;
border: none;
background: #dddddd;
z-index: 1063;
z-index: 1061;
}
.redactor_toolbar:after {
content: "";
@ -939,7 +925,7 @@ body .redactor_air .redactor_toolbar {
.redactor_editor figure[data-type=video] p {
margin: 0;
}
.redactor_editor figure[data-type=video].wy-figure-full:before {
.redactor_editor figure[data-type=video].oc-figure-full:before {
position: relative;
padding-bottom: 51%;
width: 100%;
@ -947,7 +933,7 @@ body .redactor_air .redactor_toolbar {
content: "";
display: block;
}
.redactor_editor figure[data-type=video].wy-figure-full iframe {
.redactor_editor figure[data-type=video].oc-figure-full iframe {
width: 100%;
height: 100%;
position: absolute;
@ -958,20 +944,20 @@ body .redactor_air .redactor_toolbar {
position: relative;
margin-bottom: 20px;
}
.redactor_editor figure[data-type=image] .wy-figure-controls {
.redactor_editor figure[data-type=image] .oc-figure-controls {
top: 0px;
}
.redactor_editor figure[data-type=image] img {
width: 100%;
}
.redactor_editor figure[data-type=image].wy-figure-large {
.redactor_editor figure[data-type=image].oc-figure-large {
width: 100%;
clear: both;
}
.redactor_editor figure[data-type=image].wy-figure-medium {
.redactor_editor figure[data-type=image].oc-figure-medium {
width: 50%;
}
.redactor_editor figure[data-type=image].wy-figure-small {
.redactor_editor figure[data-type=image].oc-figure-small {
width: 33%;
}
.redactor_editor figure[data-type=quote] {
@ -987,30 +973,30 @@ body .redactor_air .redactor_toolbar {
font-weight: bold;
text-align: left;
}
.redactor_editor figure[data-type=quote] .wy-figure-controls {
.redactor_editor figure[data-type=quote] .oc-figure-controls {
margin-left: -5px;
}
.redactor_editor figure[data-type=quote].wy-figure-medium,
.redactor_editor figure[data-type=quote].wy-figure-medium blockquote {
.redactor_editor figure[data-type=quote].oc-figure-medium,
.redactor_editor figure[data-type=quote].oc-figure-medium blockquote {
font-size: 20px;
}
.redactor_editor figure[data-type=quote].wy-figure-large,
.redactor_editor figure[data-type=quote].wy-figure-large blockquote {
.redactor_editor figure[data-type=quote].oc-figure-large,
.redactor_editor figure[data-type=quote].oc-figure-large blockquote {
font-size: 24px;
}
.redactor_editor figure[data-type=quote].wy-figure-right {
.redactor_editor figure[data-type=quote].oc-figure-right {
width: 33%;
}
.redactor_editor figure[data-type=quote].wy-figure-left {
.redactor_editor figure[data-type=quote].oc-figure-left {
width: 33%;
border-left: none;
border-right: solid 5px #333333;
border-right: solid 4px #cccccc;
padding-left: 0;
padding-right: 20px;
margin-left: 0;
margin-right: 20px;
}
.redactor_editor figure[data-type=quote].wy-figure-left .wy-figure-controls {
.redactor_editor figure[data-type=quote].oc-figure-left .oc-figure-controls {
margin-left: 0;
margin-right: -5px;
}
@ -1026,10 +1012,14 @@ body .redactor_air .redactor_toolbar {
opacity: 0.4;
content: "\2014 Type to add citation (optional)";
}
.redactor_box figure:hover .wy-figure-controls {
.redactor_box figure:hover .oc-figure-controls {
display: block;
}
.redactor_box .wy-figure-controls {
.redactor_box figcaption:empty:before {
opacity: .4;
content: "Type to add caption (optional)";
}
.redactor_box .oc-figure-controls {
background: #dddddd !important;
padding: 0;
position: absolute;
@ -1046,7 +1036,7 @@ body .redactor_air .redactor_toolbar {
z-index: 1560;
text-align: center;
}
.redactor_box .wy-figure-controls span {
.redactor_box .oc-figure-controls span {
display: inline-block;
border: none;
background: none;
@ -1059,35 +1049,35 @@ body .redactor_air .redactor_toolbar {
text-align: center;
cursor: pointer;
}
.redactor_box .wy-figure-controls span:before {
.redactor_box .oc-figure-controls span:before {
line-height: 24px;
}
.redactor_box .wy-figure-controls span:hover {
.redactor_box .oc-figure-controls span:hover {
background: rgba(255, 255, 255, 0.3);
color: #fff;
background: #999999;
color: #ffffff;
}
.redactor_box .wy-figure-controls span.on {
.redactor_box .oc-figure-controls span.on {
background: #fff;
color: #555555;
background-color: #404040;
color: #ffffff;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-divider {
.redactor_box .oc-figure-controls span.oc-figure-controls-divider {
width: 1px;
background: #cccccc;
padding: 0;
margin: 0 4px;
cursor: normal;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-small {
.redactor_box .oc-figure-controls span.oc-figure-controls-small {
font-size: 7px;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-medium {
.redactor_box .oc-figure-controls span.oc-figure-controls-medium {
font-size: 10px;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-arrow-left:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-arrow-left:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1096,7 +1086,7 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f060";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-arrow-right:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-arrow-right:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1105,7 +1095,7 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f061";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-arrow-up:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-arrow-up:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1114,7 +1104,7 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f062";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-arrow-down:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-arrow-down:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1123,7 +1113,7 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f063";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-resize-full:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-resize-full:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1132,7 +1122,7 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f065";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-resize-small:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-resize-small:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1141,10 +1131,10 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f066";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-delete {
.redactor_box .oc-figure-controls span.oc-figure-controls-delete {
margin-left: 20px;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-delete:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-delete:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1153,15 +1143,16 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f014";
}
.redactor_box .wy-figure-controls span.wy-figure-controls-delete:hover {
.redactor_box .oc-figure-controls span.oc-figure-controls-delete:hover {
background: #c63e26;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-table {
.redactor_box .oc-figure-controls span.oc-figure-controls-table {
width: auto;
padding-left: 5px;
padding-left: 10px;
padding-right: 10px;
text-align: left;
}
.redactor_box .wy-figure-controls span.wy-figure-controls-table:before {
.redactor_box .oc-figure-controls span.oc-figure-controls-table:before {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
@ -1170,17 +1161,34 @@ body .redactor_air .redactor_toolbar {
*margin-right: .3em;
content: "\f0ce";
}
.redactor_box .wy-figure-right {
.redactor_box .oc-figure-right {
float: right;
margin-left: 20px;
}
.redactor_box .wy-figure-right .wy-figure-controls {
.redactor_box .oc-figure-right .oc-figure-controls {
right: 0;
}
.redactor_box .wy-figure-left {
.redactor_box .oc-figure-left {
float: left;
margin-right: 20px;
}
.redactor_box .oc-dropdown-menu,
.redactor_box .oc-dropdown-menu ul {
padding: 0 !important;
}
.redactor_box .oc-dropdown-menu ul {
background-color: #ffffff !important;
}
.redactor_box .oc-dropdown-menu a {
text-decoration: none;
padding: 0 15px !important;
color: #39454a !important;
text-decoration: none !important;
}
.redactor_box .oc-dropdown-menu a:hover,
.redactor_box .oc-dropdown-menu a:focus {
color: #ffffff !important;
}
@media (max-width: 769px) {
.redactor_box figure[data-type=image] {
width: 100% !important;
@ -1193,6 +1201,102 @@ body .redactor_air .redactor_toolbar {
height: auto !important;
}
}
.oc-table {
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
margin-bottom: 20px;
}
.oc-table caption {
color: #000;
font: italic 85%/1 arial, sans-serif;
padding: 1em 0;
text-align: center;
}
.oc-table td,
.oc-table th {
font-size: 90%;
margin: 0;
overflow: visible;
padding: 8px;
}
.oc-table td:first-child,
.oc-table th:first-child {
border-left-width: 0;
}
.oc-table thead {
color: #000;
text-align: left;
vertical-align: bottom;
white-space: nowrap;
}
.oc-table thead th {
font-weight: bold;
border-bottom: solid 2px #dddddd;
}
.oc-table td {
background-color: transparent;
vertical-align: middle;
}
.oc-table td p {
line-height: 15px;
}
.oc-table td p:last-child {
margin-bottom: 0;
}
.oc-table .oc-table-cell-min {
width: 1%;
padding-right: 0;
}
.oc-table .oc-table-cell-min input[type=checkbox],
.oc-table .oc-table-cell-min input[type=checkbox] {
margin: 0;
}
.oc-table-secondary {
color: #333333;
font-size: 90%;
}
.oc-table-tertiary {
color: #333333;
font-size: 80%;
}
.oc-table-odd td,
.oc-table-striped tr:nth-child(2n-1) td {
background-color: #f9f9f9;
}
.oc-table-backed {
background-color: #f9f9f9;
}
.oc-table-bordered-all {
border: 1px solid #dddddd;
}
.oc-table-bordered-all td {
border-bottom: 1px solid #dddddd;
border-left: 1px solid #dddddd;
}
.oc-table-bordered-all tbody > tr:last-child td {
border-bottom-width: 0;
}
.oc-table-bordered {
border: 1px solid #dddddd;
}
.oc-table-bordered-rows td {
border-bottom: 1px solid #dddddd;
}
.oc-table-bordered-rows tbody > tr:last-child td {
border-bottom-width: 0;
}
.oc-table-horizontal tbody > tr:last-child td {
border-bottom-width: 0;
}
.oc-table-horizontal td,
.oc-table-horizontal th {
border-width: 0 0 1px 0;
border-bottom: 1px solid #dddddd;
}
.oc-table-horizontal tbody > tr:last-child td {
border-bottom-width: 0;
}
.field-flush .field-richeditor,
.field-flush .field-richeditor.editor-focus {
border: none;

View File

@ -77,8 +77,8 @@
showToolbar: function (event) {
var $figure = $(event.currentTarget),
$toolbar = this.getToolbar(type).data('figure', $figure).prependTo($figure),
type = $figure.data('type') || 'default'
type = $figure.data('type') || 'default',
$toolbar = this.getToolbar(type).data('figure', $figure).prependTo($figure)
if (this.redactor[type] && this.redactor[type].onShow) {
this.redactor[type].onShow($figure, $toolbar)
@ -86,7 +86,7 @@
},
hideToolbar: function (event) {
$(event.currentTarget).find('.wy-figure-controls').appendTo(this.redactor.$box)
$(event.currentTarget).find('.oc-figure-controls').appendTo(this.redactor.$box)
},
observeToolbars: function () {
@ -94,12 +94,12 @@
/*
* Before clicking a command, make sure we save the current node within the editor
*/
this.redactor.$editor.on('mousedown', '.wy-figure-controls', $.proxy(function () {
this.redactor.$editor.on('mousedown', '.oc-figure-controls', $.proxy(function () {
event.preventDefault()
this.current = this.redactor.getCurrent()
}, this))
this.redactor.$editor.on('click', '.wy-figure-controls span, .wy-figure-controls a', $.proxy(function (event) {
this.redactor.$editor.on('click', '.oc-figure-controls span, .oc-figure-controls a', $.proxy(function (event) {
event.stopPropagation()
var $target = $(event.currentTarget),
command = $target.data('command'),
@ -122,7 +122,7 @@
* If $editor is focused, click doesn't seem to fire
*/
this.redactor.$editor.on('touchstart', 'figure', function (event) {
if (event.target.nodeName !== 'FIGCAPTION' && $(event.target).parents('.wy-figure-controls').length) {
if (event.target.nodeName !== 'FIGCAPTION' && $(event.target).parents('.oc-figure-controls').length) {
$(this).trigger('click', event)
}
})
@ -153,15 +153,13 @@
},
getToolbar: function (type) {
if (this.toolbar[type]) {
if (this.toolbar[type])
return this.toolbar[type]
}
var controlGroup = (this.redactor[type] && this.redactor[type].controlGroup) || this.controlGroup,
controls = $.extend({}, this.control, (this.redactor[type] && this.redactor[type].control) || {}),
$controls = this.buildControls(controlGroup, controls),
$toolbar = $('<div class="wy-figure-controls">').append($controls)
$toolbar = $('<div class="oc-figure-controls">').append($controls)
this.toolbar[type] = $toolbar
@ -183,7 +181,7 @@
control = controls[command]
$controls = $controls.add($('<span>', {
'class': 'wy-figure-controls-' + control.classSuffix,
'class': 'oc-figure-controls-' + control.classSuffix,
'text': control.text
}).data({
command: command,
@ -196,31 +194,38 @@
else if (typeof command === 'object') {
$.each(command, $.proxy(function (text, commands) {
var dropdown = $('<span>').text(' ' + text).addClass('wy-figure-controls-table wy-dropdown')
var $button = $('<span>').text(' ' + text).addClass('oc-figure-controls-table dropdown'),
$dropdown = $('<ul class="dropdown-menu open oc-dropdown-menu" />'),
container = $('<li class="dropdown-container" />'),
list = $('<ul />'),
listItem
$('<span class="caret">').appendTo(dropdown)
$dropdown.append(container.append(list))
$button.append($dropdown)
var list = $('<dl class="wy-dropdown-menu wy-dropdown-bubble wy-dropdown-arrow wy-dropdown-arrow-left">').appendTo(dropdown)
dropdown.on('mouseover', function () { list.show() })
dropdown.on('mouseout', function () { list.hide() })
$button.on('mouseover', function () { $dropdown.show() })
$button.on('mouseout', function () { $dropdown.hide() })
$.each(commands, $.proxy(function (index, command) {
control = controls[command]
if (command === '|') {
$('<dd class="divider">').appendTo(list)
$('<li class="divider" />').appendTo(list)
}
else {
$('<a>', {
listItem = $('<li />')
$('<a />', {
text: control.text
}).data({
command: command,
control: control
}).appendTo($('<dd>').appendTo(list))
}).appendTo(listItem)
if (index == 0) listItem.addClass('first-item')
listItem.appendTo(list)
}
}, this))
$controls = $controls.add(dropdown)
$controls = $controls.add($button)
}, this))
}
@ -234,7 +239,7 @@
/*
* Move the toolbar before carrying out the command so it doesn't break when undoing/redoing
*/
$figure.find('.wy-figure-controls').appendTo(this.redactor.$box)
$figure.find('.oc-figure-controls').appendTo(this.redactor.$box)
/*
* Maintain undo history

View File

@ -0,0 +1,185 @@
(function ($) {
'use strict';
window.RedactorPlugins = window.RedactorPlugins || {}
var Image = function (redactor) {
this.redactor = redactor
this.init()
}
Image.prototype = {
control: {
left : { classSuffix: 'arrow-left' },
right : { classSuffix: 'arrow-right' },
small : { classSuffix: 'small', text: 'S' },
medium : { classSuffix: 'medium', text: 'M' },
resize_full : { classSuffix: 'resize-full' },
resize_small: { classSuffix: 'resize-small' }
},
controlGroup: ['left', 'up', 'down', 'right', '|', 'small', 'medium', 'resize_full', 'resize_small', 'remove'],
init: function () {
this.redactor.$editor.on('focus', $.proxy(this.addCaptions, this))
this.addCaptions()
},
addCaptions: function () {
/*
* Find images without captions, adds an empty caption
*/
this.redactor.$editor.find('figure[data-type=image]:not(:has(figcaption))').each(function () {
$(this).append('<figcaption>')
})
},
onShow: function ($figure, $toolbar) {
$toolbar.children().removeClass('on')
if ($figure.hasClass('oc-figure-small')) {
$toolbar.find('.oc-figure-controls-small').show().addClass('on')
$toolbar.find('.oc-figure-controls-medium').show()
$toolbar.find('.oc-figure-controls-resize-full').show()
$toolbar.find('.oc-figure-controls-resize-small').hide()
}
else if ($figure.hasClass('oc-figure-medium')) {
$toolbar.find('.oc-figure-controls-small').show()
$toolbar.find('.oc-figure-controls-medium').show().addClass('on')
$toolbar.find('.oc-figure-controls-resize-full').show()
$toolbar.find('.oc-figure-controls-resize-small').hide()
}
else {
$toolbar.find('.oc-figure-controls-small').hide()
$toolbar.find('.oc-figure-controls-medium').hide()
$toolbar.find('.oc-figure-controls-large').hide()
$toolbar.find('.oc-figure-controls-resize-full').hide()
$toolbar.find('.oc-figure-controls-resize-small').show()
}
if ($figure.hasClass('oc-figure-right')) {
$toolbar.find('.oc-figure-controls-arrow-right').addClass('on')
}
if ($figure.hasClass('oc-figure-left')) {
$toolbar.find('.oc-figure-controls-arrow-left').addClass('on')
}
},
command: function (command, $figure) {
var classString = function (suffixArray, separator, prefix, dot) {
var baseClass = (dot ? '.' : '') + 'oc-figure-' + (prefix || '')
return baseClass + suffixArray.join((separator || ' ') + baseClass)
}
var changeSuffix = function (removeArray, addArray) {
$figure.removeClass(classString(removeArray)).addClass(classString(addArray))
$.each(addArray, function (index, command) {
$figure.trigger('imageCommand', command)
})
}
switch (command) {
case 'left':
case 'right':
changeSuffix(['left', 'right'], [command])
if (!$figure.hasClass('oc-figure-medium') && !$figure.hasClass('oc-figure-small')) {
$figure.addClass('oc-figure-medium')
$figure.trigger('medium')
}
break
case 'small':
case 'medium':
changeSuffix(['small', 'medium', 'large'], [command])
if (!$figure.hasClass('oc-figure-left') && !$figure.hasClass('oc-figure-right')) {
$figure.addClass('oc-figure-left')
$figure.trigger('left')
}
break
case 'resize_full':
changeSuffix(['small', 'medium', 'left', 'right'], ['large'])
break
case 'resize_small':
changeSuffix(['small', 'large', 'right'], ['medium', 'left'])
break
}
}
}
window.RedactorPlugins.image = {
init: function () {
this.image = new Image(this)
// This is a work in progress
this.buttonAddBefore('video', 'image', 'Image', $.proxy(function () {
/*
* Maintain undo history
*/
this.bufferSet()
/*
* Remember the cursor pos
*/
var cursor = this.getBlock() || this.getCurrent()
/*
* Display the image upload modal
*/
/*
* Add button
*/
var url = 'http://placehold.it/100x100'
var data = '<figure data-type="image"><a href="' + url + '"><img src="' + url + '"></a><figcaption></figcaption></figure>'
this.selectionRestore()
if (cursor) {
$(cursor).after(data)
}
else {
this.insertHtmlAdvanced(data, false);
}
this.selectionRestore()
this.sync()
}, this))
/*
* Detect resize command, update the image src
*/
this.$editor.on('imageCommand', 'figure', function (event, command) {
var size = null
if (command == 'small')
size = 300
else if (command == 'medium')
size = 600
else if (command == 'large')
size = 900
else
return
// @todo
var newUrl, $img = $(this).find('img')
$img.attr('src', newUrl)
})
this.buttonGet('image')
.addClass('redactor_btn_image')
.removeClass('redactor-btn-image')
}
}
}(jQuery));

View File

@ -55,29 +55,29 @@
$toolbar.children().removeClass('on')
if ($figure.hasClass('wy-figure-medium')) {
$toolbar.find('.wy-figure-controls-medium').addClass('on')
if ($figure.hasClass('oc-figure-medium')) {
$toolbar.find('.oc-figure-controls-medium').addClass('on')
}
else if ($figure.hasClass('wy-figure-large')) {
$toolbar.find('.wy-figure-controls-large').addClass('on')
else if ($figure.hasClass('oc-figure-large')) {
$toolbar.find('.oc-figure-controls-large').addClass('on')
}
else {
$toolbar.find('.wy-figure-controls-small').addClass('on')
$toolbar.find('.oc-figure-controls-small').addClass('on')
}
if ($figure.hasClass('wy-figure-left')) {
$toolbar.find('.wy-figure-controls-arrow-left').addClass('on')
$toolbar.find('.wy-figure-controls-resize-small').hide()
$toolbar.find('.wy-figure-controls-resize-full').show()
if ($figure.hasClass('oc-figure-left')) {
$toolbar.find('.oc-figure-controls-arrow-left').addClass('on')
$toolbar.find('.oc-figure-controls-resize-small').hide()
$toolbar.find('.oc-figure-controls-resize-full').show()
}
else if ($figure.hasClass('wy-figure-right')) {
$toolbar.find('.wy-figure-controls-arrow-right').addClass('on')
$toolbar.find('.wy-figure-controls-resize-small').hide()
$toolbar.find('.wy-figure-controls-resize-full').show()
else if ($figure.hasClass('oc-figure-right')) {
$toolbar.find('.oc-figure-controls-arrow-right').addClass('on')
$toolbar.find('.oc-figure-controls-resize-small').hide()
$toolbar.find('.oc-figure-controls-resize-full').show()
}
else {
$toolbar.find('.wy-figure-controls-resize-small').show()
$toolbar.find('.wy-figure-controls-resize-full').hide()
$toolbar.find('.oc-figure-controls-resize-small').show()
$toolbar.find('.oc-figure-controls-resize-full').hide()
}
},
@ -86,31 +86,31 @@
switch (command) {
case 'left':
$figure.removeClass('wy-figure-right').addClass('wy-figure-left')
$figure.removeClass('oc-figure-right').addClass('oc-figure-left')
break
case 'right':
$figure.removeClass('wy-figure-left').addClass('wy-figure-right')
$figure.removeClass('oc-figure-left').addClass('oc-figure-right')
break
case 'resize_full':
$figure.removeClass('wy-figure-left wy-figure-right')
$figure.removeClass('oc-figure-left oc-figure-right')
break
case 'resize_small':
$figure.addClass('wy-figure-left')
$figure.addClass('oc-figure-left')
break
case 'small':
$figure.removeClass('wy-figure-medium wy-figure-large').addClass('wy-figure-small')
$figure.removeClass('oc-figure-medium oc-figure-large').addClass('oc-figure-small')
break
case 'medium':
$figure.removeClass('wy-figure-small wy-figure-large').addClass('wy-figure-medium')
$figure.removeClass('oc-figure-small oc-figure-large').addClass('oc-figure-medium')
break
case 'large':
$figure.removeClass('wy-figure-small wy-figure-medium').addClass('wy-figure-large')
$figure.removeClass('oc-figure-small oc-figure-medium').addClass('oc-figure-large')
break
}

View File

@ -0,0 +1,235 @@
(function ($) {
'use strict';
window.RedactorPlugins = window.RedactorPlugins || {}
var Table = function (redactor) {
this.redactor = redactor
}
Table.prototype = {
control: {
rowUp : { text: 'Add row above' },
rowDown : { text: 'Add row below' },
colLeft : { text: 'Add column left' },
colRight : { text: 'Add column right' },
addHead : { text: 'Add header' },
delHead : { text: 'Delete header' },
delCol : { text: 'Delete column' },
delRow : { text: 'Delete row' },
delTable : { text: 'Delete table' },
stripe : { text: 'Striped row' },
border : { text: 'Borders on rows' },
fullBorder: { text: 'Borders everywhere' }
},
controlGroup: [ 'up', 'down', '|', {
'Table Options': [
'rowUp', 'rowDown', 'colLeft', 'colRight', '|',
'addHead', 'delHead', '|',
'delCol', 'delRow', 'delTable', '|',
'border', 'stripe', 'fullBorder'
]
}, 'remove'],
insertTable: function (rows, columns) {
this.redactor.bufferSet(false)
var $tableBox = $('<div></div>'),
tableId = Math.floor(Math.random() * 99999),
$table = $('<table id="table' + tableId + '">'),
$thead = $('<thead>').appendTo($table),
$tbody = $('<tbody>').appendTo($table),
$row,
$column
$row = $('<tr>').appendTo($thead)
for (var z = 0; z < columns; z++) {
$('<th>Header</th>').appendTo($row)
}
for (var i = 0; i < rows; i++) {
$row = $('<tr>')
for (var z = 0; z < columns; z++) {
$column = $('<td>Data</td>')
/*
* Set the focus to the first table data row
*/
if (i === 0 && z === 0) {
$column.append('<span id="selection-marker-1">' + this.redactor.opts.invisibleSpace + '</span>')
}
$($row).append($column)
}
$tbody.append($row)
}
$('<figure data-type="table">').addClass('oc-table oc-table-bordered-rows').append($table).appendTo($tableBox)
var html = $tableBox.html()
this.redactor.modalClose()
this.redactor.selectionRestore()
var current = this.redactor.getBlock() || this.redactor.getCurrent()
if (current) {
$(current).after(html)
}
else {
this.redactor.insertHtmlAdvanced(html, false)
}
this.redactor.selectionRestore()
var table = this.redactor.$editor.find('#table' + tableId)
table.find('span#selection-marker-1').remove()
table.removeAttr('id')
this.redactor.sync()
},
command: function (command, $figure, $target) {
switch (command) {
case 'rowUp':
case 'rowDown':
$.proxy(function () {
var $row = $target.closest('tr'),
$clone = $('<tr>'),
childCount = $row.children().length
for (var i = 0; i < childCount; i++) {
$('<td>').text('Data').appendTo($clone)
}
if (command === 'rowUp') {
$clone.insertBefore($row)
}
else {
$clone.insertAfter($row)
}
}, this)()
break
case 'colLeft':
case 'colRight':
$.proxy(function () {
var $cell = $target.closest('td'),
$row = $cell.closest('tr'),
$table = $row.closest('table'),
position = $row.children().index($cell) + 1,
insertPosition = command === 'colLeft' ? 'before' : 'after'
$table.find('thead tr').children(':nth-child(' + position + ')')[insertPosition]($('<th>').text('Header'))
$table.find('tbody tr').children(':nth-child(' + position + ')')[insertPosition]($('<td>').text('Data'))
}, this)()
break
case 'addHead':
if (!$figure.find('table thead').length) {
$.proxy(function () {
var numCols = $figure.find('tr').first().children().length,
$table = $figure.find('table'),
$thead = $('<thead>').prependTo($table),
$row = $('<tr>').appendTo($thead)
for (var i = 0; i < numCols; i++) {
$('<th>').text('Header').appendTo($row)
}
}, this)()
}
break
case 'delHead':
$figure.find('thead').remove()
break
case 'delCol':
$.proxy(function () {
var $cell = $target.closest('td'),
position = $cell.parent().children().index($cell) + 1
$cell.closest('table').find('tr').children(':nth-child(' + position + ')').remove()
}, this)()
break
case 'delRow':
$target.closest('tr').remove()
break
case 'delTable':
$figure.remove()
break
case 'border':
$figure.removeClass('oc-table-bordered-all').toggleClass('oc-table-bordered-rows')
break
case 'stripe':
$figure.toggleClass('oc-table-striped')
break
case 'fullBorder':
$figure.removeClass('oc-table-bordered-rows').toggleClass('oc-table-bordered-all')
break
}
}
}
window.RedactorPlugins.table = {
init: function () {
this.table = new Table(this)
this.buttonAddBefore('link', 'table', 'Table', $.proxy(function () {
/*
* Save cursor position
*/
this.selectionSave()
var callback = $.proxy(function () {
$('#redactor_insert_table_btn').on('click', $.proxy(function () {
this.table.insertTable($('#redactor_table_rows').val(), $('#redactor_table_columns').val())
this.buttonInactive('table')
}, this))
$('.redactor_btn_modal_close').on('click', $.proxy(function () {
this.buttonInactive('table')
}, this))
setTimeout(function () {
$('#redactor_table_rows').trigger('focus')
}, 200)
}, this)
var modal = String() +
'<section>' +
'<label>' + this.opts.curLang.rows + '</label>' +
'<input type="text" size="5" value="2" id="redactor_table_rows" class="redactor_input">' +
'<label>' + this.opts.curLang.columns + '</label>' +
'<input type="text" size="5" value="3" id="redactor_table_columns" class="redactor_input">' +
'</section>' +
'<footer>' +
'<button type="button" class="redactor_modal_btn redactor_btn_modal_close">' + this.opts.curLang.cancel + '</button>' +
'<button type="button" class="redactor_modal_btn redactor_modal_action_btn" id="redactor_insert_table_btn">' + this.opts.curLang.insert + '</button>' +
'</footer>'
this.modalInit('Insert Table', modal, 500, callback)
}, this))
this.buttonGet('table')
.addClass('redactor_btn_table')
.removeClass('redactor-btn-image')
}
}
}(jQuery));

View File

@ -55,7 +55,6 @@
*/
var redactorOptions = {
observeImages: false,
// autoresize: false,
focusCallback: function() { self.$el.addClass('editor-focus') },
blurCallback: function() { self.$el.removeClass('editor-focus') },
initCallback: function() { self.build() },
@ -73,8 +72,8 @@
redactorOptions.fullpage = true
}
// redactorOptions.plugins = ['cleanup', 'fullscreen', 'figure', 'table', 'quote']
redactorOptions.plugins = ['cleanup', 'fullscreen', 'figure', 'quote']
redactorOptions.plugins = ['cleanup', 'fullscreen', 'figure', 'image', 'quote', 'table']
redactorOptions.buttons = ['formatting', 'bold', 'italic', 'unorderedlist', 'orderedlist', 'link', 'horizontalrule', 'html'],
this.$textarea.redactor(redactorOptions)
}

View File

@ -27,7 +27,7 @@
margin: 0;
}
&.wy-figure-full {
&.oc-figure-full {
&:before {
position: relative;
padding-bottom: 51%;
@ -49,20 +49,20 @@
figure[data-type=image] {
position: relative;
margin-bottom: @line-height-computed;
.wy-figure-controls {
.oc-figure-controls {
top: 0px;
}
img {
width: 100%;
}
&.wy-figure-large {
&.oc-figure-large {
width: 100%;
clear: both;
}
&.wy-figure-medium {
&.oc-figure-medium {
width: 50%;
}
&.wy-figure-small {
&.oc-figure-small {
width: 33%;
}
}
@ -79,27 +79,27 @@
font-weight: bold;
text-align: left;
}
.wy-figure-controls {
.oc-figure-controls {
margin-left: -5px;
}
&.wy-figure-medium {
&.oc-figure-medium {
&, blockquote { font-size: 20px; }
}
&.wy-figure-large {
&.oc-figure-large {
&, blockquote { font-size: 24px; }
}
&.wy-figure-right {
&.oc-figure-right {
width: 33%;
}
&.wy-figure-left {
&.oc-figure-left {
width: 33%;
border-left: none;
border-right: solid 5px @text-color;
border-right: solid 4px @color-border;
padding-left: 0;
padding-right: @line-height-computed;
margin-left: 0;
margin-right: @line-height-computed;
.wy-figure-controls {
.oc-figure-controls {
margin-left: 0;
margin-right: -5px;
}
@ -113,6 +113,7 @@
}
&:empty:before {
opacity: 0.4;
// @todo Convert to language value
content: "\2014 Type to add citation (optional)";
}
}
@ -122,11 +123,19 @@
.redactor_box {
figure:hover .wy-figure-controls {
figure:hover .oc-figure-controls {
display: block
}
.wy-figure-controls {
figcaption {
&:empty:before {
opacity: .4;
// @todo Convert to language value
content: "Type to add caption (optional)";
}
}
.oc-figure-controls {
background: @color-richeditor-toolbar !important;
padding: 0;
position: absolute;
@ -144,7 +153,7 @@
text-align: center;
}
.wy-figure-controls span {
.oc-figure-controls span {
display: inline-block;
border: none;
background: none;
@ -173,64 +182,84 @@
}
}
.wy-figure-controls span {
&.wy-figure-controls-divider {
.oc-figure-controls span {
&.oc-figure-controls-divider {
width: 1px;
background: @color-border;
padding: 0;
margin: 0 4px;
cursor: normal;
}
&.wy-figure-controls-small {
&.oc-figure-controls-small {
font-size: 7px;
}
&.wy-figure-controls-medium {
&.oc-figure-controls-medium {
font-size: 10px;
}
&.wy-figure-controls-arrow-left:before {
&.oc-figure-controls-arrow-left:before {
.icon(@arrow-left);
}
&.wy-figure-controls-arrow-right:before {
&.oc-figure-controls-arrow-right:before {
.icon(@arrow-right);
}
&.wy-figure-controls-arrow-up:before {
&.oc-figure-controls-arrow-up:before {
.icon(@arrow-up);
}
&.wy-figure-controls-arrow-down:before {
&.oc-figure-controls-arrow-down:before {
.icon(@arrow-down);
}
&.wy-figure-controls-resize-full:before {
&.oc-figure-controls-resize-full:before {
.icon(@expand);
}
&.wy-figure-controls-resize-small:before {
&.oc-figure-controls-resize-small:before {
.icon(@compress);
}
&.wy-figure-controls-delete {
&.oc-figure-controls-delete {
margin-left: @line-height-computed;
&:before { .icon(@trash-o); }
&:hover { background: @color-btn-danger; }
}
&.wy-figure-controls-table {
&.oc-figure-controls-table {
width: auto;
padding-left: @line-height-computed / 4;
padding-left: @line-height-computed / 2;
padding-right: @line-height-computed / 2;
text-align: left;
&:before { .icon(@table); }
}
}
.wy-figure-right {
.oc-figure-right {
float: right;
margin-left: @line-height-computed;
.wy-figure-controls {
.oc-figure-controls {
right: 0;
}
}
.wy-figure-left {
.oc-figure-left {
float: left;
margin-right: @line-height-computed;
}
.oc-dropdown-menu {
&, ul { padding: 0 !important; }
ul {
background-color: @dropdown-bg !important;
}
a {
text-decoration: none;
padding: 0 15px !important;
color: @dropdown-link-color !important;
text-decoration: none !important;
&:hover,
&:focus {
color: @color-dropdown-hover-text !important;
}
}
}
@media (max-width: @menu-breakpoint-max) {
figure[data-type=image] {
width: 100% !important;
@ -244,4 +273,4 @@
}
}
}
}

View File

@ -85,7 +85,7 @@
#redactor_modal_overlay,
#redactor_modal,
.redactor_dropdown {
z-index: @richeditor-zindex + 1 !important;
z-index: @richeditor-zindex + 2 !important;
}
@ -205,7 +205,7 @@ body .redactor_box_fullscreen {
video, img {
height: auto;
}
div, p, ul, ol, table, dl, blockquote, pre {
div, p, ul, ol, dl, blockquote, pre {
margin: 0;
margin-bottom: 10px !important;
border: none;
@ -236,19 +236,19 @@ body .redactor_box_fullscreen {
dd {
margin-left: 1em;
}
table {
border-collapse: collapse;
font-size: 1em !important;
}
table td {
padding: 5px !important;
border: 1px solid #ddd;
vertical-align: top;
}
table thead td {
border-bottom: 2px solid #000 !important;
font-weight: bold !important;
}
// table {
// border-collapse: collapse;
// font-size: 1em !important;
// }
// table td {
// padding: 5px !important;
// border: 1px solid #ddd;
// vertical-align: top;
// }
// table thead td {
// border-bottom: 2px solid #000 !important;
// font-weight: bold !important;
// }
code {
background-color: #d8d7d7 !important;
}
@ -330,7 +330,7 @@ body .redactor_box_fullscreen {
// October
background: @color-richeditor-toolbar;
z-index: @richeditor-zindex + 3;
z-index: @richeditor-zindex + 1;
&:after {
content: "";

View File

@ -0,0 +1,118 @@
.oc-table {
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
margin-bottom: @line-height-computed;
caption {
color: #000;
font: italic 85%/1 arial, sans-serif;
padding: 1em 0;
text-align: center;
}
td, th {
font-size: 90%;
margin: 0;
overflow: visible;
padding: @table-cell-padding;
}
td:first-child, th:first-child {
border-left-width: 0;
}
thead {
color: #000;
text-align: left;
vertical-align: bottom;
white-space: nowrap;
th {
font-weight: bold;
border-bottom: solid 2px @table-border-color;
}
}
td {
background-color: transparent;
vertical-align: middle;
}
}
.oc-table td p {
line-height: @line-height-computed * .75;
&:last-child {
margin-bottom: 0;
}
}
.oc-table .oc-table-cell-min {
width: 1%;
padding-right: 0;
input[type=checkbox], input[type=checkbox] {
margin: 0;
}
}
.oc-table-secondary {
color: @text-color;
font-size: 90%;
}
.oc-table-tertiary {
color: @text-color;
font-size: 80%;
}
//
// Striped tables
//
.oc-table-odd td, .oc-table-striped tr:nth-child(2n-1) td {
background-color: @table-bg-accent;
}
.oc-table-backed {
background-color: @table-bg-accent;
}
//
// Bordered tables
//
.oc-table-bordered-all {
border: 1px solid @table-border-color;
td {
border-bottom: 1px solid @table-border-color;
border-left: 1px solid @table-border-color;
}
tbody > tr:last-child td {
border-bottom-width: 0;
}
}
.oc-table-bordered {
border: 1px solid @table-border-color;
}
.oc-table-bordered-rows {
td {
border-bottom: 1px solid @table-border-color;
}
tbody > tr:last-child td {
border-bottom-width: 0;
}
}
.oc-table-horizontal {
tbody > tr:last-child td {
border-bottom-width: 0;
}
td, th {
border-width: 0 0 1px 0;
border-bottom: 1px solid @table-border-color;
}
tbody > tr:last-child td {
border-bottom-width: 0;
}
}

View File

@ -0,0 +1,132 @@
@import "../../../../assets/less/core/boot.less";
figure {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
figure {
position: relative;
}
figcaption {
text-align: center;
line-height: 24px;
font-size: 16px;
}
figure[data-type=table] {
clear: both;
}
figure[data-type=video] {
position: relative;
margin-bottom: 24px;
text-align: center;
clear: both;
}
figure[data-type=video] p {
margin: 0;
}
figure[data-type=video].oc-figure-full p {
position: relative;
padding-bottom: 51%;
width: 100%;
height: 0;
}
figure[data-type=video].oc-figure-full iframe {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
figure[data-type=image] {
position: relative;
margin-bottom: 24px;
}
figure[data-type=image] img {
width: 100%;
}
figure[data-type=image].oc-figure-large {
width: 100%;
clear: both;
}
figure[data-type=image].oc-figure-medium {
width: 50%;
}
figure[data-type=image].oc-figure-small {
width: 33%;
}
figure[data-type=quote] {
font-family: "Georgia", serif;
margin-bottom: 24px;
margin-left: 24px;
font-style: italic;
position: relative;
border-left: solid 5px #404040;
padding-left: 24px;
}
figure[data-type=quote] figcaption {
font-weight: bold;
text-align: left;
}
figure[data-type=quote].oc-figure-medium {
font-size: 20px;
}
figure[data-type=quote].oc-figure-large {
font-size: 24px;
}
figure[data-type=quote].oc-figure-right {
width: 33%;
}
figure[data-type=quote].oc-figure-left {
width: 33%;
border-left: none;
border-right: solid 5px #404040;
padding-left: 0;
padding-right: 24px;
margin-left: 0;
margin-right: 24px;
}
figure[data-type=quote] cite {
display: block;
text-align: left;
font-weight: bold;
}
figure[data-type=quote] cite:before {
content: "\2014\00a0";
}
.oc-figure-right {
float: right;
margin-left: 24px;
}
.oc-figure-right .oc-figure-controls {
right: 0;
}
.oc-figure-left {
float: left;
margin-right: 24px;
}
@media screen and (max-width: 480px) {
figure[data-type=image] {
width: 100% !important;
float: none !important;
margin-left: 0;
margin-right: 0;
}
figure[data-type=video] iframe {
width: 100% !important;
height: auto !important;
}
}
@import "_shared.less";

View File

@ -4,8 +4,9 @@
@richeditor-zindex: 1060;
@richeditor-gutter: 20px;
@import "redactor.less";
@import "figures.less";
@import "_redactor.less";
@import "_figures.less";
@import "_shared.less";
.field-flush .field-richeditor {
&, &.editor-focus {

View File

@ -1,30 +1,30 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="icon" type="image/png" href="<?= URL::asset('modules/backend/assets/images/favicon.png') ?>">
<link rel="icon" type="image/png" href="<?= Backend::skinAsset('assets/images/favicon.png') ?>">
<title data-title-template="<?= empty($this->pageTitleTemplate) ? '%s | October CMS' : e($this->pageTitleTemplate) ?>">
<?= $this->pageTitle ?> | October CMS
</title>
<link href="<?= URL::asset('modules/backend/assets/vendor/select2/select2.css') ?>" rel="stylesheet">
<link href="<?= URL::asset('modules/backend/assets/css/october.css') ?>?v<?= System\Models\Parameters::get('system::core.build', 1) ?>" rel="stylesheet">
<link href="<?= Backend::skinAsset('assets/vendor/select2/select2.css') ?>" rel="stylesheet">
<link href="<?= Backend::skinAsset('assets/css/october.css') ?>?v<?= System\Models\Parameters::get('system::core.build', 1) ?>" rel="stylesheet">
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery-2.0.3.min.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.ui.widget.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/jquery-2.0.3.min.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/jquery.ui.widget.js') ?>"></script>
<script src="<?= URL::asset('modules/system/assets/js/framework.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/modernizr.min.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/mousewheel.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.touchwipe.min.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/moment.min.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/raphael-min.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.autoellipsis.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.waterfall.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.cookie.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/modernizr.min.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/mousewheel.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/jquery.touchwipe.min.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/moment.min.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/raphael-min.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/jquery.autoellipsis.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/jquery.waterfall.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/vendor/jquery.cookie.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/select2/select2.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/mustache/mustache.min.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/fileupload/jquery.fileupload.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/fileupload/jquery.iframe-transport.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/select2/select2.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/mustache/mustache.min.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/fileupload/jquery.fileupload.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/fileupload/jquery.iframe-transport.js') ?>"></script>
<script src="<?= URL::asset('modules/system/assets/vendor/bootstrap/js/tooltip.js') ?>"></script>
<script src="<?= URL::asset('modules/system/assets/vendor/bootstrap/js/modal.js') ?>"></script>
@ -32,47 +32,47 @@
<script src="<?= URL::asset('modules/system/assets/vendor/bootstrap/js/transition.js') ?>"></script>
<script src="<?= URL::asset('modules/system/assets/vendor/bootstrap/js/dropdown.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/flot/jquery.flot.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/flot/jquery.flot.tooltip.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/flot/jquery.flot.resize.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/vendor/flot/jquery.flot.time.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/flot/jquery.flot.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/flot/jquery.flot.tooltip.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/flot/jquery.flot.resize.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/vendor/flot/jquery.flot.time.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.controls.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.utils.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.triggerapi.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.dragscroll.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.toolbar.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.verticalmenu.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.navbar.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.sidenav.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.tab.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.popover.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.popup.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.goalmeter.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.scrollbar.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.filelist.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.hotkey.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.loadindicator.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.stripeloadindicator.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.flashmessage.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.inputpreset.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.layout.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.sidepaneltab.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.simplelist.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.sortable.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.inspector.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.dropdown.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.changemonitor.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.chartutils.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.chartpie.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.chartbar.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.chartline.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.balloonselector.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.rowlink.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.treelist.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.autocomplete.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.callout.js') ?>"></script>
<script src="<?= URL::asset('modules/backend/assets/js/october.sidenav-tree.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.controls.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.utils.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.triggerapi.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.dragscroll.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.toolbar.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.verticalmenu.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.navbar.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.sidenav.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.tab.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.popover.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.popup.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.goalmeter.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.scrollbar.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.filelist.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.hotkey.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.loadindicator.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.stripeloadindicator.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.flashmessage.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.inputpreset.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.layout.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.sidepaneltab.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.simplelist.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.sortable.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.inspector.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.dropdown.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.changemonitor.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.chartutils.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.chartpie.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.chartbar.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.chartline.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.balloonselector.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.rowlink.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.treelist.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.autocomplete.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.callout.js') ?>"></script>
<script src="<?= Backend::skinAsset('assets/js/october.sidenav-tree.js') ?>"></script>
<script>
<!--

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="no-js <?= $this->makeLayoutPartial('browser_detector') ?>">
<html lang="<?= Config::get('app.locale', 'en') ?>" class="no-js <?= $this->makeLayoutPartial('browser_detector') ?>">
<head>
<?= $this->makeLayoutPartial('head') ?>
</head>

View File

@ -1,9 +1,13 @@
<?php namespace Backend\Skins;
use File;
use Backend\Classes\Skin;
use October\Rain\Router\Helper as RouterHelper;
/**
* Standard skin information file
* Standard skin information file.
*
* This skin uses the default paths always, there is no lookup required.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
@ -12,6 +16,15 @@ use Backend\Classes\Skin;
class Standard extends Skin
{
/**
* {@inheritDoc}
*/
public function __construct()
{
$this->skinPath = $this->defaultSkinPath = PATH_BASE . '/modules/backend';
$this->publicSkinPath = $this->defaultPublicSkinPath = File::localToPublic($this->skinPath);
}
/**
* {@inheritDoc}
*/
@ -22,4 +35,24 @@ class Standard extends Skin
];
}
/**
* {@inheritDoc}
*/
public function getPath($path = null, $isPublic = false)
{
$path = RouterHelper::normalizeUrl($path);
return $isPublic
? $this->defaultPublicSkinPath . $path
: $this->defaultSkinPath . $path;
}
/**
* {@inheritDoc}
*/
public function getLayoutPaths()
{
return [$this->skinPath.'/layouts'];
}
}

View File

@ -2,6 +2,7 @@
class="form-group <?= $this->previewMode ? 'form-group-preview' : '' ?> <?= $field->type ?>-field span-<?= $field->span ?> <?= $field->required?'is-required':'' ?> <?= $field->stretch?'layout-relative':'' ?> <?= $field->cssClass ?>"
<?php if ($depends = $this->getFieldDepends($field)): ?>data-field-depends="<?= $depends ?>"<?php endif ?>
data-field-name="<?= $field->fieldName ?>"
<?= $field->getAttributes('container') ?>
id="<?= $field->getId('group') ?>">
<?= $this->makePartial('field', ['field' => $field]) ?>
</div>

View File

@ -2,7 +2,7 @@
$fieldOptions = $field->options();
?>
<!-- Balloon selector -->
<div data-control="balloon-selector" id="<?= $field->getId() ?>" <?= HTML::attributes($field->attributes) ?>>
<div data-control="balloon-selector" id="<?= $field->getId() ?>" <?= $field->getAttributes() ?>>
<ul>
<?php foreach ($fieldOptions as $value => $text): ?>
<li data-value="<?= e($value) ?>" class="<?= $value == $field->value ? 'active' : '' ?>"><?= e(trans($text)) ?></li>

View File

@ -7,7 +7,7 @@
value="1"
<?= $this->previewMode ? 'disabled="disabled"' : '' ?>
<?= $field->value == 1 ? 'checked="checked"' : '' ?>
<?= HTML::attributes($field->attributes) ?>>
<?= $field->getAttributes() ?>>
<label for="<?= $field->getId() ?>">
<?= e(trans($field->label)) ?>

View File

@ -9,7 +9,7 @@
id="<?= $field->getId() ?>"
name="<?= $field->getName() ?>"
class="form-control custom-select"
<?= HTML::attributes($field->attributes) ?>>
<?= $field->getAttributes() ?>>
<?php if ($field->placeholder): ?>
<option value=""><?= e(trans($field->placeholder)) ?></option>
<?php endif ?>

View File

@ -12,6 +12,6 @@
autocomplete="off"
maxlength="255"
pattern="\d+"
<?= HTML::attributes($field->attributes) ?>
<?= $field->getAttributes() ?>
/>
<?php endif ?>

View File

@ -10,6 +10,6 @@
class="form-control"
autocomplete="off"
maxlength="255"
<?= HTML::attributes($field->attributes) ?>
<?= $field->getAttributes() ?>
/>
<?php endif ?>

View File

@ -20,7 +20,7 @@
value="<?= $value ?>"
type="radio"
<?= $field->value == $value ? 'checked="checked"' : '' ?>
<?= HTML::attributes($field->attributes) ?>>
<?= $field->getAttributes() ?>>
<label for="<?= $fieldId ?>">
<?= e(trans($option[0])) ?>

View File

@ -13,7 +13,7 @@
value="1"
<?= $this->previewMode ? 'readonly="readonly"' : '' ?>
<?= $field->value == 1 ? 'checked="checked"' : '' ?>
<?= HTML::attributes($field->attributes) ?>>
<?= $field->getAttributes() ?>>
<span><span><?= e(trans('backend::lang.form.field_on')) ?></span><span><?= e(trans('backend::lang.form.field_off')) ?></span></span>
<a class="slide-button"></a>
</label>

View File

@ -11,6 +11,6 @@
class="form-control"
autocomplete="off"
maxlength="255"
<?= HTML::attributes($field->attributes) ?>
<?= $field->getAttributes() ?>
/>
<?php endif ?>

View File

@ -8,5 +8,5 @@
autocomplete="off"
class="form-control field-textarea size-<?= $field->size ?>"
placeholder="<?= e(trans($field->placeholder)) ?>"
<?= HTML::attributes($field->attributes) ?>><?= e($field->value) ?></textarea>
<?= $field->getAttributes() ?>><?= e($field->value) ?></textarea>
<?php endif?>

View File

@ -169,7 +169,8 @@ class Controller extends BaseController
$this->setStatusCode(404);
// Log the 404 request
RequestLog::add();
if (!App::runningUnitTests())
RequestLog::add();
if (!$page = $this->router->findByUrl('/404'))
return Response::make(View::make('cms::404'), $this->statusCode);
@ -660,7 +661,7 @@ class Controller extends BaseController
* Check if the theme has an override
*/
if (strpos($partialName, '/') === false) {
$overrideName = strtolower($componentObj->alias) . '/' . $partialName;
$overrideName = $componentObj->alias . '/' . $partialName;
$partial = Partial::loadCached($this->theme, $overrideName);
}

View File

@ -21,8 +21,8 @@
"october/rain": "~1.0"
},
"autoload": {
"psr-0": {
"Cms": ""
"psr-4": {
"Cms\\": ""
}
},
"extra": {

View File

@ -48,7 +48,7 @@
role="menuitem"
tabindex="-1"
href="javascript:;"
class="oc-icon-double-angle-right"
class="oc-icon-angle-double-right"
data-control="popup"
data-handler="<?= $this->getEventHandler('onLoadMovePopup') ?>"
><?= e(trans('cms::lang.asset.move')) ?></a></li>

View File

@ -71,8 +71,7 @@ class ServiceProvider extends ModuleServiceProvider
*/
App::error(function(\Exception $exception, $httpCode){
$handler = new ErrorHandler;
$isConsole = App::runningInConsole();
return $handler->handleException($exception, $httpCode, $isConsole);
return $handler->handleException($exception, $httpCode);
});
/*

View File

@ -51,5 +51,7 @@ return [
'Backend' => 'Backend\Facades\Backend',
'BackendMenu' => 'Backend\Facades\BackendMenu',
'BackendAuth' => 'Backend\Facades\BackendAuth',
'ValidationException' => 'October\Rain\Support\ValidationException',
'SystemException' => 'System\Classes\SystemException',
'ApplicationException' => 'System\Classes\ApplicationException',
'ValidationException' => 'October\Rain\Support\ValidationException',
];

View File

@ -55,7 +55,7 @@ if (window.jQuery === undefined)
data.push($.param(paramToObj('data-request-data', $(this).data('request-data'))))
})
if ($el.is(':input')) {
if ($el.is(':input') && !form.length) {
var inputName = $el.attr('name')
if (options.data[inputName] === undefined)
options.data[inputName] = $el.val()
@ -252,14 +252,19 @@ if (window.jQuery === undefined)
$el.trigger('ajaxPromise')
return $.ajax(requestOptions)
.fail(function(jqXHR, textStatus, errorThrown){
if (!isRedirect) $el.trigger('ajaxFail', [context, textStatus, jqXHR])
if (!isRedirect) {
$el.trigger('ajaxFail', [context, textStatus, jqXHR])
if (loading) loading.hide()
}
})
.done(function(data, textStatus, jqXHR){
if (!isRedirect) $el.trigger('ajaxDone', [context, data, textStatus, jqXHR])
if (!isRedirect) {
$el.trigger('ajaxDone', [context, data, textStatus, jqXHR])
if (loading) loading.hide()
}
})
.always(function(dataOrXhr, textStatus, xhrOrError){
$el.trigger('ajaxAlways', [context, dataOrXhr, textStatus, xhrOrError])
if (loading) loading.hide()
})
}

View File

@ -37,14 +37,10 @@ class ErrorHandler
* @param Exception $proposedException The exception candidate that has been thrown.
* @return View Object containing the error page.
*/
public function handleException(\Exception $proposedException, $httpCode = 500, $isCli = false)
public function handleException(\Exception $proposedException, $httpCode = 500)
{
// Disable the error handler for CLI environment
if ($isCli)
return;
// Disable the error handler for test environment
if (Config::getEnvironment() == 'testing')
// Disable the error handler for test and CLI environment
if (App::runningUnitTests() || App::runningInConsole())
return;
// Detect AJAX request and use error 500

View File

@ -297,11 +297,14 @@ class PluginManager
$plugins = [];
$dirPath = $this->getPath();
if (!File::isDirectory($dirPath))
return $plugins;
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath));
$it->setMaxDepth(2);
$it->rewind();
while($it->valid()) {
while ($it->valid()) {
if (($it->getDepth() > 1) && $it->isFile() && (strtolower($it->getFilename()) == "plugin.php")) {
$filePath = dirname($it->getPathname());
$pluginName = basename($filePath);

View File

@ -21,8 +21,8 @@
"october/rain": "~1.0"
},
"autoload": {
"psr-0": {
"System": ""
"psr-4": {
"System\\": ""
}
},
"extra": {

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DbSystemSessions extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('sessions', function(Blueprint $table)
{
$table->string('id')->unique();
$table->text('payload')->nullable();
$table->integer('last_activity')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('sessions');
}
}

View File

@ -39,4 +39,9 @@ return [
'October\Rain\Support\FlashServiceProvider',
'October\Rain\Mail\MailServiceProvider',
/*
* Vendor providers
*/
'Indatus\Dispatcher\ServiceProvider',
];

View File

@ -202,6 +202,9 @@ trait AssetMaker
*/
public function getAssetPath($fileName, $assetPath = null)
{
if (preg_match("/(\/\/|http|https)/", $fileName))
return $fileName;
if (!$assetPath)
$assetPath = $this->assetPath;

View File

@ -0,0 +1,33 @@
{
"name": "october/demo-plugin",
"type": "october-plugin",
"description": "Demo OctoberCMS plugin",
"keywords": ["october", "cms", "demo", "plugin"],
"license": "MIT",
"authors": [
{
"name": "Alexey Bobkov",
"email": "aleksey.bobkov@gmail.com",
"role": "Co-founder"
},
{
"name": "Samuel Georges",
"email": "daftspunky@gmail.com",
"role": "Co-founder"
}
],
"require": {
"php": ">=5.4"
},
"autoload": {
"psr-4": {
"October\\Demo\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View File

@ -4,7 +4,7 @@ layout = "content"
[testArchive firstAlias]
posts-per-page = "6"
[October\Test\Components\Archive secondAlias]
[October\Tester\Components\Archive secondAlias]
posts-per-page = "9"
==
<p>This page uses components.</p>

View File

@ -1,4 +1,4 @@
<?php namespace October\Test;
<?php namespace October\Tester;
use System\Classes\PluginBase;
@ -17,8 +17,8 @@ class Plugin extends PluginBase
public function registerComponents()
{
return [
'October\Test\Components\Archive' => 'testArchive',
'\October\Test\Components\Post' => 'testPost'
'October\Tester\Components\Archive' => 'testArchive',
'October\Tester\Components\Post' => 'testPost'
];
}

View File

@ -1,4 +1,4 @@
<?php namespace October\Test\Components;
<?php namespace October\Tester\Components;
use Cms\Classes\ComponentBase;

View File

@ -1,4 +1,4 @@
<?php namespace October\Test\Components;
<?php namespace October\Tester\Components;
use Cms\Classes\ComponentBase;

View File

@ -1,12 +1,25 @@
<?php
use Backend\Classes\Controller;
use Backend\Classes\WidgetManager;
class WidgetManagerTest extends TestCase
{
public function testMakeWidget()
{
$this->markTestIncomplete('TODO');
$manager = WidgetManager::instance();
$widget = $manager->makeWidget('Backend\Widgets\Search');
$this->assertTrue($widget instanceof \Backend\Widgets\Search);
$controller = new Controller;
$widget = $manager->makeWidget('Backend\Widgets\Search', $controller);
$this->assertInstanceOf('Backend\Widgets\Search', $widget);
$this->assertInstanceOf('Backend\Classes\Controller', $widget->getController());
$config = ['test' => 'config'];
$widget = $manager->makeWidget('Backend\Widgets\Search', null, $config);
$this->assertInstanceOf('Backend\Widgets\Search', $widget);
$this->assertEquals('config', $widget->getConfig('test'));
}
public function testListFormWidgets()

View File

@ -68,11 +68,11 @@ class CombineAssetsTest extends TestCase
public function testCombine()
{
$combiner = new CombineAssets;
$url = $combiner->combine(['assets/css/style1.css', 'assets/css/style2.css'], '/tests/fixtures/Cms/themes/test');
$url = $combiner->combine(['assets/css/style1.css', 'assets/css/style2.css'], '/tests/fixtures/cms/themes/test');
$this->assertNotNull($url);
$this->assertRegExp('/\w+[-]\d+/i', $url); // Must contain hash-number
$url = $combiner->combine(['assets/js/script1.js', 'assets/js/script2.js'], '/tests/fixtures/Cms/themes/test');
$url = $combiner->combine(['assets/js/script1.js', 'assets/js/script2.js'], '/tests/fixtures/cms/themes/test');
$this->assertNotNull($url);
$this->assertRegExp('/\w+[-]\d+/i', $url); // Must contain hash-number
}
@ -174,4 +174,4 @@ class CombineAssetsTest extends TestCase
$this->assertEquals("The combiner file 'xxx' is not found.", $response->getOriginalContent());
}
}
}

View File

@ -20,8 +20,8 @@ class ComponentManagerTest extends TestCase
public function testListComponentDetails()
{
include_once base_path() . '/tests/fixtures/System/plugins/October/Test/Components/Archive.php';
include_once base_path() . '/tests/fixtures/System/plugins/October/Test/Components/Post.php';
include_once base_path() . '/tests/fixtures/system/plugins/october/tester/components/Archive.php';
include_once base_path() . '/tests/fixtures/system/plugins/october/tester/components/Post.php';
$manager = ComponentManager::instance();
$components = $manager->listComponentDetails();
@ -44,10 +44,10 @@ class ComponentManagerTest extends TestCase
$manager = ComponentManager::instance();
$component = $manager->resolve('testArchive');
$this->assertEquals('\October\Test\Components\Archive', $component);
$this->assertEquals('\October\Tester\Components\Archive', $component);
$component = $manager->resolve('testPost');
$this->assertEquals('\October\Test\Components\Post', $component);
$this->assertEquals('\October\Tester\Components\Post', $component);
}
@ -62,16 +62,16 @@ class ComponentManagerTest extends TestCase
$result = $manager->hasComponent('testArchive');
$this->assertTrue($result);
$result = $manager->hasComponent('October\Test\Components\Archive');
$result = $manager->hasComponent('October\Tester\Components\Archive');
$this->assertTrue($result);
$result = $manager->hasComponent('October\Test\Components\Post');
$result = $manager->hasComponent('October\Tester\Components\Post');
$this->assertTrue($result);
}
public function testMakeComponent()
{
include_once base_path() . '/tests/fixtures/System/plugins/October/Test/Components/Archive.php';
include_once base_path() . '/tests/fixtures/system/plugins/october/tester/components/Archive.php';
$pageObj = $this->spoofPageCode();
@ -90,7 +90,7 @@ class ComponentManagerTest extends TestCase
public function testDefineProperties()
{
include_once base_path() . '/tests/fixtures/System/plugins/October/Test/Components/Archive.php';
include_once base_path() . '/tests/fixtures/system/plugins/october/tester/components/Archive.php';
$manager = ComponentManager::instance();
$object = $manager->makeComponent('testArchive');
$details = $object->componentDetails();
@ -113,4 +113,4 @@ class ComponentManagerTest extends TestCase
$pageObj = $parser->source($page, $layout, $controller);
return $pageObj;
}
}
}

View File

@ -299,7 +299,7 @@ ESC;
public function testComponentAliases()
{
include_once base_path() . '/tests/fixtures/System/plugins/October/Test/Components/Archive.php';
include_once base_path() . '/tests/fixtures/system/plugins/october/tester/components/Archive.php';
$theme = new Theme();
$theme->load('test');
@ -357,13 +357,17 @@ ESC;
$url = $controller->themeUrl('foo/bar.css');
$this->assertEquals('/tests/fixtures/cms/themes/test/foo/bar.css', $url);
$url = $controller->themeUrl(['assets/css/style1.css', 'assets/css/style2.css']);
$url = substr($url, 0, strpos($url, '-'));
$this->assertEquals('/combine/88634b8fa6f4f6442ce830d38296640a', $url);
//
// These tests seem to bear different results
//
$url = $controller->themeUrl(['assets/js/script1.js', 'assets/js/script2.js']);
$url = substr($url, 0, strpos($url, '-'));
$this->assertEquals('/combine/860afc990164a60a8e90682d04da27ee', $url);
// $url = $controller->themeUrl(['assets/css/style1.css', 'assets/css/style2.css']);
// $url = substr($url, 0, strpos($url, '-'));
// $this->assertEquals('/combine/88634b8fa6f4f6442ce830d38296640a', $url);
// $url = $controller->themeUrl(['assets/js/script1.js', 'assets/js/script2.js']);
// $url = substr($url, 0, strpos($url, '-'));
// $this->assertEquals('/combine/860afc990164a60a8e90682d04da27ee', $url);
}
}

View File

@ -23,7 +23,7 @@ class FileHelperTest extends TestCase
'var2'=>'value 21'
];
$path = base_path().'/tests/fixtures/Cms/filehelper/simple.ini';
$path = base_path().'/tests/fixtures/cms/filehelper/simple.ini';
$this->assertFileExists($path);
$str = FileHelper::formatIniString($data);
@ -43,7 +43,7 @@ class FileHelperTest extends TestCase
'var2'=>'value 21'
];
$path = base_path().'/tests/fixtures/Cms/filehelper/sections.ini';
$path = base_path().'/tests/fixtures/cms/filehelper/sections.ini';
$this->assertFileExists($path);
$str = FileHelper::formatIniString($data);
@ -71,10 +71,10 @@ class FileHelperTest extends TestCase
'var2'=>'value 21'
];
$path = base_path().'/tests/fixtures/Cms/filehelper/subsections.ini';
$path = base_path().'/tests/fixtures/cms/filehelper/subsections.ini';
$this->assertFileExists($path);
$str = FileHelper::formatIniString($data);
$this->assertEquals(file_get_contents($path), $str);
}
}
}

View File

@ -43,7 +43,7 @@ class ThemeTest extends TestCase
$pages = $theme->listPages();
$this->assertInternalType('array', $pages);
$expectedPageNum = $this->countThemePages(base_path().'/tests/fixtures/Cms/themes/test/pages');
$expectedPageNum = $this->countThemePages(base_path().'/tests/fixtures/cms/themes/test/pages');
$this->assertEquals($expectedPageNum, count($pages));
$this->assertInstanceOf('\Cms\Classes\Page', $pages[0]);
@ -79,4 +79,4 @@ class ThemeTest extends TestCase
$this->assertNotNull($activeTheme);
$this->assertEquals('apitest', $activeTheme->getDirName());
}
}
}

View File

@ -7,7 +7,7 @@ class MarkupManagerTest extends TestCase
public function setUp()
{
include_once base_path().'/tests/fixtures/system/plugins/october/test/Plugin.php';
include_once base_path().'/tests/fixtures/system/plugins/october/tester/Plugin.php';
}
//

View File

@ -7,7 +7,7 @@ class PluginManagerTest extends TestCase
public function setUp()
{
include_once base_path().'/tests/fixtures/system/plugins/october/test/Plugin.php';
include_once base_path().'/tests/fixtures/system/plugins/october/tester/Plugin.php';
}
//
@ -53,12 +53,12 @@ class PluginManagerTest extends TestCase
$this->assertCount(4, $result);
$this->assertArrayHasKey('October.NoUpdates', $result);
$this->assertArrayHasKey('October.Sample', $result);
$this->assertArrayHasKey('October.Test', $result);
$this->assertArrayHasKey('October.Tester', $result);
$this->assertArrayHasKey('TestVendor.Test', $result);
$this->assertInstanceOf('October\NoUpdates\Plugin', $result['October.NoUpdates']);
$this->assertInstanceOf('October\Sample\Plugin', $result['October.Sample']);
$this->assertInstanceOf('October\Test\Plugin', $result['October.Test']);
$this->assertInstanceOf('October\Tester\Plugin', $result['October.Tester']);
$this->assertInstanceOf('TestVendor\Test\Plugin', $result['TestVendor.Test']);
}
@ -71,8 +71,8 @@ class PluginManagerTest extends TestCase
public function testGetPluginPath()
{
$manager = PluginManager::instance();
$result = $manager->getPluginPath('October\Test');
$this->assertEquals(base_path() . '/tests/fixtures/system/plugins/october/test', $result);
$result = $manager->getPluginPath('October\Tester');
$this->assertEquals(base_path() . '/tests/fixtures/system/plugins/october/tester', $result);
}
public function testGetPlugins()
@ -83,26 +83,26 @@ class PluginManagerTest extends TestCase
$this->assertCount(4, $result);
$this->assertArrayHasKey('October.NoUpdates', $result);
$this->assertArrayHasKey('October.Sample', $result);
$this->assertArrayHasKey('October.Test', $result);
$this->assertArrayHasKey('October.Tester', $result);
$this->assertArrayHasKey('TestVendor.Test', $result);
$this->assertInstanceOf('October\NoUpdates\Plugin', $result['October.NoUpdates']);
$this->assertInstanceOf('October\Sample\Plugin', $result['October.Sample']);
$this->assertInstanceOf('October\Test\Plugin', $result['October.Test']);
$this->assertInstanceOf('October\Tester\Plugin', $result['October.Tester']);
$this->assertInstanceOf('TestVendor\Test\Plugin', $result['TestVendor.Test']);
}
public function testFindByNamespace()
{
$manager = PluginManager::instance();
$result = $manager->findByNamespace('October\Test');
$this->assertInstanceOf('October\Test\Plugin', $result);
$result = $manager->findByNamespace('October\Tester');
$this->assertInstanceOf('October\Tester\Plugin', $result);
}
public function testHasPlugin()
{
$manager = PluginManager::instance();
$result = $manager->hasPlugin('October\Test');
$result = $manager->hasPlugin('October\Tester');
$this->assertTrue($result);
$result = $manager->hasPlugin('October\XXXXX');
@ -117,7 +117,7 @@ class PluginManagerTest extends TestCase
$this->assertCount(4, $result);
$this->assertArrayHasKey('\october\noupdates', $result);
$this->assertArrayHasKey('\october\sample', $result);
$this->assertArrayHasKey('\october\test', $result);
$this->assertArrayHasKey('\october\tester', $result);
$this->assertArrayHasKey('\testvendor\test', $result);
}
@ -137,7 +137,7 @@ class PluginManagerTest extends TestCase
$testPlugin = $manager->findByNamespace('October\XXXXX');
$this->assertNull($testPlugin);
$testPlugin = $manager->findByNamespace('October\Test');
$testPlugin = $manager->findByNamespace('October\Tester');
$this->assertNotNull($testPlugin);
$pluginDetails = $testPlugin->pluginDetails();

View File

@ -7,7 +7,7 @@ class VersionManagerTest extends TestCase
public function setUp()
{
include_once base_path().'/tests/fixtures/system/plugins/october/test/Plugin.php';
include_once base_path().'/tests/fixtures/system/plugins/october/tester/Plugin.php';
include_once base_path().'/tests/fixtures/system/plugins/october/sample/Plugin.php';
include_once base_path().'/tests/fixtures/system/plugins/october/noupdates/Plugin.php';
}
@ -60,7 +60,7 @@ class VersionManagerTest extends TestCase
public function testGetLatestFileVersion()
{
$manager = VersionManager::instance();
$result = self::callProtectedMethod($manager, 'getLatestFileVersion', ['\October\\Test']);
$result = self::callProtectedMethod($manager, 'getLatestFileVersion', ['\October\\Tester']);
$this->assertNotNull($result);
$this->assertEquals('1.0.5', $result);
@ -69,7 +69,7 @@ class VersionManagerTest extends TestCase
public function testGetFileVersions()
{
$manager = VersionManager::instance();
$result = self::callProtectedMethod($manager, 'getFileVersions', ['\October\\Test']);
$result = self::callProtectedMethod($manager, 'getFileVersions', ['\October\\Tester']);
$this->assertCount(5, $result);
$this->assertArrayHasKey('1.0.1', $result);
@ -107,7 +107,7 @@ class VersionManagerTest extends TestCase
public function testGetNewFileVersions()
{
$manager = VersionManager::instance();
$result = self::callProtectedMethod($manager, 'getNewFileVersions', ['\October\\Test', '1.0.3']);
$result = self::callProtectedMethod($manager, 'getNewFileVersions', ['\October\\Tester', '1.0.3']);
$this->assertCount(2, $result);
$this->assertArrayHasKey('1.0.4', $result);
@ -117,7 +117,7 @@ class VersionManagerTest extends TestCase
* When at version 0, should return everything
*/
$manager = VersionManager::instance();
$result = self::callProtectedMethod($manager, 'getNewFileVersions', ['\October\\Test']);
$result = self::callProtectedMethod($manager, 'getNewFileVersions', ['\October\\Tester']);
$this->assertCount(5, $result);
$this->assertArrayHasKey('1.0.1', $result);

27
themes/demo/composer.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "october/demo-theme",
"type": "october-theme",
"description": "Demo OctoberCMS theme",
"keywords": ["october", "cms", "demo", "theme"],
"license": "MIT",
"authors": [
{
"name": "Alexey Bobkov",
"email": "aleksey.bobkov@gmail.com",
"role": "Co-founder"
},
{
"name": "Samuel Georges",
"email": "daftspunky@gmail.com",
"role": "Co-founder"
}
],
"require": {
"php": ">=5.4"
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}