Commits

Christoffer Niska committed c4acb75

Added node administration and started to implement menus.

Comments (0)

Files changed (26)

 
 		return false;
 	}
+	
+	public function getVersion() 
+	{
+		return '0.9.1';	
+	}
 }

assets/css/cms.css

 	font-size: inherit;
 }
 
-.cms.bp .cms-content {
-	padding: 20px 0 20px 20px;
-}
-
 .cms.bp .cms-sidebar {
 	padding: 20px;
 }
 	Bootstrap theme style
 */
 
-.cms.boot form {
-	margin: 0 0 0 -20px;
-}
-
-.cms.boot .cms-content {
+.cms.boot.column2 .cms-content {
 	border-right: 1px solid #ccc;
-	padding: 20px 0 0 20px;
-}
-
-.cms.boot .cms-sidebar {
-	padding: 20px 20px 0 0;
 }
 
 .cms.boot .tags {
 }
 
 .cms.boot .actions {
-	border-radius: 0 0 0 6px;
-	-moz-border-radius: 0 0 0 6px;
-	-webkit-border-radius: 0 0 0 6px;
 	margin-bottom: 0;
 }

assets/js/es5-shim.min.js

+(function(n){"function"==typeof define?define(n):n()})(function(){function n(a){try{return Object.defineProperty(a,"sentinel",{}),"sentinel"in a}catch(d){}}if(!Function.prototype.bind)Function.prototype.bind=function(a){var d=this;if("function"!=typeof d)throw new TypeError;var b=p.call(arguments,1),c=function(){if(this instanceof c){var e=function(){};e.prototype=d.prototype;var e=new e,g=d.apply(e,b.concat(p.call(arguments)));return null!==g&&Object(g)===g?g:e}return d.apply(a,b.concat(p.call(arguments)))};
+return c};var l=Function.prototype.call,f=Object.prototype,p=Array.prototype.slice,m=l.bind(f.toString),h=l.bind(f.hasOwnProperty),t,u,q,r,o;if(o=h(f,"__defineGetter__"))t=l.bind(f.__defineGetter__),u=l.bind(f.__defineSetter__),q=l.bind(f.__lookupGetter__),r=l.bind(f.__lookupSetter__);if(!Array.isArray)Array.isArray=function(a){return"[object Array]"==m(a)};if(!Array.prototype.forEach)Array.prototype.forEach=function(a,d){var b=i(this),c=0,e=b.length>>>0;if("[object Function]"!=m(a))throw new TypeError;
+for(;c<e;)c in b&&a.call(d,b[c],c,b),c++};if(!Array.prototype.map)Array.prototype.map=function(a,d){var b=i(this),c=b.length>>>0,e=Array(c);if("[object Function]"!=m(a))throw new TypeError;for(var g=0;g<c;g++)g in b&&(e[g]=a.call(d,b[g],g,b));return e};if(!Array.prototype.filter)Array.prototype.filter=function(a,d){var b=i(this),c=b.length>>>0,e=[];if("[object Function]"!=m(a))throw new TypeError;for(var g=0;g<c;g++)g in b&&a.call(d,b[g],g,b)&&e.push(b[g]);return e};if(!Array.prototype.every)Array.prototype.every=
+function(a,d){var b=i(this),c=b.length>>>0;if("[object Function]"!=m(a))throw new TypeError;for(var e=0;e<c;e++)if(e in b&&!a.call(d,b[e],e,b))return!1;return!0};if(!Array.prototype.some)Array.prototype.some=function(a,d){var b=i(this),c=b.length>>>0;if("[object Function]"!=m(a))throw new TypeError;for(var e=0;e<c;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1};if(!Array.prototype.reduce)Array.prototype.reduce=function(a){var d=i(this),b=d.length>>>0;if("[object Function]"!=m(a))throw new TypeError;
+if(!b&&1==arguments.length)throw new TypeError;var c=0,e;if(2<=arguments.length)e=arguments[1];else{do{if(c in d){e=d[c++];break}if(++c>=b)throw new TypeError;}while(1)}for(;c<b;c++)c in d&&(e=a.call(void 0,e,d[c],c,d));return e};if(!Array.prototype.reduceRight)Array.prototype.reduceRight=function(a){var d=i(this),b=d.length>>>0;if("[object Function]"!=m(a))throw new TypeError;if(!b&&1==arguments.length)throw new TypeError;var c,b=b-1;if(2<=arguments.length)c=arguments[1];else{do{if(b in d){c=d[b--];
+break}if(0>--b)throw new TypeError;}while(1)}do b in this&&(c=a.call(void 0,c,d[b],b,d));while(b--);return c};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(a){var d=i(this),b=d.length>>>0;if(!b)return-1;var c=0;1<arguments.length&&(c=v(arguments[1]));for(c=0<=c?c:Math.max(0,b+c);c<b;c++)if(c in d&&d[c]===a)return c;return-1};if(!Array.prototype.lastIndexOf)Array.prototype.lastIndexOf=function(a){var d=i(this),b=d.length>>>0;if(!b)return-1;var c=b-1;1<arguments.length&&(c=Math.min(c,
+v(arguments[1])));for(c=0<=c?c:b-Math.abs(c);0<=c;c--)if(c in d&&a===d[c])return c;return-1};if(!Object.getPrototypeOf)Object.getPrototypeOf=function(a){return a.__proto__||(a.constructor?a.constructor.prototype:f)};if(!Object.getOwnPropertyDescriptor)Object.getOwnPropertyDescriptor=function(a,d){if("object"!=typeof a&&"function"!=typeof a||null===a)throw new TypeError("Object.getOwnPropertyDescriptor called on a non-object: "+a);if(h(a,d)){var b,c,e;b={enumerable:!0,configurable:!0};if(o){var g=
+a.__proto__;a.__proto__=f;c=q(a,d);e=r(a,d);a.__proto__=g;if(c||e){if(c)b.get=c;if(e)b.set=e;return b}}b.value=a[d];return b}};if(!Object.getOwnPropertyNames)Object.getOwnPropertyNames=function(a){return Object.keys(a)};if(!Object.create)Object.create=function(a,d){var b;if(null===a)b={__proto__:null};else{if("object"!=typeof a)throw new TypeError("typeof prototype["+typeof a+"] != 'object'");b=function(){};b.prototype=a;b=new b;b.__proto__=a}void 0!==d&&Object.defineProperties(b,d);return b};if(Object.defineProperty){var l=
+n({}),y="undefined"==typeof document||n(document.createElement("div"));if(!l||!y)var s=Object.defineProperty}if(!Object.defineProperty||s)Object.defineProperty=function(a,d,b){if("object"!=typeof a&&"function"!=typeof a||null===a)throw new TypeError("Object.defineProperty called on non-object: "+a);if("object"!=typeof b&&"function"!=typeof b||null===b)throw new TypeError("Property description must be an object: "+b);if(s)try{return s.call(Object,a,d,b)}catch(c){}if(h(b,"value"))if(o&&(q(a,d)||r(a,
+d))){var e=a.__proto__;a.__proto__=f;delete a[d];a[d]=b.value;a.__proto__=e}else a[d]=b.value;else{if(!o)throw new TypeError("getters & setters can not be defined on this javascript engine");h(b,"get")&&t(a,d,b.get);h(b,"set")&&u(a,d,b.set)}return a};if(!Object.defineProperties)Object.defineProperties=function(a,d){for(var b in d)h(d,b)&&Object.defineProperty(a,b,d[b]);return a};if(!Object.seal)Object.seal=function(a){return a};if(!Object.freeze)Object.freeze=function(a){return a};try{Object.freeze(function(){})}catch(D){Object.freeze=
+function(a){return function(d){return"function"==typeof d?d:a(d)}}(Object.freeze)}if(!Object.preventExtensions)Object.preventExtensions=function(a){return a};if(!Object.isSealed)Object.isSealed=function(){return!1};if(!Object.isFrozen)Object.isFrozen=function(){return!1};if(!Object.isExtensible)Object.isExtensible=function(a){if(Object(a)===a)throw new TypeError;for(var d="";h(a,d);)d+="?";a[d]=!0;var b=h(a,d);delete a[d];return b};if(!Object.keys){var w=!0,x="toString,toLocaleString,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,constructor".split(","),
+z=x.length,j;for(j in{toString:null})w=!1;Object.keys=function(a){if("object"!=typeof a&&"function"!=typeof a||null===a)throw new TypeError("Object.keys called on a non-object");var d=[],b;for(b in a)h(a,b)&&d.push(b);if(w)for(b=0;b<z;b++){var c=x[b];h(a,c)&&d.push(c)}return d}}if(!Date.prototype.toISOString||-1===(new Date(-621987552E5)).toISOString().indexOf("-000001"))Date.prototype.toISOString=function(){var a,d,b,c;if(!isFinite(this))throw new RangeError;a=[this.getUTCMonth()+1,this.getUTCDate(),
+this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];c=this.getUTCFullYear();c=(0>c?"-":9999<c?"+":"")+("00000"+Math.abs(c)).slice(0<=c&&9999>=c?-4:-6);for(d=a.length;d--;)b=a[d],10>b&&(a[d]="0"+b);return c+"-"+a.slice(0,2).join("-")+"T"+a.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};if(!Date.now)Date.now=function(){return(new Date).getTime()};if(!Date.prototype.toJSON)Date.prototype.toJSON=function(){if("function"!=typeof this.toISOString)throw new TypeError;return this.toISOString()};
+if(!Date.parse||864E13!==Date.parse("+275760-09-13T00:00:00.000Z"))Date=function(a){var d=function g(b,d,c,f,h,i,j){var k=arguments.length;return this instanceof a?(k=1==k&&""+b===b?new a(g.parse(b)):7<=k?new a(b,d,c,f,h,i,j):6<=k?new a(b,d,c,f,h,i):5<=k?new a(b,d,c,f,h):4<=k?new a(b,d,c,f):3<=k?new a(b,d,c):2<=k?new a(b,d):1<=k?new a(b):new a,k.constructor=g,k):a.apply(this,arguments)},b=RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$"),
+c;for(c in a)d[c]=a[c];d.now=a.now;d.UTC=a.UTC;d.prototype=a.prototype;d.prototype.constructor=d;d.parse=function(d){var c=b.exec(d);if(c){c.shift();for(var f=1;7>f;f++)c[f]=+(c[f]||(3>f?1:0)),1==f&&c[f]--;var h=+c.pop(),i=+c.pop(),j=c.pop(),f=0;if(j){if(23<i||59<h)return NaN;f=6E4*(60*i+h)*("+"==j?-1:1)}h=+c[0];return 0<=h&&99>=h?(c[0]=h+400,a.UTC.apply(this,c)+f-126227808E5):a.UTC.apply(this,c)+f}return a.parse.apply(this,arguments)};return d}(Date);j="\t\n\u000b\u000c\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff";
+if(!String.prototype.trim||j.trim()){j="["+j+"]";var A=RegExp("^"+j+j+"*"),B=RegExp(j+j+"*$");String.prototype.trim=function(){return(""+this).replace(A,"").replace(B,"")}}var v=function(a){a=+a;a!==a?a=0:0!==a&&a!==1/0&&a!==-(1/0)&&(a=(0<a||-1)*Math.floor(Math.abs(a)));return a},C="a"!="a"[0],i=function(a){if(null==a)throw new TypeError;return C&&"string"==typeof a&&a?a.split(""):Object(a)}});

components/CmsActiveRecord.php

 class CmsActiveRecord extends CActiveRecord
 {
 	/**
-	 * Actions to be taken before calling find.
+	 * @return array the default scope.
 	 */
-	public function beforeFind()
+	public function defaultScope()
 	{
+		$scope = parent::defaultScope();
+
 		if ($this->hasAttribute('deleted'))
 		{
-			$alias = $this->getTableAlias();
-			$attribute = $alias.'.deleted';
-			$criteria = $this->getDbCriteria();
+			$prefix = $this->getTableAlias(true, false);
+			$condition = $prefix . '.deleted=0';
 
-			if (strpos($criteria->condition, $attribute) === false)
-			{
-				$criteria->addCondition($attribute.'=0');
-				$this->setDbCriteria($criteria);
-			}
+			if (isset($scope['condition']))
+				$scope['condition'] .= ' AND ' . $condition;
+			else
+				$scope['condition'] = $condition;
 		}
+
+		return $scope;
 	}
-	
+
 	/**
-     * Actions to be taken before saving the record.
-	 * @return boolean
-     */
-    public function beforeSave()
-    {
+	 * Actions to be taken before saving the record.
+	 * @return boolean whether the record can be saved
+	 */
+	public function beforeSave()
+	{
 		if (parent::beforeSave())
 		{
 			$now = new CDbExpression('NOW()');
 			$userId = Yii::app()->user->id;
-			
-			// We are creating a new record.
+
 			if ($this->isNewRecord)
 			{
+				// We are creating a new record.
 				if ($this->hasAttribute('created'))
-				   $this->created = $now;
-				
+					$this->created = $now;
+
 				if ($this->hasAttribute('creatorId') && $userId !== null)
-				   $this->creatorId = $userId;
+					$this->creatorId = $userId;
 			}
-			// We are updating an existing record.
 			else
 			{
-				if ($this->hasAttribute('updated'))
-					$this->updated = $now;
-				
-				if ($this->hasAttribute('updaterId') && $userId !== null)
-				   $this->updaterId = $userId;
+				// We are updating an existing record.
+				if ($this->hasAttribute('modified'))
+					$this->modified = $now;
+
+				if ($this->hasAttribute('modifierId') && $userId !== null)
+					$this->modifierId = $userId;
 			}
 
 			return true;
 		}
 		else
 			return false;
-    }
+	}
 
 	/**
 	 * Actions to be taken before calling delete.
-	 * @return boolean
+	 * @param boolean $soft indicates whether to perform a "soft" delete
+	 * @return boolean whether the record can be deleted
 	 */
-	public function beforeDelete()
+	public function beforeDelete($soft)
 	{
-		if (parent::beforeDelete())
+		if (parent::beforeDelete() && $soft && $this->hasAttribute('deleted'))
 		{
-			if (!$this->hasAttribute('deleted'))
-				return true;
-
 			$this->deleted = 1;
 			$this->save(false);
+			return false;
 		}
+		else
+			return true;
+	}
 
-		return false;
+	/**
+	 * Deletes the row corresponding to this active record.
+	 * @param boolean $soft indicates whether to perform a "soft" delete
+	 * @return boolean whether the deletion is successful
+	 * @throws CException if the record is new
+	 */
+	public function delete($soft = true)
+	{
+		if (!$this->getIsNewRecord())
+		{
+			Yii::trace(get_class($this) . '.delete()', 'CmsActiveRecord');
+
+			if ($this->beforeDelete($soft))
+			{
+				$result = $this->deleteByPk($this->getPrimaryKey()) > 0;
+				$this->afterDelete();
+				return $result;
+			}
+			else
+				return false;
+		}
+		else
+			throw new CDbException('The active record cannot be deleted because it is new.');
 	}
 }

components/CmsController.php

 	/**
 	 * @property string the default layout for the controller view
 	 */
-	public $layout = '//layouts/column1';
+	public $layout = 'cms-column1';
 	/**
 	 * @property array context menu items
 	 */

controllers/AdminController.php

+<?php
+/**
+ * AdminController class file.
+ * @author Christoffer Niska <christoffer.niska@nordsoftware.com>
+ * @copyright Copyright &copy; 2011, Nord Software Ltd
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @package cms.controllers
+ * @since 0.9.1
+ */
+
+class AdminController extends CmsController
+{
+	public function actionIndex()
+	{
+		$nodeDp = new CActiveDataProvider('CmsNode', array(
+			'criteria'=>array(
+				'order'=>'parentId ASC, id ASC',
+			),
+		));
+
+		$this->render('index', array(
+			'nodeDp'=>$nodeDp,
+		));
+	}
+}

controllers/NodeController.php

  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  * @package cms.controllers
  */
+
 class NodeController extends CmsController
 {
 	/**
+	 * @property string the default layout for the controller view
+	 */
+	public $layout = 'cms-column2';
+
+	/**
 	 * @property string the name of the default action
 	 */
 	public $defaultAction = 'view';
-	/**
-	 * @string string the layout to use with this controller
-	 */
-	public $layout = 'cms';
 
 	/**
 	 * @return array the action filters for this controller.
 		));
 	}
 
+	public function actionIndex()
+	{
+		$nodeDp = new CActiveDataProvider('CmsNode', array(
+			'criteria'=>array(
+				'order'=>'parentId ASC, id ASC',
+			),
+		));
+
+		$this->layout = 'cms-column1';
+
+		$this->render('index', array(
+			'nodeDp'=>$nodeDp,
+		));
+	}
+
 	/**
 	 * Deletes a particular model.
 	 * If deletion is successful, the browser will be redirected to the 'admin' page.
   `byteSize` int(10) unsigned NOT NULL,
   PRIMARY KEY (`id`),
   KEY `contentId` (`contentId`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS `cms_menu` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) NOT NULL,
+  `created` timestamp NULL DEFAULT NULL,
+  `updated` timestamp NULL DEFAULT NULL,
+  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS `cms_menu_item` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `menuId` int(10) unsigned NOT NULL,
+  `label` varchar(255) NOT NULL,
+  `url` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

models/CmsContent.php

 	public function attributeLabels()
 	{
 		return array(
-			'id' => Yii::t('CmsModule.core', 'Id'),
+			'id' => '#',
 			'nodeId' => Yii::t('CmsModule.core', 'Node'),
 			'locale' => Yii::t('CmsModule.core', 'Locale'),
 			'heading' => Yii::t('CmsModule.core', 'Heading'),

models/CmsMenu.php

+<?php
+/**
+ * CmsMenu class file.
+ * @author Christoffer Niska <christoffer.niska@nordsoftware.com>
+ * @copyright Copyright &copy; 2011, Nord Software Ltd
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @package cms.models
+ */
+
+Yii::import('cms.components.CmsActiveRecord');
+
+/**
+ * This is the model class for table "cms_menu".
+ *
+ * The followings are the available columns in table 'cms_menu':
+ * @property string $id
+ * @property string $name
+ * @property string $created
+ * @property string $updated
+ * @property integer $deleted
+ */
+class CmsMenu extends CmsActiveRecord
+{
+	/**
+	 * Returns the static model of the specified AR class.
+	 * @param string $className the class name
+	 * @return CmsMenu the static model class
+	 */
+	public static function model($className=__CLASS__)
+	{
+		return parent::model($className);
+	}
+
+	/**
+	 * @return string the associated database table name
+	 */
+	public function tableName()
+	{
+		return 'cms_menu';
+	}
+
+	/**
+	 * @return array validation rules for model attributes.
+	 */
+	public function rules()
+	{
+		return array(
+			array('name', 'required'),
+			array('deleted', 'numerical', 'integerOnly'=>true),
+			array('name', 'length', 'max'=>255),
+			array('created, updated', 'safe'),
+			array('id, name, created, updated, deleted', 'safe', 'on'=>'search'),
+		);
+	}
+
+	/**
+	 * @return array relational rules.
+	 */
+	public function relations()
+	{
+		return array(
+			'items'=>array(self::HAS_MANY, 'CmsMenuItem', 'menuId'),
+		);
+	}
+
+	/**
+	 * @return array customized attribute labels (name=>label)
+	 */
+	public function attributeLabels()
+	{
+		return array(
+			'id' => '#',
+			'name' => Yii::t('CmsModule.core', 'Name'),
+			'created' => Yii::t('CmsModule.core', 'Created'),
+			'updated' => Yii::t('CmsModule.core', 'Updated'),
+		);
+	}
+
+	/**
+	 * Retrieves a list of models based on the current search/filter conditions.
+	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
+	 */
+	public function search()
+	{
+		$criteria=new CDbCriteria;
+
+		$criteria->compare('id',$this->id,true);
+		$criteria->compare('name',$this->name,true);
+		$criteria->compare('created',$this->created,true);
+		$criteria->compare('updated',$this->updated,true);
+
+		return new CActiveDataProvider($this, array(
+			'criteria'=>$criteria,
+		));
+	}
+}

models/CmsMenuItem.php

+<?php
+/**
+ * CmsMenuItem class file.
+ * @author Christoffer Niska <christoffer.niska@nordsoftware.com>
+ * @copyright Copyright &copy; 2011, Nord Software Ltd
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @package cms.models
+ */
+
+Yii::import('cms.components.CmsActiveRecord');
+
+/**
+ * This is the model class for table "cms_menu_item".
+ *
+ * The followings are the available columns in table 'cms_menu_item':
+ * @property string $id
+ * @property string $menuId
+ * @property string $label
+ * @property string $url
+ */
+class CmsMenuItem extends CmsActiveRecord
+{
+	/**
+	 * Returns the static model of the specified AR class.
+	 * @param string $className the class name
+	 * @return CmsMenuItem the static model class
+	 */
+	public static function model($className=__CLASS__)
+	{
+		return parent::model($className);
+	}
+
+	/**
+	 * @return string the associated database table name
+	 */
+	public function tableName()
+	{
+		return 'cms_menu_item';
+	}
+
+	/**
+	 * @return array validation rules for model attributes.
+	 */
+	public function rules()
+	{
+		return array(
+			array('menuId, label, url', 'required'),
+			array('menuId', 'length', 'max'=>10),
+			array('label, url', 'length', 'max'=>255),
+			array('id, menuId, label, url', 'safe', 'on'=>'search'),
+		);
+	}
+
+	/**
+	 * @return array relational rules.
+	 */
+	public function relations()
+	{
+		return array(
+		);
+	}
+
+	/**
+	 * @return array customized attribute labels (name=>label)
+	 */
+	public function attributeLabels()
+	{
+		return array(
+			'id' => '#',
+			'menuId' => Yii::t('CmsModule.core', 'Menu'),
+			'label' => Yii::t('CmsModule.core', 'Label'),
+			'url' => Yii::t('CmsModule.core', 'URL'),
+		);
+	}
+
+	/**
+	 * Retrieves a list of models based on the current search/filter conditions.
+	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
+	 */
+	public function search()
+	{
+		$criteria=new CDbCriteria;
+
+		$criteria->compare('id',$this->id,true);
+		$criteria->compare('menuId',$this->menuId,true);
+		$criteria->compare('label',$this->label,true);
+		$criteria->compare('url',$this->url,true);
+
+		return new CActiveDataProvider($this, array(
+			'criteria'=>$criteria,
+		));
+	}
+}

models/CmsNode.php

 	public function attributeLabels()
 	{
 		return array(
-			'id' => Yii::t('CmsModule.core', 'Id'),
+			'id' => '#',
 			'created' => Yii::t('CmsModule.core', 'Created'),
 			'updated' => Yii::t('CmsModule.core', 'Updated'),
 			'name' => Yii::t('CmsModule.core', 'Name'),
 	{
 		$breadcrumbs = array();
 
-		if ($this->parent !== null)
+		if ($this->parent === null) {
+			$breadcrumbs[Yii::t('CmsModule.core','Cms')] = array('admin/index');
+			$breadcrumbs[Yii::t('CmsModule.core','Nodes')] = array('node/index');
+		}
+		else
 			$breadcrumbs = $this->parent->getBreadcrumbs(true); // get the parent as a link
 
 		if ($this->content !== null && !empty($this->content->breadcrumb))

themes/bootstrap/views/cms/layouts/cms-column1.php

+<?php $this->beginContent(Yii::app()->cms->appLayout) ?>
+
+<div class="cms boot column1">
+
+	<div class="row">
+
+		<div class="span16">
+
+			<div class="cms-content">
+
+				<?php echo $content ?>
+
+			</div>
+
+		</div>
+
+	</div>
+
+</div>
+
+<?php $this->endContent() ?>

themes/bootstrap/views/cms/layouts/cms-column2.php

+<?php $this->beginContent(Yii::app()->cms->appLayout) ?>
+
+<div class="cms boot column2">
+
+	<div class="row">
+
+		<div class="span12">
+
+			<div class="cms-content">
+
+				<?php echo $content ?>
+
+			</div>
+
+		</div>
+
+		<div class="span4">
+
+			<div class="cms-sidebar">
+
+				<h3><?php echo Yii::t('CmsModule.core','Nodes') ?></h3>
+				
+				<?php echo CmsNode::model()->renderTree() ?>
+
+				<p><?php echo CHtml::link(Yii::t('CmsModule.core','Create a new node'),array('node/create'),array('class'=>'btn small')) ?></p>
+
+			</div>
+
+		</div>
+
+	</div>
+
+</div>
+
+<?php $this->endContent() ?>

themes/bootstrap/views/cms/layouts/cms.php

-<?php $this->beginContent(Yii::app()->cms->appLayout) ?>
-
-<div class="cms boot">
-
-	<div class="row">
-
-		<div class="span12">
-
-			<div class="cms-content">
-
-				<?php echo $content ?>
-
-			</div>
-
-		</div>
-
-		<div class="span4">
-
-			<div class="cms-sidebar">
-
-				<h3><?php echo Yii::t('CmsModule.core','Nodes') ?></h3>
-				
-				<?php echo CmsNode::model()->renderTree() ?>
-
-				<p><?php echo CHtml::link(Yii::t('CmsModule.core','Create a new node'),array('node/create'),array('class'=>'btn small')) ?></p>
-
-			</div>
-
-		</div>
-
-	</div>
-
-</div>
-
-<?php $this->endContent() ?>

themes/bootstrap/views/cms/node/create.php

-<?php $this->breadcrumbs = array(Yii::t('CmsModule.core','Create node')) ?>
+<?php $this->breadcrumbs = array(
+	Yii::t('CmsModule.core','Cms')=>array('admin/index'),
+	Yii::t('CmsModule.core','Create node')
+) ?>
 
 <div class="node-create">
 

themes/bootstrap/views/cms/node/page.php

-<div class="cms boot">
-
-	<div class="node-page">
-
-		<div class="node-content"><?php echo $content ?></div>
-
-		<?php if (Yii::app()->cms->checkAccess()): ?>
-			<?php echo CHtml::link(Yii::t('CmsModule.core', 'Update'),
-					array('node/update', 'id'=>$model->id), array('class'=>'btn small update-link')) ?>
-		<?php endif ?>
-
-	</div>
-
-</div>

themes/bootstrap/views/cms/node/update.php

-<?php $this->breadcrumbs = CMap::mergeArray($model->getBreadcrumbs(true), array(Yii::t('CmsModule.core','Update'))) ?>
+<?php $this->breadcrumbs = CMap::mergeArray($model->getBreadcrumbs(true), array(
+	Yii::t('CmsModule.core','Update'))
+) ?>
 
 <div class="node-update">
 

views/admin/index.php

+<?php $this->breadcrumbs = array(
+	Yii::t('CmsModule.core','Cms'),
+) ?>
+
+<div class="admin-index">
+
+	<h1><?php echo Yii::t('CmsModule.core','Cms'); ?></h1>
+
+	<div class="nodes">
+		<h2><?php echo CHtml::link(Yii::t('CmsModule.core','Nodes'),array('node/index')); ?></h2>
+	</div>
+
+	<!--
+	<div class="menus">
+		<h2><?php echo Yii::t('CmsModule.core','Menus'); ?></h2>
+	</div>
+	-->
+
+</div>

views/layouts/cms-column1.php

+<?php $this->beginContent(Yii::app()->cms->appLayout) ?>
+
+<div class="cms bp column1">
+
+	<div class="clearfix">
+
+		<div class="span-24 last">
+
+			<div class="cms-content">
+
+				<?php echo $content ?>
+
+			</div>
+
+		</div>
+
+	</div>
+
+</div>
+
+<?php $this->endContent() ?>

views/layouts/cms-column2.php

+<?php $this->beginContent(Yii::app()->cms->appLayout) ?>
+
+<div class="cms bp column2">
+
+	<div class="clearfix">
+
+		<div class="span-18">
+
+			<div class="cms-content">
+
+				<?php echo $content ?>
+
+			</div>
+
+		</div>
+
+		<div class="span-6 last">
+
+			<div class="cms-sidebar">
+
+				<h3><?php echo Yii::t('CmsModule.core','Nodes') ?></h3>
+				
+				<?php echo CmsNode::model()->renderTree() ?>
+				
+				<p><?php echo CHtml::link(Yii::t('CmsModule.core','Create a new node'),array('node/create')) ?></p>
+
+			</div>
+
+		</div>
+
+	</div>
+
+</div>
+
+<?php $this->endContent() ?>

views/layouts/cms.php

-<?php $this->beginContent(Yii::app()->cms->appLayout) ?>
-
-<div class="cms bp">
-
-	<div class="clearfix">
-
-		<div class="span-18">
-
-			<div class="cms-content">
-
-				<?php echo $content ?>
-
-			</div>
-
-		</div>
-
-		<div class="span-6 last">
-
-			<div class="cms-sidebar">
-
-				<h3><?php echo Yii::t('CmsModule.core','Nodes') ?></h3>
-				
-				<?php echo CmsNode::model()->renderTree() ?>
-				
-				<p><?php echo CHtml::link(Yii::t('CmsModule.core','Create a new node'),array('node/create')) ?></p>
-
-			</div>
-
-		</div>
-
-	</div>
-
-</div>
-
-<?php $this->endContent() ?>

views/node/create.php

-<?php $this->breadcrumbs = array(Yii::t('CmsModule.core','Create node')) ?>
+<?php $this->breadcrumbs = array(
+	Yii::t('CmsModule.core','Cms')=>array('admin/index'),
+	Yii::t('CmsModule.core','Create node')
+) ?>
 
 <div class="node-create form">
 

views/node/index.php

+<?php $this->breadcrumbs = array(
+	Yii::t('CmsModule.core','Cms')=>array('admin/index'),
+	Yii::t('CmsModule.core','Nodes'),
+) ?>
+
+<div class="node-index">
+
+	<h1><?php echo Yii::t('CmsModule.core','Nodes'); ?></h1>
+
+	<p><?php echo CHtml::link(Yii::t('CmsModule.core','Create a new node'),array('node/create'),array('class'=>'btn')) ?></p>
+
+	<?php $this->widget('bootstrap.widgets.BootGridView',array(
+		'dataProvider'=>$nodeDp,
+		'columns'=>array(
+			'id',
+			'name',
+			array(
+				'name'=>'parentId',
+				'value'=>'$data->parent !== null ? $data->parent->name : ""',
+			),
+			array(
+				'class'=>'CButtonColumn',
+				'viewButtonUrl'=>'Yii::app()->cms->createUrl($data->name)',
+			),
+		),
+	)) ?>
+
+</div>

views/node/page.php

-<div class="cms bp">
+<div class="cms">
 
 	<div class="node-page">
 
 
 		<?php if (Yii::app()->cms->checkAccess()): ?>
 			<?php echo CHtml::link(Yii::t('CmsModule.core', 'Update'),
-					array('node/update', 'id'=>$model->id), array('class'=>'update-link')) ?>
+					array('node/update', 'id'=>$model->id), array('class'=>'btn small update-link')) ?>
 		<?php endif ?>
 
 	</div>

views/node/update.php

-<?php $this->breadcrumbs = CMap::mergeArray($model->getBreadcrumbs(true), array(Yii::t('CmsModule.core','Update'))) ?>
+<?php $this->breadcrumbs = CMap::mergeArray($model->getBreadcrumbs(true), array(
+	Yii::t('CmsModule.core','Update'))
+) ?>
 
 <div class="node-update form">
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.