From 710c7b88d2df485ed541fd47ab0b4872d9347415 Mon Sep 17 00:00:00 2001 From: UndefinedOffset Date: Wed, 9 May 2012 14:14:34 -0300 Subject: [PATCH] Initial commit of module --- .buildpath | 6 + .project | 29 ++++ .settings/.jsdtscope | 16 ++ .settings/org.eclipse.php.core.prefs | 3 + ...rg.eclipse.wst.jsdt.ui.superType.container | 1 + .../org.eclipse.wst.jsdt.ui.superType.name | 1 + _config.php | 3 + code/extensions/GridFieldSortableObject.php | 135 +++++++++++++++++ code/forms/GridFieldSortableRows.php | 143 ++++++++++++++++++ css/GridFieldSortableRows.css | 7 + javascript/GridFieldSortableRows.js | 43 ++++++ templates/Includes/GridFieldSortableRows.ss | 9 ++ 12 files changed, 396 insertions(+) create mode 100644 .buildpath create mode 100644 .project create mode 100644 .settings/.jsdtscope create mode 100644 .settings/org.eclipse.php.core.prefs create mode 100644 .settings/org.eclipse.wst.jsdt.ui.superType.container create mode 100644 .settings/org.eclipse.wst.jsdt.ui.superType.name create mode 100644 _config.php create mode 100644 code/extensions/GridFieldSortableObject.php create mode 100644 code/forms/GridFieldSortableRows.php create mode 100644 css/GridFieldSortableRows.css create mode 100644 javascript/GridFieldSortableRows.js create mode 100644 templates/Includes/GridFieldSortableRows.ss diff --git a/.buildpath b/.buildpath new file mode 100644 index 0000000..c1ec64b --- /dev/null +++ b/.buildpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..a9dc0b2 --- /dev/null +++ b/.project @@ -0,0 +1,29 @@ + + + SortableGridField + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.dltk.core.scriptbuilder + + + + + + ca.edchipman.silverstripepdt.SilverStripeNature + org.eclipse.php.core.PHPNature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 0000000..2f6f983 --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.php.core.prefs b/.settings/org.eclipse.php.core.prefs new file mode 100644 index 0000000..f39b247 --- /dev/null +++ b/.settings/org.eclipse.php.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +include_path=0;/SortableGridField\u00055;ca.edchipman.silverstripepdt.LANGUAGE +silverstripe_version=SS2.4 diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/_config.php b/_config.php new file mode 100644 index 0000000..15c5adc --- /dev/null +++ b/_config.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/code/extensions/GridFieldSortableObject.php b/code/extensions/GridFieldSortableObject.php new file mode 100644 index 0000000..a560f8b --- /dev/null +++ b/code/extensions/GridFieldSortableObject.php @@ -0,0 +1,135 @@ +'Int' + ); + + protected static $sortable_classes = array(); + protected static $many_many_sortable_relations = array(); + protected static $sort_dir = "ASC"; + + + public static function set_sort_dir($dir) { + self::$sort_dir=$dir; + } + + + public static function add_sortable_class($className) { + if(!self::is_sortable_class($className)) { + Object::add_extension($className, 'GridFieldSortableObject'); + + self::$sortable_classes[]=$className; + } + } + + public static function add_sortable_classes(array $classes) { + foreach($classes as $class) { + self::add_sortable_class($class); + } + } + + public static function add_sortable_many_many_relation($ownerClass, $componentName) { + list($parentClass, $componentClass, $parentField, $componentField, $table)=singleton($ownerClass)->many_many($componentName); + + Object::add_static_var($ownerClass, 'many_many_extraFields', array( + $componentName=>array( + 'SortOrder'=>'Int' + ))); + + + if(!isset(self::$many_many_sortable_relations[$componentClass])) { + self::$many_many_sortable_relations[$componentClass] = array(); + } + + + self::$many_many_sortable_relations[$componentClass][$parentClass]=$table; + self::add_sortable_class($componentClass); + } + + public static function remove_sortable_class($class) { + Object::remove_extension($class, 'GridFieldSortableObject'); + } + + public static function is_sortable_class($classname) { + if(in_array($classname, self::$sortable_classes)) { + return true; + } + + foreach(self::$sortable_classes as $class) { + if(is_subclass_of($classname, $class)) { + return true; + } + } + + + return Object::has_extension($classname, 'GridFieldSortableObject'); + } + + public static function is_sortable_many_many($componentClass, $parentClass=null) { + $map=self::$many_many_sortable_relations; + if($parentClass===null) { + return isset($map[$componentClass]); + }else { + if(isset($map[$componentClass])) { + return isset($map[$componentClass][$parentClass]); + } + + return false; + } + + } + + public static function get_join_tables($classname) { + if(isset(self::$many_many_sortable_relations[$classname])) { + return self::$many_many_sortable_relations[$classname]; + } + + return false; + } + + public function augmentSQL(SQLQuery &$query) { + if(empty($query->select) || $query->delete || in_array("COUNT(*)", $query->select) || in_array("count(*)", $query->select)) { + return; + } + + + $sort_field=false; + if($join_tables=self::get_join_tables($this->owner->class)) { + foreach($query->from as $from) { + if($sort_field) { + break; + } + + foreach($join_tables as $join_table) { + if(stristr($from,$join_table)) { + $sort_field="\"$join_table\".\"SortOrder\""; + + if(isset($query->select['SortOrder'])) { + $query->select['SortOrder']="\"{$this->owner->class}\".SortOrder AS LocalSort"; + } + + break; + } + } + } + } + + + if(!$sort_field) { + $sort_field="\"SortOrder\""; + } + + if(!$query->orderby || ($query->orderby==$this->owner->stat('default_sort'))) { + $query->orderby="$sort_field ".self::$sort_dir; + } + } + + public function onBeforeWrite() { + if(!$this->owner->ID) { + if($peers=DataList::create($this->owner->class)) { + $this->owner->SortOrder=$peers->Count()+1; + } + } + } +} +?> \ No newline at end of file diff --git a/code/forms/GridFieldSortableRows.php b/code/forms/GridFieldSortableRows.php new file mode 100644 index 0000000..51e7f61 --- /dev/null +++ b/code/forms/GridFieldSortableRows.php @@ -0,0 +1,143 @@ +State->GridFieldSortableRows; + if(!is_bool($state->sortableToggle)) { + $state->sortableToggle=false; + } + + + + if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) { + //Sort order toggle + $sortOrderToggle=new GridField_FormAction($gridField, 'sortablerows_toggle', 'Allow drag and drop re-ordering', 'saveGridRowSort', null); + $sortOrderToggle->addExtraClass('sortablerows_toggle'); + + //Disable Pagenator + if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) { + $disablePagenator=new GridField_FormAction($gridField, 'sortablerows_disablepagenator', 'Disable Pagenator', 'sortableRowsDisablePaginator', null); + $disablePagenator->addExtraClass('sortablerows_disablepagenator'); + }else { + $disablePagenator=null; + } + + $forTemplate=new ArrayData(array( + 'SortableToggle'=>$sortOrderToggle, + 'PagenatorToggle'=>$disablePagenator, + 'Checked'=>($state->sortableToggle==true ? ' checked="checked"':'') + )); + + + //Inject Requirements + Requirements::css('SortableGridField/css/GridFieldSortableRows.css'); + Requirements::javascript('SortableGridField/javascript/GridFieldSortableRows.js'); + + + return array( + 'header'=>$forTemplate->renderWith('GridFieldSortableRows', array('Colspan'=>count($gridField->getColumns()))) + ); + } + + return array(); + } + + /** + * Return a list of the actions handled by this action provider. + * @param GridField $gridField Grid Field Reference + * @return {array} Array with action identifier strings. + */ + public function getActions($gridField) { + if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) { + if($gridField->getConfig()->getComponentByType('GridFieldPaginator')) { + return array('saveGridRowSort', 'sortableRowsDisablePaginator'); + }else { + return array('saveGridRowSort'); + } + } + + return array(); + } + + /** + * Handle an action on the given grid field. + * @param {GridField} $gridField Grid Field Reference + * @param {string} $actionName Action identifier, see {@link getActions()}. + * @param {array} $arguments Arguments relevant for this + * @param {array} $data All form data + */ + public function handleAction(GridField $gridField, $actionName, $arguments, $data) { + $state=$gridField->State->GridFieldSortableRows; + if(!is_bool($state->sortableToggle)) { + $state->sortableToggle=false; + }else if($state->sortableToggle==true) { + if($gridField->getConfig()->getComponentsByType('GridFieldPaginator')) { + $gridField->getConfig()->removeComponentsByType('GridFieldPaginator'); + $gridField->getConfig()->addComponent(new GridFieldFooter()); + } + + $gridField->getConfig()->removeComponentsByType('GridFieldFilterHeader'); + $gridField->getConfig()->removeComponentsByType('GridFieldSortableHeader'); + } + + + if(Object::has_extension($gridField->getModelClass(), 'GridFieldSortableObject')) { + if($actionName=='savegridrowsort') { + return $this->saveGridRowSort($gridField, $data); + } + } + } + + /** + * Handles saving of the row sort order + * @param {GridField} $gridField Grid Field Reference + * @param {array} $data Data submitted in the request + */ + private function saveGridRowSort(GridField $gridField, $data) { + if(empty($data['Items'])) { + user_error('No items to sort', E_USER_ERROR); + } + + $className=$gridField->getModelClass(); + $ownerClass=$gridField->Form->Controller()->class; + + $many_many=GridFieldSortableObject::is_sortable_many_many($className); + if($many_many) { + $candidates=singleton($ownerClass)->many_many(); + if(is_array($candidates)) { + foreach($candidates as $name => $class) + if($class==$className) { + $relationName=$name; + break; + } + } + + if(!isset($relationName)) { + return false; + } + + list($parentClass, $componentClass, $parentField, $componentField, $table)=singleton($ownerClass)->many_many($relationName); + } + + + $data['Items']=explode(',', $data['Items']); + for($sort=0;$sortSortOrder=$sort; + $obj->write(); + } + } + } +} +?> \ No newline at end of file diff --git a/css/GridFieldSortableRows.css b/css/GridFieldSortableRows.css new file mode 100644 index 0000000..3141843 --- /dev/null +++ b/css/GridFieldSortableRows.css @@ -0,0 +1,7 @@ +.cms table.ss-gridfield-table thead tr th.sortablerowsheading { + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} + +.cms table.ss-gridfield-table thead tr th.sortablerowsheading .gridfield-sortablerows button { + display: none; +} \ No newline at end of file diff --git a/javascript/GridFieldSortableRows.js b/javascript/GridFieldSortableRows.js new file mode 100644 index 0000000..da1ef28 --- /dev/null +++ b/javascript/GridFieldSortableRows.js @@ -0,0 +1,43 @@ +(function($) { + $('.ss-gridfield .gridfield-sortablerows input').entwine({ + onmatch: function() { + var refCheckbox=$(this); + + var gridField=$(this).getGridField(); + gridField.find('tbody').sortable({ + disabled: ($(this).is(':checked')==false), + helper: function(e, ui) { + //Maintains width of the columns + ui.children().each(function() { + $(this).width($(this).width()); + }); + + return ui; + }, + update: function(event, ui) { + var dataRows=[]; + var gridItems=gridField.getItems(); + var button=refCheckbox.parent().find('.sortablerows_toggle'); + + + for(var i=0;i + +
+ Allow drag and drop re-ordering + $SortableToggle + $PagenatorToggle +
+ + \ No newline at end of file