prototyping media picker
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@
|
||||
replace: true,
|
||||
templateUrl: 'views/components/editor/umb-editor.html',
|
||||
scope: {
|
||||
editor: "="
|
||||
model: "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -281,6 +281,13 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
}
|
||||
};
|
||||
|
||||
scope.clickEdit = function(item, $event) {
|
||||
if (scope.onClickEdit) {
|
||||
scope.onClickEdit({"item": item})
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
var unbindItemsWatcher = scope.$watch('items', function(newValue, oldValue) {
|
||||
if (angular.isArray(newValue)) {
|
||||
activate();
|
||||
@@ -302,6 +309,7 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
onDetailsHover: "=",
|
||||
onClick: '=',
|
||||
onClickName: "=",
|
||||
onClickEdit: "&",
|
||||
filterBy: "=",
|
||||
itemMaxWidth: "@",
|
||||
itemMaxHeight: "@",
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
// set unique id
|
||||
editor.id = editors.length + 1;
|
||||
|
||||
// set flag so we know when the editor is open in "infinie mode"
|
||||
editor.infiniteMode = true;
|
||||
|
||||
editors.push(editor);
|
||||
|
||||
setIndent();
|
||||
@@ -40,15 +43,10 @@
|
||||
|
||||
function setIndent() {
|
||||
|
||||
//console.log("editors", editors);
|
||||
|
||||
var indentSize = 80;
|
||||
var numberOfCollapsed = editors.length;
|
||||
|
||||
console.log(numberOfCollapsed);
|
||||
|
||||
angular.forEach(editors, function(editor, index){
|
||||
//console.log("editor", editor);
|
||||
|
||||
var lastOpened = false;
|
||||
var style = {};
|
||||
@@ -76,7 +74,6 @@
|
||||
style.left = (index + 1) * indentSize + "px";
|
||||
editor.style = style;
|
||||
|
||||
console.log(editor.style);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -141,3 +141,19 @@
|
||||
margin-left: 7px;
|
||||
transition: background 100ms;
|
||||
}
|
||||
|
||||
.umb-media-grid__edit {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
background: @white;
|
||||
border-radius: 50px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: @black;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="umb-editor" ng-style="editor.style" ng-class="{'umb-editor--small': editor.size === 'small'}">
|
||||
<div ng-if="!editor.view" ng-transclude></div>
|
||||
<div ng-if="editor.view" ng-include="editor.view"></div>
|
||||
<div ng-if="editor.showOverlay" class="umb-editor__overlay"></div>
|
||||
<div class="umb-editor" ng-style="model.style" ng-class="{'umb-editor--small': model.size === 'small'}">
|
||||
<div ng-if="!model.view" ng-transclude></div>
|
||||
<div ng-if="model.view" ng-include="model.view"></div>
|
||||
<div ng-if="model.showOverlay" class="umb-editor__overlay"></div>
|
||||
</div>
|
||||
@@ -2,6 +2,7 @@
|
||||
<div data-element="media-grid-item-{{$index}}" class="umb-media-grid__item" title="{{item.name}}" ng-click="clickItem(item, $event, $index)" ng-repeat="item in items | filter:filterBy" ng-style="item.flexStyle" ng-class="{'-selected': item.selected, '-file': !item.thumbnail, '-svg': item.extension == 'svg'}">
|
||||
<div>
|
||||
<i ng-show="item.selected" class="icon-check umb-media-grid__checkmark"></i>
|
||||
<a ng-click="clickEdit(item, $event)" ng-href="" class="icon-edit umb-media-grid__edit"></a>
|
||||
|
||||
<div data-element="media-grid-item-edit" class="umb-media-grid__item-overlay" ng-class="{'-locked': item.selected}" ng-click="clickItemName(item, $event, $index)">
|
||||
<i ng-if="onDetailsHover" class="icon-info umb-media-grid__info" ng-mouseover="hoverItemDetails(item, $event, true)" ng-mouseleave="hoverItemDetails(item, $event, false)"></i>
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
//used for the media picker dialog
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.MediaPickerController",
|
||||
function($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService, $element, $timeout, $cookies, localStorageService, localizationService, editorService) {
|
||||
|
||||
if (!$scope.model.title) {
|
||||
$scope.model.title = localizationService.localize("defaultdialogs_selectMedia");
|
||||
}
|
||||
|
||||
var dialogOptions = $scope.model;
|
||||
|
||||
$scope.disableFolderSelect = dialogOptions.disableFolderSelect;
|
||||
$scope.onlyImages = dialogOptions.onlyImages;
|
||||
$scope.showDetails = dialogOptions.showDetails;
|
||||
$scope.multiPicker = (dialogOptions.multiPicker && dialogOptions.multiPicker !== "0") ? true : false;
|
||||
$scope.startNodeId = dialogOptions.startNodeId ? dialogOptions.startNodeId : -1;
|
||||
$scope.cropSize = dialogOptions.cropSize;
|
||||
$scope.lastOpenedNode = localStorageService.get("umbLastOpenedMediaNodeId");
|
||||
$scope.lockedFolder = true;
|
||||
|
||||
var umbracoSettings = Umbraco.Sys.ServerVariables.umbracoSettings;
|
||||
var allowedUploadFiles = mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);
|
||||
if ($scope.onlyImages) {
|
||||
$scope.acceptedFileTypes = mediaHelper.formatFileTypes(umbracoSettings.imageFileTypes);
|
||||
} else {
|
||||
// Use whitelist of allowed file types if provided
|
||||
if (allowedUploadFiles !== '') {
|
||||
$scope.acceptedFileTypes = allowedUploadFiles;
|
||||
} else {
|
||||
// If no whitelist, we pass in a blacklist by adding ! to the file extensions, allowing everything EXCEPT for disallowedUploadFiles
|
||||
$scope.acceptedFileTypes = !mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.maxFileSize = umbracoSettings.maxFileSize + "KB";
|
||||
|
||||
$scope.model.selectedImages = [];
|
||||
|
||||
$scope.acceptedMediatypes = [];
|
||||
mediaTypeHelper.getAllowedImagetypes($scope.startNodeId)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: '',
|
||||
};
|
||||
|
||||
//preload selected item
|
||||
$scope.target = undefined;
|
||||
if (dialogOptions.currentTarget) {
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
if ($scope.startNodeId !== -1) {
|
||||
entityResource.getById($scope.startNodeId, "media")
|
||||
.then(function (ent) {
|
||||
$scope.startNodeId = ent.id;
|
||||
run();
|
||||
});
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
function run() {
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(ensureWithinStartNode, gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
} else {
|
||||
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||
//media object so we need to look it up
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||
var altText = $scope.target.altText;
|
||||
mediaResource.getById(id)
|
||||
.then(function (node) {
|
||||
$scope.target = node;
|
||||
if (ensureWithinStartNode(node)) {
|
||||
selectImage(node);
|
||||
$scope.target.url = mediaHelper.resolveFile(node);
|
||||
$scope.target.altText = altText;
|
||||
$scope.openDetailsDialog();
|
||||
}
|
||||
},
|
||||
gotoStartNode);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.upload = function(v) {
|
||||
angular.element(".umb-file-dropzone-directive .file-select").click();
|
||||
};
|
||||
|
||||
$scope.dragLeave = function(el, event) {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
$scope.dragEnter = function(el, event) {
|
||||
$scope.activeDrag = true;
|
||||
};
|
||||
|
||||
$scope.submitFolder = function() {
|
||||
if ($scope.newFolderName) {
|
||||
$scope.creatingFolder = true;
|
||||
mediaResource
|
||||
.addFolder($scope.newFolderName, $scope.currentFolder.id)
|
||||
.then(function(data) {
|
||||
//we've added a new folder so lets clear the tree cache for that specific item
|
||||
treeService.clearCache({
|
||||
cacheKey: "__media", //this is the main media tree cache key
|
||||
childrenOf: data.parentId //clear the children of the parent
|
||||
});
|
||||
$scope.creatingFolder = false;
|
||||
$scope.gotoFolder(data);
|
||||
$scope.showFolderInput = false;
|
||||
$scope.newFolderName = "";
|
||||
});
|
||||
} else {
|
||||
$scope.showFolderInput = false;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.enterSubmitFolder = function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
$scope.submitFolder();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.gotoFolder = function(folder) {
|
||||
if (!$scope.multiPicker) {
|
||||
deselectAllImages($scope.model.selectedImages);
|
||||
}
|
||||
|
||||
if (!folder) {
|
||||
folder = { id: -1, name: "Media", icon: "icon-folder" };
|
||||
}
|
||||
|
||||
if (folder.id > 0) {
|
||||
entityResource.getAncestors(folder.id, "media")
|
||||
.then(function(anc) {
|
||||
$scope.path = _.filter(anc,
|
||||
function(f) {
|
||||
return f.path.indexOf($scope.startNodeId) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
mediaTypeHelper.getAllowedImagetypes(folder.id)
|
||||
.then(function(types) {
|
||||
$scope.acceptedMediatypes = types;
|
||||
});
|
||||
} else {
|
||||
$scope.path = [];
|
||||
}
|
||||
|
||||
$scope.lockedFolder = folder.id === -1 && $scope.model.startNodeIsVirtual;
|
||||
|
||||
$scope.currentFolder = folder;
|
||||
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
||||
return getChildren(folder.id);
|
||||
};
|
||||
|
||||
$scope.clickHandler = function(image, event, index) {
|
||||
if (image.isFolder) {
|
||||
if ($scope.disableFolderSelect) {
|
||||
$scope.gotoFolder(image);
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
selectImage(image);
|
||||
}
|
||||
} else {
|
||||
eventsService.emit("dialogs.mediaPicker.select", image);
|
||||
if ($scope.showDetails) {
|
||||
|
||||
$scope.target = image;
|
||||
|
||||
// handle both entity and full media object
|
||||
if (image.image) {
|
||||
$scope.target.url = image.image;
|
||||
} else {
|
||||
$scope.target.url = mediaHelper.resolveFile(image);
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog();
|
||||
} else {
|
||||
selectImage(image);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clickItemName = function(item) {
|
||||
if (item.isFolder) {
|
||||
$scope.gotoFolder(item);
|
||||
}
|
||||
};
|
||||
|
||||
function selectImage(image) {
|
||||
if (image.selected) {
|
||||
for (var i = 0; $scope.model.selectedImages.length > i; i++) {
|
||||
var imageInSelection = $scope.model.selectedImages[i];
|
||||
if (image.key === imageInSelection.key) {
|
||||
image.selected = false;
|
||||
$scope.model.selectedImages.splice(i, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$scope.multiPicker) {
|
||||
deselectAllImages($scope.model.selectedImages);
|
||||
}
|
||||
image.selected = true;
|
||||
$scope.model.selectedImages.push(image);
|
||||
}
|
||||
}
|
||||
|
||||
function deselectAllImages(images) {
|
||||
for (var i = 0; i < images.length; i++) {
|
||||
var image = images[i];
|
||||
image.selected = false;
|
||||
}
|
||||
images.length = 0;
|
||||
}
|
||||
|
||||
$scope.onUploadComplete = function(files) {
|
||||
$scope.gotoFolder($scope.currentFolder).then(function() {
|
||||
if (files.length === 1 && $scope.model.selectedImages.length === 0) {
|
||||
selectImage($scope.images[$scope.images.length - 1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.onFilesQueue = function() {
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
function ensureWithinStartNode(node) {
|
||||
// make sure that last opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
||||
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
||||
return true;
|
||||
} else {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function gotoStartNode(err) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog = function() {
|
||||
|
||||
$scope.mediaPickerDetailsOverlay = {};
|
||||
$scope.mediaPickerDetailsOverlay.show = true;
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.submit = function(model) {
|
||||
$scope.model.selectedImages.push($scope.target);
|
||||
$scope.model.submit($scope.model);
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.show = false;
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
|
||||
$scope.mediaPickerDetailsOverlay.close = function(oldModel) {
|
||||
$scope.mediaPickerDetailsOverlay.show = false;
|
||||
$scope.mediaPickerDetailsOverlay = null;
|
||||
};
|
||||
};
|
||||
|
||||
var debounceSearchMedia = _.debounce(function() {
|
||||
$scope.$apply(function() {
|
||||
if ($scope.searchOptions.filter) {
|
||||
searchMedia();
|
||||
} else {
|
||||
// reset pagination
|
||||
$scope.searchOptions = {
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
filter: ''
|
||||
};
|
||||
getChildren($scope.currentFolder.id);
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
|
||||
$scope.changeSearch = function() {
|
||||
$scope.loading = true;
|
||||
debounceSearchMedia();
|
||||
};
|
||||
|
||||
$scope.changePagination = function(pageNumber) {
|
||||
$scope.loading = true;
|
||||
$scope.searchOptions.pageNumber = pageNumber;
|
||||
searchMedia();
|
||||
};
|
||||
|
||||
function searchMedia() {
|
||||
$scope.loading = true;
|
||||
entityResource.getPagedDescendants($scope.startNodeId, "Media", $scope.searchOptions)
|
||||
.then(function(data) {
|
||||
// update image data to work with image grid
|
||||
angular.forEach(data.items,
|
||||
function(mediaItem) {
|
||||
// set thumbnail and src
|
||||
mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true);
|
||||
mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false);
|
||||
// set properties to match a media object
|
||||
if (mediaItem.metaData &&
|
||||
mediaItem.metaData.umbracoWidth &&
|
||||
mediaItem.metaData.umbracoHeight) {
|
||||
|
||||
mediaItem.properties = [
|
||||
{
|
||||
alias: "umbracoWidth",
|
||||
value: mediaItem.metaData.umbracoWidth.Value
|
||||
},
|
||||
{
|
||||
alias: "umbracoHeight",
|
||||
value: mediaItem.metaData.umbracoHeight.Value
|
||||
}
|
||||
];
|
||||
}
|
||||
});
|
||||
// update images
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// update pagination
|
||||
if (data.pageNumber > 0)
|
||||
$scope.searchOptions.pageNumber = data.pageNumber;
|
||||
if (data.pageSize > 0)
|
||||
$scope.searchOptions.pageSize = data.pageSize;
|
||||
$scope.searchOptions.totalItems = data.totalItems;
|
||||
$scope.searchOptions.totalPages = data.totalPages;
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function getChildren(id) {
|
||||
$scope.loading = true;
|
||||
return mediaResource.getChildren(id)
|
||||
.then(function(data) {
|
||||
$scope.searchOptions.filter = "";
|
||||
$scope.images = data.items ? data.items : [];
|
||||
// set already selected images to selected
|
||||
preSelectImages();
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
function preSelectImages() {
|
||||
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
|
||||
var folderImage = $scope.images[folderImageIndex];
|
||||
var imageIsSelected = false;
|
||||
|
||||
if ($scope.model && angular.isArray($scope.model.selectedImages)) {
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageIsSelected) {
|
||||
folderImage.selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.editMediaItem = function(item) {
|
||||
|
||||
var mediaEditor = {
|
||||
"view": "views/media/edit.html",
|
||||
"node": item,
|
||||
submit: function(model) {
|
||||
editorService.close(model.id);
|
||||
},
|
||||
close: function(model) {
|
||||
editorService.close(model.id);
|
||||
}
|
||||
};
|
||||
|
||||
editorService.open(mediaEditor);
|
||||
|
||||
};
|
||||
|
||||
$scope.submit = function() {
|
||||
if($scope.model.submit) {
|
||||
$scope.model.submit($scope.model);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.close = function() {
|
||||
if($scope.model.close) {
|
||||
$scope.model.close($scope.model);
|
||||
}
|
||||
};
|
||||
|
||||
onInit();
|
||||
|
||||
});
|
||||
@@ -0,0 +1,176 @@
|
||||
<umb-editor-view ng-controller="Umbraco.Editors.MediaPickerController as vm">
|
||||
|
||||
<umb-editor-header
|
||||
name="model.title"
|
||||
name-locked="true"
|
||||
hide-alias="true"
|
||||
hide-icon="true"
|
||||
hide-description="true">
|
||||
</umb-editor-header>
|
||||
|
||||
<umb-editor-container>
|
||||
|
||||
<form id="fileupload" method="POST" enctype="multipart/form-data" umb-image-upload="options">
|
||||
|
||||
<div on-drag-leave="dragLeave()" on-drag-end="dragLeave()" on-drag-enter="dragEnter()">
|
||||
|
||||
<div class="umb-control-group umb-mediapicker-upload">
|
||||
|
||||
<umb-load-indicator
|
||||
ng-if="loading">
|
||||
</umb-load-indicator>
|
||||
|
||||
<div class="form-search">
|
||||
<i class="icon-search"></i>
|
||||
<input class="umb-search-field search-query -full-width-input"
|
||||
ng-model="searchOptions.filter"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_search"
|
||||
ng-change="changeSearch()"
|
||||
type="text"
|
||||
no-dirty-check />
|
||||
</div>
|
||||
|
||||
<div class="upload-button">
|
||||
<umb-button
|
||||
type="button"
|
||||
label-key="general_upload"
|
||||
action="upload()"
|
||||
disabled="lockedFolder">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row umb-control-group" ng-show="!searchOptions.filter">
|
||||
<ul class="umb-breadcrumbs">
|
||||
<li ng-hide="startNodeId != -1" class="umb-breadcrumbs__ancestor">
|
||||
<a href ng-click="gotoFolder()" prevent-default>Media</a>
|
||||
<span class="umb-breadcrumbs__seperator">/</span>
|
||||
</li>
|
||||
|
||||
<li ng-repeat="item in path" class="umb-breadcrumbs__ancestor">
|
||||
<a href ng-click="gotoFolder(item)" prevent-default>{{item.name}}</a>
|
||||
<span class="umb-breadcrumbs__seperator">/</span>
|
||||
</li>
|
||||
|
||||
<li class="umb-breadcrumbs__ancestor" ng-show="!lockedFolder">
|
||||
<a href ng-hide="showFolderInput" ng-click="showFolderInput = true">
|
||||
<i class="icon icon-add small"></i>
|
||||
</a>
|
||||
|
||||
<input type="text" class="umb-breadcrumbs__add-ancestor" ng-show="showFolderInput" ng-model="newFolderName" ng-keydown="enterSubmitFolder($event)"
|
||||
on-blur="submitFolder()" focus-when="{{showFolderInput}}" />
|
||||
</li>
|
||||
</ul>
|
||||
<div class="umb-loader" ng-if="creatingFolder"></div>
|
||||
</div>
|
||||
|
||||
<umb-file-dropzone
|
||||
ng-if="acceptedMediatypes.length > 0 && !loading && !lockedFolder"
|
||||
accepted-mediatypes="acceptedMediatypes"
|
||||
parent-id="{{currentFolder.id}}"
|
||||
files-uploaded="onUploadComplete"
|
||||
files-queued="onFilesQueue"
|
||||
accept="{{acceptedFileTypes}}"
|
||||
max-file-size="{{maxFileSize}}"
|
||||
hide-dropzone="{{!activeDrag && images.length > 0 || searchOptions.filter }}"
|
||||
compact="{{ images.length > 0 }}">
|
||||
</umb-file-dropzone>
|
||||
|
||||
<umb-media-grid
|
||||
ng-if="!loading"
|
||||
items="images"
|
||||
on-click="clickHandler"
|
||||
on-click-name="clickItemName"
|
||||
on-click-edit="editMediaItem(item)"
|
||||
item-max-width="150"
|
||||
item-max-height="150"
|
||||
item-min-width="100"
|
||||
item-min-height="100"
|
||||
only-images={{onlyImages}}>
|
||||
</umb-media-grid>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<umb-pagination
|
||||
ng-if="searchOptions.totalPages > 0 && !loading"
|
||||
page-number="searchOptions.pageNumber"
|
||||
total-pages="searchOptions.totalPages"
|
||||
on-change="changePagination(pageNumber)">
|
||||
</umb-pagination>
|
||||
</div>
|
||||
|
||||
<umb-empty-state ng-if="searchOptions.filter && images.length === 0 && !loading" position="center">
|
||||
<localize key="general_searchNoResult"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-overlay ng-if="mediaPickerDetailsOverlay.show" model="mediaPickerDetailsOverlay" position="right">
|
||||
|
||||
<div class="umb-control-group">
|
||||
|
||||
<div ng-if="target.url">
|
||||
<umb-image-gravity
|
||||
src="target.url"
|
||||
center="target.focalPoint">
|
||||
</umb-image-gravity>
|
||||
</div>
|
||||
|
||||
<div ng-if="cropSize">
|
||||
|
||||
<h5>
|
||||
<localize key="general_preview">Preview</localize>
|
||||
</h5>
|
||||
|
||||
<umb-image-thumbnail center="target.focalPoint" src="target.url" height="{{cropSize.height}}" width="{{cropSize.width}}"
|
||||
max-size="400">
|
||||
</umb-image-thumbnail>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group">
|
||||
<label>
|
||||
<localize key="@general_url"></localize>
|
||||
</label>
|
||||
<input type="text" localize="placeholder" placeholder="@general_url" class="umb-property-editor umb-textstring" ng-model="target.url"
|
||||
ng-disabled="target.id" />
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group">
|
||||
<label>
|
||||
<localize key="@content_altTextOptional"></localize>
|
||||
</label>
|
||||
<input type="text" class="umb-property-editor umb-textstring" ng-model="target.altText" />
|
||||
</div>
|
||||
|
||||
|
||||
</umb-overlay>
|
||||
|
||||
</form>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
<umb-editor-footer>
|
||||
<umb-editor-footer-content-right>
|
||||
|
||||
<umb-button
|
||||
action="close()"
|
||||
button-style="link"
|
||||
label="Close"
|
||||
type="button">
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
button-style="success"
|
||||
label="Select image"
|
||||
type="button"
|
||||
action="submit(model)">
|
||||
</umb-button>
|
||||
|
||||
</umb-editor-footer-content-right>
|
||||
</umb-editor-footer>
|
||||
|
||||
</umb-editor-view>
|
||||
@@ -44,6 +44,14 @@
|
||||
|
||||
<umb-editor-footer-content-right>
|
||||
|
||||
<umb-button
|
||||
ng-if="model.infiniteMode"
|
||||
action="close()"
|
||||
button-style="link"
|
||||
label="Close"
|
||||
type="button">
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
alias="returnToList"
|
||||
ng-if="page.listViewPath"
|
||||
@@ -53,11 +61,11 @@
|
||||
label-key="buttons_returnToList">
|
||||
</umb-button>
|
||||
|
||||
<!-- label-key="buttons_save" -->
|
||||
<umb-button
|
||||
alias="save"
|
||||
type="submit"
|
||||
label="Save"
|
||||
label-key="buttons_save"
|
||||
label="{{page.submitButtonLabel}}"
|
||||
button-style="success"
|
||||
shortcut="ctrl+s"
|
||||
state="page.saveButtonState">
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
* The controller for the media editor
|
||||
*/
|
||||
function mediaEditController($scope, $routeParams, appState, mediaResource, entityResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, treeService, formHelper, umbModelMapper, editorState, umbRequestHelper, $http) {
|
||||
|
||||
var nodeId = null;
|
||||
|
||||
if($scope.model && $scope.model.node && $scope.model.node.id) {
|
||||
nodeId = $scope.model.node.id;
|
||||
} else {
|
||||
nodeId = $routeParams.id;
|
||||
}
|
||||
|
||||
//setup scope vars
|
||||
$scope.currentSection = appState.getSectionState("currentSection");
|
||||
@@ -19,6 +27,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
$scope.page.menu.currentNode = null; //the editors affiliated node
|
||||
$scope.page.listViewPath = null;
|
||||
$scope.page.saveButtonState = "init";
|
||||
$scope.page.submitButtonLabel = "Save";
|
||||
|
||||
/** Syncs the content item to it's tree node - this occurs on first load and after saving */
|
||||
function syncTreeNode(content, path, initialLoad) {
|
||||
@@ -47,7 +56,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
|
||||
$scope.page.loading = true;
|
||||
|
||||
mediaResource.getScaffold($routeParams.id, $routeParams.doctype)
|
||||
mediaResource.getScaffold(nodeId, $routeParams.doctype)
|
||||
.then(function (data) {
|
||||
$scope.content = data;
|
||||
|
||||
@@ -66,7 +75,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
|
||||
$scope.page.loading = true;
|
||||
|
||||
mediaResource.getById($routeParams.id)
|
||||
mediaResource.getById(nodeId)
|
||||
.then(function (data) {
|
||||
|
||||
$scope.content = data;
|
||||
@@ -85,11 +94,13 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
// if there are any and then clear them so the collection no longer persists them.
|
||||
serverValidationManager.executeAndClearAllSubscriptions();
|
||||
|
||||
syncTreeNode($scope.content, data.path, true);
|
||||
if(!$scope.model.infiniteMode) {
|
||||
syncTreeNode($scope.content, data.path, true);
|
||||
}
|
||||
|
||||
if ($scope.content.parentId && $scope.content.parentId != -1) {
|
||||
//We fetch all ancestors of the node to generate the footer breadcrump navigation
|
||||
entityResource.getAncestors($routeParams.id, "media")
|
||||
entityResource.getAncestors(nodeId, "media")
|
||||
.then(function (anc) {
|
||||
$scope.ancestors = anc;
|
||||
});
|
||||
@@ -151,6 +162,11 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
// set first app to active
|
||||
$scope.content.apps[0].active = true;
|
||||
|
||||
// setup infinite mode
|
||||
if($scope.model && $scope.model.infiniteMode === true) {
|
||||
$scope.page.submitButtonLabel = "Save and Close";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$scope.save = function () {
|
||||
@@ -174,10 +190,19 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
editorState.set($scope.content);
|
||||
$scope.busy = false;
|
||||
|
||||
syncTreeNode($scope.content, data.path);
|
||||
if(!$scope.model.infiniteMode) {
|
||||
syncTreeNode($scope.content, data.path);
|
||||
}
|
||||
|
||||
init($scope.content);
|
||||
|
||||
$scope.page.saveButtonState = "success";
|
||||
|
||||
// close the editor if it's infinite mode
|
||||
if($scope.model && $scope.model.infiniteMode && $scope.model.submit) {
|
||||
$scope.model.submit($scope.model);
|
||||
}
|
||||
|
||||
}, function(err) {
|
||||
|
||||
contentEditingHelper.handleSaveError({
|
||||
@@ -208,6 +233,12 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti
|
||||
$location.path($scope.page.listViewPath);
|
||||
};
|
||||
|
||||
$scope.close = function() {
|
||||
if($scope.model.close) {
|
||||
$scope.model.close($scope.model);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco")
|
||||
|
||||
+53
-34
@@ -1,7 +1,7 @@
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
|
||||
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService) {
|
||||
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService, editorService) {
|
||||
|
||||
//check the pre-values for multi-picker
|
||||
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
|
||||
@@ -94,45 +94,64 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
$scope.sync();
|
||||
};
|
||||
|
||||
$scope.goToItem = function(item) {
|
||||
$location.path('media/media/edit/' + item.id);
|
||||
$scope.editItem = function(item) {
|
||||
|
||||
var mediaEditor = {
|
||||
"view": "views/media/edit.html",
|
||||
"node": item,
|
||||
submit: function(model) {
|
||||
console.log("submitted", model);
|
||||
editorService.close(model.id);
|
||||
},
|
||||
close: function(model) {
|
||||
console.log("closed", model);
|
||||
editorService.close(model.id);
|
||||
}
|
||||
};
|
||||
|
||||
editorService.open(mediaEditor);
|
||||
|
||||
};
|
||||
|
||||
$scope.add = function() {
|
||||
$scope.add = function() {
|
||||
var mediaPicker = {
|
||||
"view": "views/editors/mediapicker/mediapicker.html",
|
||||
"size": "small",
|
||||
startNodeId: $scope.model.config.startNodeId,
|
||||
startNodeIsVirtual: $scope.model.config.startNodeIsVirtual,
|
||||
multiPicker: multiPicker,
|
||||
onlyImages: onlyImages,
|
||||
disableFolderSelect: disableFolderSelect,
|
||||
submit: function(model) {
|
||||
|
||||
$scope.mediaPickerOverlay = {
|
||||
view: "mediapicker",
|
||||
title: "Select media",
|
||||
startNodeId: $scope.model.config.startNodeId,
|
||||
startNodeIsVirtual: $scope.model.config.startNodeIsVirtual,
|
||||
multiPicker: multiPicker,
|
||||
onlyImages: onlyImages,
|
||||
disableFolderSelect: disableFolderSelect,
|
||||
show: true,
|
||||
submit: function(model) {
|
||||
_.each(model.selectedImages, function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
$scope.images.push(media);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
|
||||
editorService.close(model.id);
|
||||
|
||||
_.each(model.selectedImages, function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
},
|
||||
close: function(model) {
|
||||
editorService.close(model.id);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.images.push(media);
|
||||
editorService.open(mediaPicker);
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$scope.sortableOptions = {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</span>
|
||||
|
||||
<div class="umb-sortable-thumbnails__actions" data-element="sortable-thumbnail-actions">
|
||||
<a class="umb-sortable-thumbnails__action" data-element="action-edit" href="" ng-click="goToItem(image)">
|
||||
<a class="umb-sortable-thumbnails__action" data-element="action-edit" href="" ng-click="editItem(image)">
|
||||
<i class="icon icon-edit"></i>
|
||||
</a>
|
||||
<a class="umb-sortable-thumbnails__action -red" data-element="action-remove" href="" ng-click="remove($index)">
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
<umb-editor
|
||||
ng-repeat="editor in editors"
|
||||
editor="editor">
|
||||
model="editor">
|
||||
</umb-editor>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user