Skip to content

ListView drag and drop #393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ module.exports = function (grunt) {
'misc/angular-bootstrap-prettify.js',
'lib/lodash/lodash.min.js',
'dist/angular-patternfly.js',
'lib/angular-ui-router/release/angular-ui-router.min.js'],
'lib/angular-ui-router/release/angular-ui-router.min.js',
'node_modules/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js'],
html5Mode: false,
template: 'grunt-ngdocs-index.tmpl',
styles: ['lib/patternfly/dist/css/patternfly.css', 'lib/patternfly/dist/css/patternfly-additions.css',
styles: ['node_modules/patternfly/dist/css/patternfly.css', 'node_modules/patternfly/dist/css/patternfly-additions.css',
'dist/styles/angular-patternfly.css', 'misc/ng-docs.css', 'misc/examples.css']
},

Expand Down
10 changes: 8 additions & 2 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"angular-sanitize": "1.3.0 - 1.5.*",
"angular-ui-bootstrap": "0.14.x",
"lodash": "3.x",
"patternfly": "~3.18.1"
"patternfly": "git+https://git@github.com/patternfly/patternfly#list-view-dnd-dist"
},
"devDependencies": {
"express": "3.4.4",
Expand Down Expand Up @@ -45,6 +45,9 @@
"nsp": "^2.6.1",
"patternfly-eng-release": "~3.18.1"
},
"optionalDependencies": {
"angular-drag-and-drop-lists": "2.0.0"
},
"scripts": {
"test": "grunt test"
},
Expand Down
66 changes: 66 additions & 0 deletions src/views/listview/list-view-directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
* <li>.showSelectBox - (boolean) Show item selection boxes for each item, default is true
* <li>.selectItems - (boolean) Allow row selection, default is false
* <li>.dlbClick - (boolean) Handle double clicking (item remains selected on a double click). Default is false.
* <li>.dragEnabled - (boolean) Enable drag and drop. Default is false.
* <li>.dragEnd - ( function() ) Function to call when the drag operation ended, default is none
* <li>.dragMoved - ( function() ) Function to call when the drag operation moved an element, default is none
* <li>.dragStart - ( function(item) ) Function to call when the drag operation started, default is none
* <li>.multiSelect - (boolean) Allow multiple row selections, selectItems must also be set, not applicable when dblClick is true. Default is false
* <li>.useExpandingRows - (boolean) Allow row expansion for each list item.
* <li>.selectionMatchProp - (string) Property of the items to use for determining matching, default is 'uuid'
Expand Down Expand Up @@ -151,6 +155,15 @@
</div>
</form>
</div>
<div class="col-md-12">
<form role="form">
<div class="form-group">
<label class="checkbox-inline">
<input type="checkbox" ng-model="config.dragEnabled">Drag and Drop</input>
</label>
</div>
</form>
</div>
<div class="col-md-12">
<label style="font-weight:normal;vertical-align:center;">Events: </label>
</div>
Expand Down Expand Up @@ -184,6 +197,27 @@
return $scope.showDisabled && (item.name === "John Smith");
};

var dragEnd = function() {
$scope.eventText = 'drag end\r\n' + $scope.eventText;
};
var dragMoved = function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this dragMoved functionality be the default behavior in the directive instead of leaving it up to the end users to implement it correctly?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applications will want to handle this on their own. Moving an item's order in the list would typically require a backend call to make the change. Maybe some validation, etc.

var index = -1;

for (var i = 0; i < $scope.items.length; i++) {
if ($scope.items[i] === $scope.dragItem) {
index = i;
}
}
if (index >= 0) {
$scope.items.splice(index, 1);
}
$scope.eventText = 'drag moved\r\n' + $scope.eventText;
};
var dragStart = function(item) {
$scope.dragItem = item;
$scope.eventText = item.name + ': drag start\r\n' + $scope.eventText;
};

