refactor move logic from tree controller into to mini-list-view component

This commit is contained in:
Mads Rasmussen
2017-02-08 14:58:54 +01:00
parent c060856782
commit 843796c9a4
4 changed files with 278 additions and 285 deletions

View File

@@ -1,33 +1,194 @@
(function() {
(function () {
'use strict';
function MiniListViewDirective() {
function MiniListViewDirective($q, contentResource, memberResource, mediaResource, entityResource) {
function link(scope, el, attr, ctrl) {
scope.search = "";
scope.miniListViews = [];
scope.breadcrumb = [];
scope.openChild = function(event, child) {
if(scope.onOpenChild) {
scope.onOpenChild({"child": child});
event.stopPropagation();
}
};
var miniListViewsHistory = [];
var goingForward = true;
scope.selectChild = function(child) {
if(scope.onSelectChild) {
scope.onSelectChild({"child": child});
}
};
function onInit() {
open(scope.node);
}
scope.searchMiniListView = function() {
if (scope.search !== null && scope.search !== undefined) {
if(scope.onSearch) {
scope.onSearch({"search": scope.search});
function open(node) {
goingForward = true;
var miniListView = {
node: node,
loading: true,
pagination: {
pageSize: 10,
pageNumber: 1,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder",
orderBySystemField: true
}
};
// start loading animation on node
node.loading = true;
getChildrenForMiniListView(miniListView)
.then(function (data) {
// stop loading animation on node
node.loading = false;
// clear and push mini list view in dom so we only render 1 view
scope.miniListViews = [];
scope.miniListViews.push(miniListView);
// store in history so we quickly can navigate back
miniListViewsHistory.push(miniListView);
});
// get ancestors
getAncestors(node);
}
function getChildrenForMiniListView(miniListView) {
// setup promise
var deferred = $q.defer();
// start loading animation list view
miniListView.loading = true;
// setup the correct resource depending on section
var resource = "";
if (scope.entityType === "Member") {
resource = memberResource.getPagedResults;
} else if (scope.entityType === "Media") {
resource = mediaResource.getChildren;
} else {
resource = contentResource.getChildren;
}
resource(miniListView.node.id, miniListView.pagination)
.then(function (data) {
// update children
miniListView.children = data.items;
// update pagination
miniListView.pagination.totalItems = data.totalItems;
miniListView.pagination.totalPages = data.totalPages;
// stop load indicator
miniListView.loading = false;
deferred.resolve(data);
});
return deferred.promise;
}
scope.openNode = function(event, node) {
open(node);
event.stopPropagation();
};
scope.selectNode = function(node) {
if(scope.onSelect) {
scope.onSelect({'node': node});
}
};
/* Pagination */
scope.goToPage = function(pageNumber, miniListView) {
// set new page number
miniListView.pagination.pageNumber = pageNumber;
// get children
getChildrenForMiniListView(miniListView);
};
/* Breadcrumb */
scope.clickBreadcrumb = function(ancestor) {
var found = false;
goingForward = false;
angular.forEach(miniListViewsHistory, function(historyItem, index){
if(Number(historyItem.node.id) === Number(ancestor.id)) {
// load the list view from history
scope.miniListViews = [];
scope.miniListViews.push(historyItem);
// get ancestors
getAncestors(historyItem.node);
found = true;
}
});
if(!found) {
// if we can't find the view in the history
miniListViewsHistory = [];
scope.miniListViews = [];
}
};
function getAncestors(node) {
entityResource.getAncestors(node.id, scope.entityType)
.then(function (ancestors) {
// if there is a start node remove all ancestors before that one
if(scope.startNodeId && scope.startNodeId !== -1) {
var found = false;
scope.breadcrumb = [];
angular.forEach(ancestors, function(ancestor){
if(Number(ancestor.id) === Number(scope.startNodeId)) {
found = true;
}
if(found) {
scope.breadcrumb.push(ancestor);
}
});
} else {
scope.breadcrumb = ancestors;
}
});
}
/* Search */
scope.searchMiniListView = function(search, miniListView) {
// set search value
miniListView.pagination.filter = search;
// start loading animation list view
miniListView.loading = true;
searchMiniListView(miniListView);
};
var searchMiniListView = _.debounce(function (miniListView) {
scope.$apply(function () {
getChildrenForMiniListView(miniListView);
});
}, 500);
/* Animation */
scope.getMiniListViewAnimation = function() {
if(goingForward) {
return 'umb-mini-list-view--forward';
} else {
return 'umb-mini-list-view--backwards';
}
};
onInit();
}
var directive = {
@@ -36,11 +197,9 @@
templateUrl: 'views/components/umb-mini-list-view.html',
scope: {
node: "=",
children: "=",
onSelectChild: "&",
onOpenChild: "&",
onSearch: "&",
loadingChildren: "="
entityType: "@",
startNodeId: "=",
onSelect: "&"
},
link: link
};

View File

@@ -22,17 +22,17 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
$scope.init = function(contentType) {
if(contentType === "content") {
entityType = "Document";
$scope.entityType = "Document";
if(!$scope.model.title) {
$scope.model.title = localizationService.localize("defaultdialogs_selectContent");
}
} else if(contentType === "member") {
entityType = "Member";
$scope.entityType = "Member";
if(!$scope.model.title) {
$scope.model.title = localizationService.localize("defaultdialogs_selectMember");
}
} else if(contentType === "media") {
entityType = "Media";
$scope.entityType = "Media";
if(!$scope.model.title) {
$scope.model.title = localizationService.localize("defaultdialogs_selectMedia");
}
@@ -49,7 +49,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
});
// Allow the entity type to be passed in but defaults to Document for backwards compatibility.
var entityType = dialogOptions.entityType ? dialogOptions.entityType : "Document";
$scope.entityType = dialogOptions.entityType ? dialogOptions.entityType : "Document";
//min / max values
@@ -61,10 +61,10 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
}
if (dialogOptions.section === "member") {
entityType = "Member";
$scope.entityType = "Member";
}
else if (dialogOptions.section === "media") {
entityType = "Media";
$scope.entityType = "Media";
}
// Search and listviews is only working for content, media and member section so we will remove it from everything else
@@ -73,7 +73,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
//if a alternative startnode is used, we need to check if it is a container
if (dialogOptions.startNodeId && dialogOptions.startNodeId !== -1) {
entityResource.getById(dialogOptions.startNodeId, entityType).then(function (node) {
entityResource.getById(dialogOptions.startNodeId, $scope.entityType).then(function (node) {
if (node.metaData.IsContainer) {
openMiniListView(node);
}
@@ -193,7 +193,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
multiSelectItem(entity);
} else {
//otherwise we have to get it from the server
entityResource.getById(id, entityType).then(function (ent) {
entityResource.getById(id, $scope.entityType).then(function (ent) {
multiSelectItem(ent);
});
}
@@ -218,7 +218,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
multiSelectItem(entity);
} else {
//otherwise we have to get it from the server
entityResource.getById(id, entityType).then(function (ent) {
entityResource.getById(id, $scope.entityType).then(function (ent) {
multiSelectItem(ent);
});
}
@@ -235,7 +235,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
$scope.model.submit($scope.model);
} else {
//otherwise we have to get it from the server
entityResource.getById(id, entityType).then(function (ent) {
entityResource.getById(id, $scope.entityType).then(function (ent) {
$scope.model.selection.push(ent);
$scope.model.submit($scope.model);
});
@@ -316,7 +316,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
}
$scope.multiSubmit = function (result) {
entityResource.getByIds(result, entityType).then(function (ents) {
entityResource.getByIds(result, $scope.entityType).then(function (ents) {
$scope.submit(ents);
});
};
@@ -466,179 +466,14 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
});
/* --- Mini List View --- */
$scope.miniListViews = [];
$scope.breadcrumb = [];
var miniListViewsHistory = [];
var goingForward = true;
$scope.goToPage = function(pageNumber, miniListView) {
// set new page number
miniListView.pagination.pageNumber = pageNumber;
// get children
getChildrenForMiniListView(miniListView);
};
$scope.selectListViewItem = function(item) {
select(item.name, item.id);
$scope.selectListViewNode = function(node) {
select(node.name, node.id);
//toggle checked state
item.selected = item.selected === true ? false : true;
node.selected = node.selected === true ? false : true;
};
$scope.clickBreadcrumb = function(ancestor) {
var found = false;
goingForward = false;
angular.forEach(miniListViewsHistory, function(historyItem, index){
if(parseInt(historyItem.node.id) === parseInt(ancestor.id)) {
// load the list view from history
$scope.miniListViews = [];
$scope.miniListViews.push(historyItem);
// get ancestors
getAncestors(historyItem.node);
found = true;
}
});
if(!found) {
// if we can't find the view in the history
miniListViewsHistory = [];
$scope.miniListViews = [];
}
};
$scope.searchMiniListView = function(search, miniListView) {
// set search value
miniListView.pagination.filter = search;
// start loading animation list view
miniListView.loading = true;
searchMiniListView(miniListView);
};
$scope.test = function(node) {
openMiniListView(node);
};
var searchMiniListView = _.debounce(function (miniListView) {
$scope.$apply(function () {
getChildrenForMiniListView(miniListView);
});
}, 500);
function openMiniListView(node) {
goingForward = true;
var miniListView = {
node: node,
loading: true,
pagination: {
pageSize: 10,
pageNumber: 1,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder",
orderBySystemField: true
}
};
// start loading animation on node
node.loading = true;
getChildrenForMiniListView(miniListView)
.then(function(data){
// stop loading animation on node
node.loading = false;
// clear and push mini list view in dom so we only render 1 view
$scope.miniListViews = [];
$scope.miniListViews.push(miniListView);
// store in history so we quickly can navigate back
miniListViewsHistory.push(miniListView);
});
// get ancestors
getAncestors(node);
}
function getChildrenForMiniListView(miniListView) {
// setup promise
var deferred = $q.defer();
// start loading animation list view
miniListView.loading = true;
// setup the correct resource depending on section
var resource = "";
if (entityType === "Document") {
resource = contentResource.getChildren;
} else if (entityType === "Member") {
resource = memberResource.getPagedResults;
} else if (entityType === "Media") {
resource = mediaResource.getChildren;
}
resource(miniListView.node.id, miniListView.pagination)
.then(function (data) {
console.log("data, data, data", data);
// update children
miniListView.children = data.items;
// update pagination
miniListView.pagination.totalItems = data.totalItems;
miniListView.pagination.totalPages = data.totalPages;
// stop load indicator
miniListView.loading = false;
deferred.resolve(data);
});
return deferred.promise;
}
function getAncestors(node) {
entityResource.getAncestors(node.id, entityType)
.then(function (ancestors) {
// if there is a start node remove all ancestors before that one
if(dialogOptions.startNodeId && dialogOptions.startNodeId !== -1) {
var found = false;
$scope.breadcrumb = [];
angular.forEach(ancestors, function(ancestor){
if(parseInt(ancestor.id) === parseInt(dialogOptions.startNodeId)) {
found = true;
}
if(found) {
$scope.breadcrumb.push(ancestor);
}
});
} else {
$scope.breadcrumb = ancestors;
}
});
}
$scope.getMiniListViewAnimation = function() {
if(goingForward) {
return 'umb-mini-list-view--forward';
} else {
return 'umb-mini-list-view--backwards';
}
$scope.miniListView = node;
}
});

View File

@@ -1,6 +1,6 @@
<div ng-controller="Umbraco.Overlays.TreePickerController">
<div ng-hide="miniListViews.length > 0">
<div ng-hide="miniListView">
<div class="umb-control-group">
<umb-tree-search-box
@@ -36,40 +36,13 @@
</div>
</div>
<div ng-repeat="miniListView in miniListViews" ng-animate="getMiniListViewAnimation()">
<div class="umb-mini-list-view__title">
<i class="umb-mini-list-view__title-icon {{ miniListView.node.icon }}"></i>
<h4 class="umb-mini-list-view__title-text">{{ miniListView.node.name }}</h4>
</div>
<umb-breadcrumbs
style="margin-bottom: 10px;"
ng-if="breadcrumb && breadcrumb.length > 0"
ancestors="breadcrumb"
entity-type="content"
on-open="clickBreadcrumb(ancestor)">
</umb-breadcrumbs>
<umb-mini-list-view
node="miniListView.node"
children="miniListView.children"
on-select-child="selectListViewItem(child)"
on-open-child="test(child)"
on-search="searchMiniListView(search, miniListView)"
loading-children="miniListView.loading">
</umb-mini-list-view>
<div class="flex justify-center">
<umb-pagination
ng-if="miniListView.pagination.totalPages > 0 && !miniListView.loading"
page-number="miniListView.pagination.pageNumber"
total-pages="miniListView.pagination.totalPages"
on-change="goToPage(pageNumber, miniListView)">
</umb-pagination>
</div>
</div>
<umb-mini-list-view
ng-if="miniListView"
node="miniListView"
entity-type="{{entityType}}"
start-node-id="model.startNodeId"
on-select="selectListViewNode(node)">
</umb-mini-list-view>
</div>

View File

@@ -1,65 +1,91 @@
<div>
<div class="umb-table umb-table--condensed">
<div ng-repeat="miniListView in miniListViews" ng-animate="getMiniListViewAnimation()">
<!-- Head -->
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell" style="display: none;"></div>
<div class="umb-table-cell" style="padding-top: 8px; padding-bottom: 8px;">
<form class="form-search -no-margin-bottom" style="width: 100%; margin-right: 0;" novalidate>
<div class="inner-addon left-addon">
<i class="icon icon-search" style="font-size: 14px;"></i>
<input
style="width: 100%;"
class="form-control search-input"
type="text"
localize="placeholder"
placeholder="@general_typeToSearch"
ng-model="search"
ng-change="searchMiniListView(search)"
prevent-enter-submit
no-dirty-check>
</div>
</form>
</div>
</div>
<div class="umb-mini-list-view__title">
<i class="umb-mini-list-view__title-icon {{ miniListView.node.icon }}"></i>
<h4 class="umb-mini-list-view__title-text">{{ miniListView.node.name }}</h4>
</div>
<!-- Body -->
<div class="umb-table-body">
<umb-breadcrumbs
style="margin-bottom: 10px;"
ng-if="breadcrumb && breadcrumb.length > 0"
ancestors="breadcrumb"
entity-type="content"
on-open="clickBreadcrumb(ancestor)">
</umb-breadcrumbs>
<!-- Load indicator when the list has items -->
<div class="umb-table__loading-overlay" ng-if="loadingChildren && children.length > 0">
<umb-load-indicator></umb-load-indicator>
</div>
<div class="umb-table umb-table--condensed">
<!-- Items -->
<div class="umb-table-row"
ng-repeat="child in children"
ng-click="selectChild(child)"
ng-class="{'-selected':child.selected}">
<div class="umb-table-cell umb-table-cell--auto-width" ng-class="{'umb-table-cell--faded':!child.published}">
<div class="flex items-center">
<ins class="icon-navigation-right umb-table__row-expand" ng-click="openChild($event, child)">&nbsp;</ins>
<i class="umb-table-body__icon umb-table-body__fileicon {{child.icon}}"></i>
<i class="umb-table-body__icon umb-table-body__checkicon icon-check"></i>
<!-- Head -->
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell" style="display: none;"></div>
<div class="umb-table-cell" style="padding-top: 8px; padding-bottom: 8px;">
<form class="form-search -no-margin-bottom" style="width: 100%; margin-right: 0;" novalidate>
<div class="inner-addon left-addon">
<i class="icon icon-search" style="font-size: 14px;"></i>
<input
style="width: 100%;"
class="form-control search-input"
type="text"
localize="placeholder"
placeholder="@general_typeToSearch"
ng-model="search"
ng-change="searchMiniListView(search, miniListView)"
prevent-enter-submit
no-dirty-check>
</div>
</form>
</div>
</div>
<div class="umb-table-cell black" ng-class="{'umb-table-cell--faded':!child.published}">{{ child.name }}</div>
</div>
<!-- Load indicator when the list doesn't have items -->
<div ng-if="!loadingChildren && !children" class="umb-table-row umb-table-row--empty">
<span ng-if="search === ''"><localize key="general_noItemsInList"></localize></span>
<span ng-if="search !== ''"><localize key="general_searchNoResult"></localize></span>
<!-- Body -->
<div class="umb-table-body">
<!-- Load indicator when the list has items -->
<div class="umb-table__loading-overlay" ng-if="miniListView.loading && miniListView.children.length > 0">
<umb-load-indicator></umb-load-indicator>
</div>
<!-- Items -->
<div class="umb-table-row"
ng-repeat="child in miniListView.children"
ng-click="selectNode(child)"
ng-class="{'-selected':child.selected}">
<div class="umb-table-cell umb-table-cell--auto-width" ng-class="{'umb-table-cell--faded':!child.published}">
<div class="flex items-center">
<ins class="icon-navigation-right umb-table__row-expand" ng-click="openNode($event, child)">&nbsp;</ins>
<i class="umb-table-body__icon umb-table-body__fileicon {{child.icon}}"></i>
<i class="umb-table-body__icon umb-table-body__checkicon icon-check"></i>
</div>
</div>
<div class="umb-table-cell black" ng-class="{'umb-table-cell--faded':!child.published}">{{ child.name }}</div>
</div>
<!-- Load indicator when the list doesn't have items -->
<div ng-if="!miniListView.loading && !miniListView.children" class="umb-table-row umb-table-row--empty">
<span ng-if="search === ''"><localize key="general_noItemsInList"></localize></span>
<span ng-if="search !== ''"><localize key="general_searchNoResult"></localize></span>
</div>
<!-- Load indicator when the list doesn't have items -->
<div ng-if="miniListView.loading && !miniListView.children" class="umb-table-row umb-table-row--empty">
<umb-load-indicator></umb-load-indicator>
</div>
</div>
<!-- Load indicator when the list doesn't have items -->
<div ng-if="loadingChildren && !children" class="umb-table-row umb-table-row--empty">
<umb-load-indicator></umb-load-indicator>
</div>
</div>
<div class="flex justify-center">
<umb-pagination
ng-if="miniListView.pagination.totalPages > 0 && !miniListView.loading"
page-number="miniListView.pagination.pageNumber"
total-pages="miniListView.pagination.totalPages"
on-change="goToPage(pageNumber, miniListView)">
</umb-pagination>
</div>
</div>