$scope.enableButtonForItemFn = function(action, item) {
return !((action.name ==='Action 2') && (item.name === "Frank Livingston")) &&
!(action.name === 'Start' && item.started);
Expand Down Expand Up @@ -224,6 +258,10 @@
selectItems: false,
multiSelect: false,
dblClick: false,
dragEnabled: false,
dragEnd: dragEnd,
dragMoved: dragMoved,
dragStart: dragStart,
selectionMatchProp: 'name',
selectedItems: [],
checkDisabled: checkDisabledItem,
Expand Down Expand Up @@ -424,6 +462,10 @@ angular.module('patternfly.views').directive('pfListView', function ($timeout, $
selectItems: false,
multiSelect: false,
dblClick: false,
dragEnabled: false,
dragEnd: null,
dragMoved: null,
dragStart: null,
selectionMatchProp: 'uuid',
selectedItems: [],
checkDisabled: false,
Expand Down Expand Up @@ -618,6 +660,30 @@ angular.module('patternfly.views').directive('pfListView', function ($timeout, $
scope.checkDisabled = function (item) {
return scope.config.checkDisabled && scope.config.checkDisabled(item);
};

scope.dragEnd = function () {
if (angular.isFunction(scope.config.dragEnd)) {
scope.config.dragEnd();
}
};

scope.dragMoved = function () {
if (angular.isFunction(scope.config.dragMoved)) {
scope.config.dragMoved();
}
};

scope.isDragOriginal = function (item) {
return (item === scope.dragItem);
};

scope.dragStart = function (item) {
scope.dragItem = item;

if (angular.isFunction(scope.config.dragStart)) {
scope.config.dragStart(item);
}
};
}
};
});
94 changes: 53 additions & 41 deletions src/views/listview/list-view.html
Original file line number Diff line number Diff line change
@@ -1,52 +1,64 @@
<div class="list-group list-view-pf">
<div class="list-group list-view-pf" dnd-list="items" ng-class="{'list-view-pf-dnd': config.dragEnabled === true}">
<div class='dndPlaceholder'></div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this div only be added when drag drop is enabled?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The placeholder div has to be there; otherwise, I get an ugly empty space at the top of the list when enabled.

screen shot 2017-01-27 at 10 04 29 am

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but if drag/drop is not enabled it should be OK without it right?
(ng-if="config.dragEnabled")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this and I don't quite understand why it behaves this way but you are correct. I don't see why the ng-if makes a difference but I guess we leave it as is.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why it behaves like this, but suspect the library is looking for the selector when the page is loaded. If I don't provide this tag, the dnd library will use an HTML "li" element and then you see a list dot in the page when dragging.

Copy link
Member Author

@dlabrecq dlabrecq Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a problem, I can style the HTML "li" element to not show up. Just thought this solution was more elegant than incorrectly using an "li" within a "div" tag.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if is fine as is. No harm no foul.

<div class="list-group-item {{item.rowClass}}"
ng-repeat="item in items track by $index"
ng-class="{'pf-selectable': selectItems, 'active': isSelected(item), 'disabled': checkDisabled(item), 'list-view-pf-expand-active': item.isExpanded}">
dnd-draggable="item"
dnd-effect-allowed="move"
dnd-disable-if="config.dragEnabled !== true"
dnd-dragstart="dragStart(item)"
dnd-moved="dragMoved()"
dnd-dragend="dragEnd()"
ng-class="{'drag-original': isDragOriginal(item), 'pf-selectable': selectItems, 'active': isSelected(item), 'disabled': checkDisabled(item), 'list-view-pf-expand-active': item.isExpanded}">
<div class="list-group-item-header">
<div class="list-view-pf-expand" ng-if="config.useExpandingRows">
<span class="fa fa-angle-right" ng-show="!item.disableRowExpansion" ng-click="toggleItemExpansion(item)" ng-class="{'fa-angle-down': item.isExpanded}"></span>
<span class="pf-expand-placeholder" ng-show="item.disableRowExpansion"></span>
</div>
<div class="list-view-pf-checkbox" ng-if="config.showSelectBox" >
<input type="checkbox" value="item.selected" ng-model="item.selected" ng-disabled="checkDisabled(item)" ng-change="checkBoxChange(item)"/>
<div class="list-view-pf-dnd-drag-items" ng-if="config.dragEnabled === true">
<div pf-transclude="parent" class="list-view-pf-main-info"></div>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This div should only be added if drag and drop is enabled

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will add this only when drag and drop is enabled.

<div ng-class="{'list-view-pf-dnd-original-items': config.dragEnabled === true}">
<div class="list-view-pf-expand" ng-if="config.useExpandingRows">
<span class="fa fa-angle-right" ng-show="!item.disableRowExpansion" ng-click="toggleItemExpansion(item)" ng-class="{'fa-angle-down': item.isExpanded}"></span>
<span class="pf-expand-placeholder" ng-show="item.disableRowExpansion"></span>
</div>
<div class="list-view-pf-checkbox" ng-if="config.showSelectBox" >
<input type="checkbox" value="item.selected" ng-model="item.selected" ng-disabled="checkDisabled(item)" ng-change="checkBoxChange(item)"/>
</div>

<div class="list-view-pf-actions"
ng-if="(actionButtons && actionButtons.length > 0) || (menuActions && menuActions.length > 0)">
<button class="btn btn-default {{actionButton.class}}" ng-repeat="actionButton in actionButtons"
title="{{actionButton.title}}"
ng-class="{'disabled' : checkDisabled(item) || !enableButtonForItem(actionButton, item)}"
ng-click="handleButtonAction(actionButton, item)">
<div ng-if="actionButton.include" class="actionButton.includeClass" ng-include src="actionButton.include"></div>
<span ng-if="!actionButton.include">{{actionButton.name}}</span>
</button>
<div uib-dropdown class="{{dropdownClass}} pull-right dropdown-kebab-pf {{getMenuClassForItem(item)}} {{hideMenuForItem(item) ? 'invisible' : ''}}"
id="kebab_{{$index}}"
ng-if="menuActions && menuActions.length > 0">
<button uib-dropdown-toggle class="btn btn-link" type="button"
id="dropdownKebabRight_{{$index}}"
ng-class="{'disabled': checkDisabled(item)}"
ng-click="setupActions(item, $event)">
<span class="fa fa-ellipsis-v"></span>
<div class="list-view-pf-actions"
ng-if="(actionButtons && actionButtons.length > 0) || (menuActions && menuActions.length > 0)">
<button class="btn btn-default {{actionButton.class}}" ng-repeat="actionButton in actionButtons"
title="{{actionButton.title}}"
ng-class="{'disabled' : checkDisabled(item) || !enableButtonForItem(actionButton, item)}"
ng-click="handleButtonAction(actionButton, item)">
<div ng-if="actionButton.include" class="actionButton.includeClass" ng-include src="actionButton.include"></div>
<span ng-if="!actionButton.include">{{actionButton.name}}</span>
</button>
<ul uib-dropdown-menu class="dropdown-menu dropdown-menu-right {{$index}}" aria-labelledby="dropdownKebabRight_{{$index}}" >
<li ng-repeat="menuAction in menuActions"
ng-if="menuAction.isVisible !== false"
role="{{menuAction.isSeparator === true ? 'separator' : 'menuitem'}}"
ng-class="{'divider': (menuAction.isSeparator === true), 'disabled': (menuAction.isDisabled === true)}">
<a ng-if="menuAction.isSeparator !== true" title="{{menuAction.title}}" ng-click="handleMenuAction(menuAction, item)">
{{menuAction.name}}
</a>
</li>
</ul>
<div uib-dropdown class="{{dropdownClass}} pull-right dropdown-kebab-pf {{getMenuClassForItem(item)}} {{hideMenuForItem(item) ? 'invisible' : ''}}"
id="kebab_{{$index}}"
ng-if="menuActions && menuActions.length > 0">
<button uib-dropdown-toggle class="btn btn-link" type="button"
id="dropdownKebabRight_{{$index}}"
ng-class="{'disabled': checkDisabled(item)}"
ng-click="setupActions(item, $event)">
<span class="fa fa-ellipsis-v"></span>
</button>
<ul uib-dropdown-menu class="dropdown-menu dropdown-menu-right {{$index}}" aria-labelledby="dropdownKebabRight_{{$index}}" >
<li ng-repeat="menuAction in menuActions"
ng-if="menuAction.isVisible !== false"
role="{{menuAction.isSeparator === true ? 'separator' : 'menuitem'}}"
ng-class="{'divider': (menuAction.isSeparator === true), 'disabled': (menuAction.isDisabled === true)}">
<a ng-if="menuAction.isSeparator !== true" title="{{menuAction.title}}" ng-click="handleMenuAction(menuAction, item)">
{{menuAction.name}}
</a>
</li>
</ul>
</div>
</div>
</div>
<div pf-transclude="parent"
class="list-view-pf-main-info"
ng-click="itemClick($event, item)"
ng-dblclick="dblClick($event, item)">
<div pf-transclude="parent"
class="list-view-pf-main-info"
ng-click="itemClick($event, item)"
ng-dblclick="dblClick($event, item)">
</div>
<div class="list-group-item-container container-fluid" ng-transclude="expandedContent" ng-if="config.useExpandingRows && item.isExpanded"></div>
</div>
</div>
<div class="list-group-item-container container-fluid" ng-transclude="expandedContent" ng-if="config.useExpandingRows && item.isExpanded"></div>
</div>
</div>
2 changes: 1 addition & 1 deletion src/views/views.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* Views module for patternfly.
*
*/
angular.module('patternfly.views', ['patternfly.utils', 'patternfly.filters', 'patternfly.sort', 'patternfly.charts']);
angular.module('patternfly.views', ['patternfly.utils', 'patternfly.filters', 'patternfly.sort', 'patternfly.charts', 'dndLists']);
3 changes: 2 additions & 1 deletion test/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ module.exports = function(config) {
'test/wizard/script.js',
'test/**/*.spec.js',
'test/**/*.html',
'lib/angular-ui-router/release/angular-ui-router.min.js'
'lib/angular-ui-router/release/angular-ui-router.min.js',
'node_modules/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js'
],

// list of files to exclude
Expand Down