Merge remote-tracking branch 'origin/dev-v7-contenttypeeditor' into dev-v7-contenttypeeditor-validation
Conflicts: src/Umbraco.Web.UI.Client/src/common/directives/validation/valregex.directive.js src/Umbraco.Web.UI.Client/src/less/forms.less
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
|
||||
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', ['jshint:dev', 'build', 'karma:unit']);
|
||||
@@ -18,7 +18,7 @@ module.exports = function (grunt) {
|
||||
grunt.registerTask('watch-test', ['jshint:dev', 'karma:unit']);
|
||||
|
||||
//triggered from grunt
|
||||
grunt.registerTask('build', ['clean:pre', 'concat', 'recess:build', 'recess:installer', 'recess:canvasdesigner', 'postcss', 'bower-install-simple', 'bower', 'copy', 'clean:post']);
|
||||
grunt.registerTask('build', ['concat', 'recess:build', 'recess:installer', 'recess:canvasdesigner', 'postcss', 'bower-install-simple', 'bower', 'copy', 'clean:post']);
|
||||
|
||||
//triggered from grunt dev vs or grunt vs
|
||||
grunt.registerTask('build-dev', ['clean:pre', 'concat', 'recess:build', 'recess:installer', 'postcss', 'bower-install-simple', 'bower', 'copy']);
|
||||
@@ -92,7 +92,7 @@ module.exports = function (grunt) {
|
||||
' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
|
||||
src: {
|
||||
js: ['src/**/*.js', 'src/*.js'],
|
||||
|
||||
|
||||
common: ['src/common/**/*.js'],
|
||||
controllers: ['src/**/*.controller.js'],
|
||||
|
||||
@@ -143,17 +143,21 @@ module.exports = function (grunt) {
|
||||
vendor: {
|
||||
files: [{ dest: '<%= distdir %>/lib', src: '**', expand: true, cwd: 'lib/' }]
|
||||
},
|
||||
|
||||
views: {
|
||||
files: [{ dest: '<%= distdir %>/views', src: ['**/*.*', '!**/*.controller.js'], expand: true, cwd: 'src/views/' }]
|
||||
files: [{ dest: '<%= distdir %>/views', src: ['**/*.*', '!**/*.controller.js'], expand: true, cwd: 'src/views' }]
|
||||
},
|
||||
|
||||
app: {
|
||||
files: [
|
||||
{ dest: '<%= distdir %>/js', src: '*.js', expand: true, cwd: 'src/' }
|
||||
]
|
||||
},
|
||||
|
||||
mocks: {
|
||||
files: [{ dest: '<%= distdir %>/js', src: '*.js', expand: true, cwd: 'src/common/mocks/' }]
|
||||
},
|
||||
|
||||
vs: {
|
||||
files: [
|
||||
//everything except the index.html root file!
|
||||
@@ -197,6 +201,7 @@ module.exports = function (grunt) {
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
canvasdesignerJs: {
|
||||
src: ['src/canvasdesigner/canvasdesigner.global.js', 'src/canvasdesigner/canvasdesigner.controller.js', 'src/canvasdesigner/editors/*.js', 'src/canvasdesigner/lib/*.js'],
|
||||
dest: '<%= distdir %>/js/canvasdesigner.panel.js'
|
||||
@@ -324,6 +329,18 @@ module.exports = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
ngTemplateCache: {
|
||||
views: {
|
||||
files: {
|
||||
'<%= distdir %>/js/umbraco.views.js': 'src/views/**/*.html'
|
||||
},
|
||||
options: {
|
||||
trim: 'src/',
|
||||
module: 'umbraco.views'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
docs: {
|
||||
files: ['docs/src/**/*.md'],
|
||||
@@ -435,7 +452,7 @@ module.exports = function (grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
bower: {
|
||||
bower: {
|
||||
dev: {
|
||||
dest: '<%= distdir %>/lib',
|
||||
options: {
|
||||
@@ -473,7 +490,7 @@ module.exports = function (grunt) {
|
||||
},
|
||||
'angular-dynamic-locale': {
|
||||
files: ['tmhDynamicLocale.min.js', 'tmhDynamicLocale.min.js.map']
|
||||
},
|
||||
},
|
||||
'ng-file-upload': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['ng-file-upload.min.js']
|
||||
@@ -530,4 +547,5 @@ module.exports = function (grunt) {
|
||||
grunt.loadNpmTasks('grunt-ngdocs');
|
||||
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-hustler');
|
||||
};
|
||||
|
||||
BIN
src/Umbraco.Web.UI.Client/src/assets/img/transparent.png
Normal file
BIN
src/Umbraco.Web.UI.Client/src/assets/img/transparent.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,105 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function LayoutSelectorDirective() {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.layoutDropDownIsOpen = false;
|
||||
scope.showLayoutSelector = true;
|
||||
|
||||
function activate() {
|
||||
|
||||
setVisibility();
|
||||
|
||||
setActiveLayout(scope.layouts);
|
||||
|
||||
}
|
||||
|
||||
function setVisibility() {
|
||||
|
||||
var numberOfAllowedLayouts = getNumberOfAllowedLayouts(scope.layouts);
|
||||
|
||||
if(numberOfAllowedLayouts === 1) {
|
||||
scope.showLayoutSelector = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getNumberOfAllowedLayouts(layouts) {
|
||||
|
||||
var allowedLayouts = 0;
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
|
||||
var layout = layouts[i];
|
||||
|
||||
if(layout.selected === true) {
|
||||
allowedLayouts++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return allowedLayouts;
|
||||
}
|
||||
|
||||
function setActiveLayout(layouts) {
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
|
||||
var layout = layouts[i];
|
||||
|
||||
if(layout.name === scope.activeLayout.name && layout.path === scope.activeLayout.path) {
|
||||
layout.active = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scope.pickLayout = function(selectedLayout) {
|
||||
|
||||
for (var i = 0; scope.layouts.length > i; i++) {
|
||||
|
||||
var layout = scope.layouts[i];
|
||||
|
||||
layout.active = false;
|
||||
}
|
||||
|
||||
selectedLayout.active = true;
|
||||
|
||||
scope.activeLayout = selectedLayout;
|
||||
|
||||
scope.layoutDropDownIsOpen = false;
|
||||
|
||||
};
|
||||
|
||||
scope.toggleLayoutDropdown = function() {
|
||||
scope.layoutDropDownIsOpen = !scope.layoutDropDownIsOpen;
|
||||
};
|
||||
|
||||
scope.closeLayoutDropdown = function() {
|
||||
scope.layoutDropDownIsOpen = false;
|
||||
};
|
||||
|
||||
activate();
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-layout-selector.html',
|
||||
scope: {
|
||||
layouts: '=',
|
||||
activeLayout: '='
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbLayoutSelector', LayoutSelectorDirective);
|
||||
|
||||
})();
|
||||
@@ -59,6 +59,7 @@
|
||||
|
||||
$timeout(function() {
|
||||
input.focus();
|
||||
input.select();
|
||||
input.on("blur", onBlurHandler);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function MediaGridDirective($filter, mediaHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
scope.folders = [];
|
||||
scope.mediaItems = [];
|
||||
var itemMaxHeight = 200;
|
||||
|
||||
function activate() {
|
||||
|
||||
scope.folders = [];
|
||||
scope.mediaItems = [];
|
||||
|
||||
for (var i = 0; scope.items.length > i; i++) {
|
||||
|
||||
var item = scope.items[i];
|
||||
|
||||
setItemData(item);
|
||||
|
||||
setOriginalSize(item, itemMaxHeight);
|
||||
|
||||
seperateFolderAndMediaItems(item);
|
||||
|
||||
}
|
||||
|
||||
if(scope.mediaItems.length > 0) {
|
||||
setFlexValues(scope.mediaItems);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function setItemData(item) {
|
||||
|
||||
item.isFolder = !mediaHelper.hasFilePropertyType(item);
|
||||
|
||||
if(!item.isFolder){
|
||||
item.thumbnail = mediaHelper.resolveFile(item, true);
|
||||
item.image = mediaHelper.resolveFile(item, false);
|
||||
}
|
||||
}
|
||||
|
||||
function setOriginalSize(item, maxHeight) {
|
||||
|
||||
//set to a square by default
|
||||
item.originalWidth = maxHeight;
|
||||
item.originalHeight = maxHeight;
|
||||
item.aspectRatio = 1;
|
||||
|
||||
var widthProp = _.find(item.properties, function(v) { return (v.alias === "umbracoWidth"); });
|
||||
|
||||
if (widthProp && widthProp.value) {
|
||||
item.originalWidth = parseInt(widthProp.value, 10);
|
||||
if (isNaN(item.originalWidth)) {
|
||||
item.originalWidth = maxHeight;
|
||||
}
|
||||
}
|
||||
|
||||
var heightProp = _.find(item.properties, function(v) { return (v.alias === "umbracoHeight"); });
|
||||
|
||||
if (heightProp && heightProp.value) {
|
||||
item.originalHeight = parseInt(heightProp.value, 10);
|
||||
if (isNaN(item.originalHeight)) {
|
||||
item.originalHeight = maxHeight;
|
||||
}
|
||||
}
|
||||
|
||||
item.aspectRatio = item.originalWidth / item.originalHeight;
|
||||
|
||||
}
|
||||
|
||||
function seperateFolderAndMediaItems(item) {
|
||||
|
||||
if(item.isFolder){
|
||||
scope.folders.push(item);
|
||||
} else {
|
||||
scope.mediaItems.push(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function setFlexValues(mediaItems) {
|
||||
|
||||
var flexSortArray = mediaItems;
|
||||
var smallestImageWidth = null;
|
||||
var widestImageAspectRatio = null;
|
||||
|
||||
// sort array after image width with the widest image first
|
||||
flexSortArray = $filter('orderBy')(flexSortArray, 'originalWidth', true);
|
||||
|
||||
// find widest image aspect ratio
|
||||
widestImageAspectRatio = flexSortArray[0].aspectRatio;
|
||||
|
||||
// find smallest image width
|
||||
smallestImageWidth = flexSortArray[flexSortArray.length - 1].originalWidth;
|
||||
|
||||
for (var i = 0; flexSortArray.length > i; i++) {
|
||||
|
||||
var mediaItem = flexSortArray[i];
|
||||
var flex = 1 / (widestImageAspectRatio / mediaItem.aspectRatio);
|
||||
|
||||
if (flex === 0) {
|
||||
flex = 1;
|
||||
}
|
||||
|
||||
var imageMinWidth = smallestImageWidth * flex;
|
||||
|
||||
var flexStyle = {
|
||||
"flex": flex + " 1 " + imageMinWidth + "px",
|
||||
"max-width": mediaItem.originalWidth + "px"
|
||||
};
|
||||
|
||||
mediaItem.flexStyle = flexStyle;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scope.toggleSelectItem = function(item) {
|
||||
item.selected = !item.selected;
|
||||
};
|
||||
|
||||
var unbindItemsWatcher = scope.$watch('items', function(newValue, oldValue){
|
||||
activate();
|
||||
});
|
||||
|
||||
scope.$on('$destroy', function(){
|
||||
unbindItemsWatcher();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-media-grid.html',
|
||||
scope: {
|
||||
items: '='
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbMediaGrid', MediaGridDirective);
|
||||
|
||||
})();
|
||||
@@ -29,7 +29,7 @@ angular.module("umbraco.directives")
|
||||
scope.alias = "Generating Alias...";
|
||||
|
||||
generateAliasTimeout = $timeout(function () {
|
||||
contentTypeResource.getSafeAlias(value, false).then(function(safeAlias){
|
||||
contentTypeResource.getSafeAlias(value, true).then(function(safeAlias){
|
||||
scope.alias = safeAlias.alias;
|
||||
});
|
||||
}, 500);
|
||||
|
||||
@@ -211,7 +211,7 @@ angular.module('umbraco.directives')
|
||||
|
||||
link: function (scope, element, attrs, ctrl) {
|
||||
var active = false;
|
||||
var fn = $parse(attrs.delayedMouseleave);
|
||||
var fn = $parse(attrs.onDelayedMouseleave);
|
||||
|
||||
var leave_f = function(event) {
|
||||
var callback = function() {
|
||||
|
||||
@@ -41,7 +41,7 @@ function valRegex() {
|
||||
var patternValidator = function (viewValue) {
|
||||
if (regex) {
|
||||
//NOTE: we don't validate on empty values, use required validator for that
|
||||
if (!viewValue || regex.test(viewValue)) {
|
||||
if (!viewValue || regex.test(viewValue.toString())) {
|
||||
// it is valid
|
||||
ctrl.$setValidity('valRegex', true);
|
||||
//assign a message to the validator
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.dialogService
|
||||
*
|
||||
* @requires $rootScope
|
||||
* @requires $rootScope
|
||||
* @requires $compile
|
||||
* @requires $http
|
||||
* @requires $log
|
||||
* @requires $q
|
||||
* @requires $templateCache
|
||||
*
|
||||
*
|
||||
* @description
|
||||
* Application-wide service for handling modals, overlays and dialogs
|
||||
* By default it injects the passed template url into a div to body of the document
|
||||
@@ -22,10 +22,10 @@
|
||||
* <pre>
|
||||
* var dialog = dialogService.open({template: 'path/to/page.html', show: true, callback: done});
|
||||
* functon done(data){
|
||||
* //The dialog has been submitted
|
||||
* //The dialog has been submitted
|
||||
* //data contains whatever the dialog has selected / attached
|
||||
* }
|
||||
* </pre>
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
angular.module('umbraco.services')
|
||||
@@ -38,12 +38,12 @@ angular.module('umbraco.services')
|
||||
for (var i = 0; i < dialogs.length; i++) {
|
||||
var dialog = dialogs[i];
|
||||
|
||||
//very special flag which means that global events cannot close this dialog - currently only used on the login
|
||||
//very special flag which means that global events cannot close this dialog - currently only used on the login
|
||||
// dialog since it's special and cannot be closed without logging in.
|
||||
if (!dialog.manualClose) {
|
||||
dialog.close(args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,28 +56,18 @@ angular.module('umbraco.services')
|
||||
//this is not entirely enough since the damn webforms scriploader still complains
|
||||
if (dialog.iframe) {
|
||||
dialog.element.find("iframe").attr("src", "about:blank");
|
||||
$timeout(function () {
|
||||
//we need to do more than just remove the element, this will not destroy the
|
||||
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
|
||||
// take care of this ourselves we have memory leaks.
|
||||
dialog.element.remove();
|
||||
//SD: No idea why this is required but was there before - pretty sure it's not required
|
||||
$("#" + dialog.element.attr("id")).remove();
|
||||
dialog.scope.$destroy();
|
||||
}, 1000);
|
||||
} else {
|
||||
//we need to do more than just remove the element, this will not destroy the
|
||||
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
|
||||
// take care of this ourselves we have memory leaks.
|
||||
dialog.element.remove();
|
||||
//SD: No idea why this is required but was there before - pretty sure it's not required
|
||||
$("#" + dialog.element.attr("id")).remove();
|
||||
dialog.scope.$destroy();
|
||||
}
|
||||
}
|
||||
|
||||
//remove 'this' dialog from the dialogs array
|
||||
dialogs = _.reject(dialogs, function (i) { return i === dialog; });
|
||||
dialog.scope.$destroy();
|
||||
|
||||
//we need to do more than just remove the element, this will not destroy the
|
||||
// scope in angular 1.1x, in angular 1.2x this is taken care of but if we dont
|
||||
// take care of this ourselves we have memory leaks.
|
||||
dialog.element.remove();
|
||||
|
||||
//remove 'this' dialog from the dialogs array
|
||||
dialogs = _.reject(dialogs, function (i) { return i === dialog; });
|
||||
}
|
||||
}
|
||||
|
||||
/** Internal method that handles opening all dialogs */
|
||||
@@ -93,17 +83,17 @@ angular.module('umbraco.services')
|
||||
template: "views/common/notfound.html",
|
||||
callback: undefined,
|
||||
closeCallback: undefined,
|
||||
element: undefined,
|
||||
element: undefined,
|
||||
// It will set this value as a property on the dialog controller's scope as dialogData,
|
||||
// used to pass in custom data to the dialog controller's $scope. Though this is near identical to
|
||||
// the dialogOptions property that is also set the the dialog controller's $scope object.
|
||||
// used to pass in custom data to the dialog controller's $scope. Though this is near identical to
|
||||
// the dialogOptions property that is also set the the dialog controller's $scope object.
|
||||
// So there's basically 2 ways of doing the same thing which we're now stuck with and in fact
|
||||
// dialogData has another specially attached property called .selection which gets used.
|
||||
dialogData: undefined
|
||||
};
|
||||
|
||||
var dialog = angular.extend(defaults, options);
|
||||
|
||||
|
||||
//NOTE: People should NOT pass in a scope object that is legacy functoinality and causes problems. We will ALWAYS
|
||||
// destroy the scope when the dialog is closed regardless if it is in use elsewhere which is why it shouldn't be done.
|
||||
var scope = options.scope || $rootScope.$new();
|
||||
@@ -156,7 +146,7 @@ angular.module('umbraco.services')
|
||||
|
||||
dialog.element.css("width", dialog.width);
|
||||
|
||||
//Autoshow
|
||||
//Autoshow
|
||||
if (dialog.show) {
|
||||
dialog.element.modal('show');
|
||||
}
|
||||
@@ -167,7 +157,7 @@ angular.module('umbraco.services')
|
||||
else {
|
||||
|
||||
//We need to load the template with an httpget and once it's loaded we'll compile and assign the result to the container
|
||||
// object. However since the result could be a promise or just data we need to use a $q.when. We still need to return the
|
||||
// object. However since the result could be a promise or just data we need to use a $q.when. We still need to return the
|
||||
// $modal object so we'll actually return the modal object synchronously without waiting for the promise. Otherwise this openDialog
|
||||
// method will always need to return a promise which gets nasty because of promises in promises plus the result just needs a reference
|
||||
// to the $modal object which will not change (only it's contents will change).
|
||||
@@ -177,7 +167,7 @@ angular.module('umbraco.services')
|
||||
// Build modal object
|
||||
dialog.element.html(template);
|
||||
|
||||
//append to body or other container element
|
||||
//append to body or other container element
|
||||
dialog.container.append(dialog.element);
|
||||
|
||||
// Compile modal content
|
||||
@@ -224,8 +214,8 @@ angular.module('umbraco.services')
|
||||
scope.close = function (data) {
|
||||
dialog.close(data);
|
||||
};
|
||||
|
||||
//NOTE: This can ONLY ever be used to show the dialog if dialog.show is false (autoshow).
|
||||
|
||||
//NOTE: This can ONLY ever be used to show the dialog if dialog.show is false (autoshow).
|
||||
// You CANNOT call show() after you call hide(). hide = close, they are the same thing and once
|
||||
// a dialog is closed it's resources are disposed of.
|
||||
scope.show = function () {
|
||||
@@ -237,7 +227,7 @@ angular.module('umbraco.services')
|
||||
//just show normally
|
||||
dialog.element.modal('show');
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
scope.select = function (item) {
|
||||
@@ -266,11 +256,11 @@ angular.module('umbraco.services')
|
||||
|
||||
dialog.scope = scope;
|
||||
|
||||
//Autoshow
|
||||
//Autoshow
|
||||
if (dialog.show) {
|
||||
scope.show();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
//Return the modal object outside of the promise!
|
||||
@@ -368,7 +358,7 @@ angular.module('umbraco.services')
|
||||
* @param {Function} options.callback callback function
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
contentPicker: function (options) {
|
||||
contentPicker: function (options) {
|
||||
|
||||
options.treeAlias = "content";
|
||||
options.section = "content";
|
||||
@@ -424,7 +414,7 @@ angular.module('umbraco.services')
|
||||
* @returns {Object} modal object
|
||||
*/
|
||||
memberPicker: function (options) {
|
||||
|
||||
|
||||
options.treeAlias = "member";
|
||||
options.section = "member";
|
||||
|
||||
@@ -511,7 +501,7 @@ angular.module('umbraco.services')
|
||||
* @name umbraco.services.dialogService#embedDialog
|
||||
* @methodOf umbraco.services.dialogService
|
||||
* @description
|
||||
* Opens a dialog to an embed dialog
|
||||
* Opens a dialog to an embed dialog
|
||||
*/
|
||||
embedDialog: function (options) {
|
||||
options.template = 'views/common/dialogs/rteembed.html';
|
||||
@@ -546,4 +536,4 @@ angular.module('umbraco.services')
|
||||
return openDialog(options);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.navigationService
|
||||
*
|
||||
* @requires $rootScope
|
||||
* @requires $rootScope
|
||||
* @requires $routeParams
|
||||
* @requires $log
|
||||
* @requires $location
|
||||
* @requires dialogService
|
||||
* @requires treeService
|
||||
* @requires sectionResource
|
||||
*
|
||||
*
|
||||
* @description
|
||||
* Service to handle the main application navigation. Responsible for invoking the tree
|
||||
* Section navigation and search, and maintain their state for the entire application lifetime
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
function navigationService($rootScope, $routeParams, $log, $location, $q, $timeout, $injector, dialogService, umbModelMapper, treeService, notificationsService, historyService, appState, angularHelper) {
|
||||
|
||||
|
||||
|
||||
//used to track the current dialog object
|
||||
var currentDialog = null;
|
||||
|
||||
|
||||
//the main tree event handler, which gets assigned via the setupTreeEvents method
|
||||
var mainTreeEventHandler = null;
|
||||
//tracks the user profile dialog
|
||||
@@ -35,8 +35,8 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
appState.setMenuState("showMenuDialog", false);
|
||||
appState.setGlobalState("stickyNavigation", false);
|
||||
appState.setGlobalState("showTray", false);
|
||||
|
||||
//$("#search-form input").focus();
|
||||
|
||||
//$("#search-form input").focus();
|
||||
break;
|
||||
case 'menu':
|
||||
appState.setGlobalState("navMode", "menu");
|
||||
@@ -87,7 +87,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
/** initializes the navigation service */
|
||||
init: function() {
|
||||
|
||||
//keep track of the current section - initially this will always be undefined so
|
||||
//keep track of the current section - initially this will always be undefined so
|
||||
// no point in setting it now until it changes.
|
||||
$rootScope.$watch(function () {
|
||||
return $routeParams.section;
|
||||
@@ -95,7 +95,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
appState.setSectionState("currentSection", newVal);
|
||||
});
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* Shows the legacy iframe and loads in the content based on the source url
|
||||
* @param {String} source The URL to load into the iframe
|
||||
*/
|
||||
loadLegacyIFrame: function (source) {
|
||||
loadLegacyIFrame: function (source) {
|
||||
$location.path("/" + appState.getSectionState("currentSection") + "/framed/" + encodeURIComponent(source));
|
||||
},
|
||||
|
||||
@@ -149,7 +149,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
showTree: function (sectionAlias, syncArgs) {
|
||||
if (sectionAlias !== appState.getSectionState("currentSection")) {
|
||||
appState.setSectionState("currentSection", sectionAlias);
|
||||
|
||||
|
||||
if (syncArgs) {
|
||||
this.syncTree(syncArgs);
|
||||
}
|
||||
@@ -165,7 +165,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
appState.setGlobalState("showTray", false);
|
||||
},
|
||||
|
||||
/**
|
||||
/**
|
||||
Called to assign the main tree event handler - this is called by the navigation controller.
|
||||
TODO: Potentially another dev could call this which would kind of mung the whole app so potentially there's a better way.
|
||||
*/
|
||||
@@ -179,7 +179,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
|
||||
//when a tree node is synced this event will fire, this allows us to set the currentNode
|
||||
mainTreeEventHandler.bind("treeSynced", function (ev, args) {
|
||||
|
||||
|
||||
if (args.activate === undefined || args.activate === true) {
|
||||
//set the current selected node
|
||||
appState.setTreeState("selectedNode", args.node);
|
||||
@@ -196,7 +196,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
|
||||
//Set the current action node (this is not the same as the current selected node!)
|
||||
appState.setMenuState("currentNode", args.node);
|
||||
|
||||
|
||||
if (args.event && args.event.altKey) {
|
||||
args.skipDefault = true;
|
||||
}
|
||||
@@ -220,7 +220,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
ev.preventDefault();
|
||||
|
||||
if (n.metaData && n.metaData["jsClickCallback"] && angular.isString(n.metaData["jsClickCallback"]) && n.metaData["jsClickCallback"] !== "") {
|
||||
//this is a legacy tree node!
|
||||
//this is a legacy tree node!
|
||||
var jsPrefix = "javascript:";
|
||||
var js;
|
||||
if (n.metaData["jsClickCallback"].startsWith(jsPrefix)) {
|
||||
@@ -243,7 +243,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
else if (n.routePath) {
|
||||
//add action to the history service
|
||||
historyService.add({ name: n.name, link: n.routePath, icon: n.icon });
|
||||
|
||||
|
||||
//put this node into the tree state
|
||||
appState.setTreeState("selectedNode", args.node);
|
||||
//when a node is clicked we also need to set the active menu node to this node
|
||||
@@ -269,7 +269,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* The path format is: ["itemId","itemId"], and so on
|
||||
* so to sync to a specific document type node do:
|
||||
* <pre>
|
||||
* navigationService.syncTree({tree: 'content', path: ["-1","123d"], forceReload: true});
|
||||
* navigationService.syncTree({tree: 'content', path: ["-1","123d"], forceReload: true});
|
||||
* </pre>
|
||||
* @param {Object} args arguments passed to the function
|
||||
* @param {String} args.tree the tree alias to sync to
|
||||
@@ -287,7 +287,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
if (!args.tree) {
|
||||
throw "args.tree cannot be null";
|
||||
}
|
||||
|
||||
|
||||
if (mainTreeEventHandler) {
|
||||
//returns a promise
|
||||
return mainTreeEventHandler.syncTree(args);
|
||||
@@ -297,8 +297,8 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
return angularHelper.rejectedPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
Internal method that should ONLY be used by the legacy API wrapper, the legacy API used to
|
||||
/**
|
||||
Internal method that should ONLY be used by the legacy API wrapper, the legacy API used to
|
||||
have to set an active tree and then sync, the new API does this in one method by using syncTree
|
||||
*/
|
||||
_syncPath: function(path, forceReload) {
|
||||
@@ -322,8 +322,8 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Internal method that should ONLY be used by the legacy API wrapper, the legacy API used to
|
||||
/**
|
||||
Internal method that should ONLY be used by the legacy API wrapper, the legacy API used to
|
||||
have to set an active tree and then sync, the new API does this in one method by using syncTreePath
|
||||
*/
|
||||
_setActiveTreeType: function (treeAlias, loadChildren) {
|
||||
@@ -331,7 +331,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
mainTreeEventHandler._setActiveTreeType(treeAlias, loadChildren);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.navigationService#hideTree
|
||||
@@ -356,7 +356,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* @methodOf umbraco.services.navigationService
|
||||
*
|
||||
* @description
|
||||
* Hides the tree by hiding the containing dom element.
|
||||
* Hides the tree by hiding the containing dom element.
|
||||
* This always returns a promise!
|
||||
*
|
||||
* @param {Event} event the click event triggering the method, passed from the DOM element
|
||||
@@ -382,7 +382,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
|
||||
//NOTE: This is assigning the current action node - this is not the same as the currently selected node!
|
||||
appState.setMenuState("currentNode", args.node);
|
||||
|
||||
|
||||
//ensure the current dialog is cleared before creating another!
|
||||
if (currentDialog) {
|
||||
dialogService.close(currentDialog);
|
||||
@@ -400,13 +400,13 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
}
|
||||
}
|
||||
|
||||
//there is no default or we couldn't find one so just continue showing the menu
|
||||
//there is no default or we couldn't find one so just continue showing the menu
|
||||
|
||||
setMode("menu");
|
||||
|
||||
appState.setMenuState("currentNode", args.node);
|
||||
appState.setMenuState("menuActions", data.menuItems);
|
||||
appState.setMenuState("dialogTitle", args.node.name);
|
||||
appState.setMenuState("dialogTitle", args.node.name);
|
||||
|
||||
//we're not opening a dialog, return null.
|
||||
deferred.resolve(null);
|
||||
@@ -437,7 +437,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
throw "action cannot be null";
|
||||
}
|
||||
if (!node) {
|
||||
throw "node cannot be null";
|
||||
throw "node cannot be null";
|
||||
}
|
||||
if (!section) {
|
||||
throw "section cannot be null";
|
||||
@@ -456,9 +456,9 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
var menuAction = action.metaData["jsAction"].split('.');
|
||||
if (menuAction.length !== 2) {
|
||||
|
||||
//if it is not two parts long then this most likely means that it's a legacy action
|
||||
//if it is not two parts long then this most likely means that it's a legacy action
|
||||
var js = action.metaData["jsAction"].replace("javascript:", "");
|
||||
//there's not really a different way to acheive this except for eval
|
||||
//there's not really a different way to acheive this except for eval
|
||||
eval(js);
|
||||
}
|
||||
else {
|
||||
@@ -551,7 +551,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
modalClass: "umb-modal-left",
|
||||
show: true
|
||||
});
|
||||
|
||||
|
||||
return service.helpDialog;
|
||||
},
|
||||
|
||||
@@ -564,13 +564,13 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* Opens a dialog, for a given action on a given tree node
|
||||
* uses the dialogService to inject the selected action dialog
|
||||
* into #dialog div.umb-panel-body
|
||||
* the path to the dialog view is determined by:
|
||||
* the path to the dialog view is determined by:
|
||||
* "views/" + current tree + "/" + action alias + ".html"
|
||||
* The dialog controller will get passed a scope object that is created here with the properties:
|
||||
* scope.currentNode = the selected tree node
|
||||
* scope.currentAction = the selected menu item
|
||||
* so that the dialog controllers can use these properties
|
||||
*
|
||||
*
|
||||
* @param {Object} args arguments passed to the function
|
||||
* @param {Scope} args.scope current scope passed to the dialog
|
||||
* @param {Object} args.action the clicked action containing `name` and `alias`
|
||||
@@ -590,6 +590,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
//ensure the current dialog is cleared before creating another!
|
||||
if (currentDialog) {
|
||||
dialogService.close(currentDialog);
|
||||
currentDialog = null;
|
||||
}
|
||||
|
||||
setMode("dialog");
|
||||
@@ -649,14 +650,14 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
}
|
||||
|
||||
//TODO: some action's want to launch a new window like live editing, we support this in the menu item's metadata with
|
||||
// a key called: "actionUrlMethod" which can be set to either: Dialog, BlankWindow. Normally this is always set to Dialog
|
||||
// if a URL is specified in the "actionUrl" metadata. For now I'm not going to implement launching in a blank window,
|
||||
// a key called: "actionUrlMethod" which can be set to either: Dialog, BlankWindow. Normally this is always set to Dialog
|
||||
// if a URL is specified in the "actionUrl" metadata. For now I'm not going to implement launching in a blank window,
|
||||
// though would be v-easy, just not sure we want to ever support that?
|
||||
|
||||
var dialog = dialogService.open(
|
||||
{
|
||||
container: $("#dialog div.umb-modalcolumn-body"),
|
||||
//The ONLY reason we're passing in scope to the dialogService (which is legacy functionality) is
|
||||
//The ONLY reason we're passing in scope to the dialogService (which is legacy functionality) is
|
||||
// for backwards compatibility since many dialogs require $scope.currentNode or $scope.currentAction
|
||||
// to exist
|
||||
scope: dialogScope,
|
||||
@@ -685,9 +686,9 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* hides the currently open dialog
|
||||
*/
|
||||
hideDialog: function (showMenu) {
|
||||
|
||||
|
||||
setMode("default");
|
||||
|
||||
|
||||
if(showMenu){
|
||||
this.showMenu(undefined, { skipDefault: true, node: appState.getMenuState("currentNode") });
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@
|
||||
@import "components/umb-tabs.less";
|
||||
@import "components/umb-load-indicator.less";
|
||||
@import "components/umb-breadcrumbs.less";
|
||||
@import "components/umb-media-grid.less";
|
||||
@import "components/umb-layout-selector.less";
|
||||
@import "components/overlays/umb-overlay-backdrop.less";
|
||||
|
||||
@import "components/buttons/umb-button.less";
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
.umb-layout-selector {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.umb-layout-selector__active-layout {
|
||||
box-sizing: border-box;
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
margin: 0 8px;
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.umb-layout-selector__active-layout:hover {
|
||||
border-color: @grayLight;
|
||||
}
|
||||
|
||||
.umb-layout-selector__dropdown {
|
||||
position: absolute;
|
||||
padding: 5px;
|
||||
background: #333;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
background: #fff;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
transform: translate(-50%,0);
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.umb-layout-selector__dropdown-item {
|
||||
padding: 5px;
|
||||
margin: 3px 5px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
border: 1px solid transparent;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.umb-layout-selector__dropdown-item:hover {
|
||||
border: 1px solid @grayLight;
|
||||
}
|
||||
|
||||
.umb-layout-selector__dropdown-item.-active {
|
||||
border: 1px solid @blue;
|
||||
}
|
||||
|
||||
.umb-layout-selector__dropdown-item-icon {
|
||||
font-size: 20px;
|
||||
color: @gray;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
.umb-media-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* ---------- FOLDERS --------- */
|
||||
|
||||
.umb-media-grid__folders {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.umb-media-grid__folder {
|
||||
background: @grayLighter;
|
||||
margin: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 30px 10px 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1 1 200px;
|
||||
border: 1px solid transparent;
|
||||
transition: border 0.2s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.umb-media-grid__folder.-selected {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.umb-media-grid__folder:focus,
|
||||
.umb-media-grid__folder:active {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-media-grid__folder:hover {
|
||||
text-decoration: none;
|
||||
border: 1px solid @blue;
|
||||
}
|
||||
|
||||
.umb-media-grid__folder-icon {
|
||||
font-size: 20px;
|
||||
color: @gray;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.umb-media-grid__folder-name {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* ---------- MEDIA ---------- */
|
||||
|
||||
.umb-media-grid__media {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.umb-media-grid__item {
|
||||
margin: 7px;
|
||||
position: relative;
|
||||
background: @grayLighter;
|
||||
}
|
||||
|
||||
.umb-media-grid__item:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-media-grid__item-image-placeholder {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.umb-media-grid__item-image {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.umb-media-grid__item-image.-faded {
|
||||
opacity: 0.5;
|
||||
transition: opacity 100ms ease-in;
|
||||
}
|
||||
|
||||
.umb-media-grid__item-overlay {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
padding: 5px;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
background: black;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.umb-media-grid__item:hover .umb-media-grid__item-overlay {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.umb-media-grid__item-name {
|
||||
text-align: center;
|
||||
color: @gray;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.umb-media-grid__item-icon {
|
||||
color: @gray;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
font-size: 40px;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
|
||||
.umb-media-grid__select {
|
||||
opacity: 0;
|
||||
border: 1px solid #ffffff;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.umb-media-grid__select.-size-20 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.umb-media-grid__select:hover {
|
||||
background: @blue;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.umb-media-grid__select.-selected {
|
||||
opacity: 1;
|
||||
background: @blue;
|
||||
}
|
||||
|
||||
.umb-media-grid__select-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.umb-media-grid__item:hover .umb-media-grid__select,
|
||||
.umb-media-grid__folder:hover .umb-media-grid__select{
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
@@ -167,6 +167,12 @@ input[type="color"],
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
input.-full-width-input {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
// Reset appearance properties for textual inputs and textarea
|
||||
// Declare width for legacy (can't be on input[type=*] selectors or it's too specific)
|
||||
input,
|
||||
@@ -429,7 +435,7 @@ input[type="checkbox"][readonly] {
|
||||
|
||||
|
||||
//SD: NOTE: Had to change these to use our 'form' prefixed colors since we cannot
|
||||
// share colors with the notifications/alerts. Also had to change them so that
|
||||
// share colors with the notifications/alerts. Also had to change them so that
|
||||
// we do not show any errors unless the containing element has the show-validation
|
||||
// class assigned.
|
||||
|
||||
@@ -792,4 +798,4 @@ legend + .control-group {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus,
|
||||
.dropdown-submenu:hover > a,
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus,
|
||||
.dropdown-submenu:hover > a,
|
||||
.dropdown-submenu:focus > a {
|
||||
color: @black;
|
||||
background: @grayLighter;
|
||||
@@ -124,7 +124,7 @@
|
||||
}
|
||||
|
||||
.umb-listview .selected i.icon, .umb-listview tbody tr:hover i.icon{display: none}
|
||||
.umb-listview .selected input[type="checkbox"],
|
||||
.umb-listview .selected input[type="checkbox"],
|
||||
.umb-listview tr:hover input[type="checkbox"]{display: inline-block !important;}
|
||||
.umb-listview .inactive{color: @grayLight;}
|
||||
|
||||
@@ -181,6 +181,10 @@
|
||||
color: #b0b0b0
|
||||
}
|
||||
|
||||
.umb-listview .pagination {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.umb-listview .pagination ul {
|
||||
-webkit-border-radius: 0px;
|
||||
-moz-border-radius: 0px;
|
||||
@@ -195,7 +199,7 @@
|
||||
border:none;
|
||||
padding: 8px 4px 2px 4px;
|
||||
background: none;
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
color: #b0b0b0
|
||||
}
|
||||
|
||||
@@ -242,3 +246,87 @@
|
||||
.table-striped tbody i:hover {
|
||||
display: none !important
|
||||
}
|
||||
|
||||
/* ---------- LAYOUTS ---------- */
|
||||
|
||||
.list-view-layouts {
|
||||
|
||||
}
|
||||
|
||||
.list-view-layout {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
background: @grayLighter;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.list-view-layout__sort-handle {
|
||||
font-size: 14px;
|
||||
color: @grayLight;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.list-view-layout__name {
|
||||
flex: 5;
|
||||
font-weight: bold;
|
||||
margin-right: 15px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
.list-view-layout__name-text {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.list-view-layout__system {
|
||||
font-size: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.list-view-layout__path {
|
||||
flex: 10;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.list-view-layout__icon {
|
||||
font-size: 18px;
|
||||
margin-right: 10px;
|
||||
vertical-align: middle;
|
||||
border: 1px solid @grayLight;
|
||||
border-radius: 5px;
|
||||
background: #ffffff;
|
||||
padding: 6px 8px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.list-view-layout__icon:hover,
|
||||
.list-view-layout__icon:focus,
|
||||
.list-view-layout__icon:active {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.list-view-layout__remove-layout {
|
||||
flex: 2;
|
||||
text-align: right;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.list-view-add-layout {
|
||||
margin-top: 10px;
|
||||
color: @blue;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.list-view-add-layout:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<div class="umb-layout-selector" ng-show="showLayoutSelector">
|
||||
|
||||
<div class="umb-layout-selector__active-layout" ng-click="toggleLayoutDropdown()">
|
||||
<i class="{{ activeLayout.icon }}"></i>
|
||||
</div>
|
||||
|
||||
<div ng-if="layoutDropDownIsOpen" class="umb-layout-selector__dropdown shadow-depth-3 animated -half-second fadeIn" on-outside-click="closeLayoutDropdown()">
|
||||
|
||||
<div ng-repeat="layout in layouts | filter:{selected:true}" class="umb-layout-selector__dropdown-item" ng-click="pickLayout(layout)" ng-class="{'-active': layout.active }">
|
||||
<i class="{{ layout.icon }} umb-layout-selector__dropdown-item-icon"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
<div class="umb-media-grid">
|
||||
|
||||
<div class="umb-media-grid__folders">
|
||||
|
||||
<a href="#{{folder.editPath}}" class="umb-media-grid__folder" ng-repeat="folder in folders">
|
||||
|
||||
<i class="umb-media-grid__folder-icon {{ folder.icon }}"></i>
|
||||
|
||||
<div class="umb-media-grid__folder-name">{{ folder.name }}</div>
|
||||
|
||||
<div class="umb-media-grid__select -size-20" ng-click="toggleSelectItem(folder)" ng-class="{'-selected': folder.selected}" prevent-default>
|
||||
<i class="icon-check umb-media-grid__select-icon"></i>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-media-grid__media">
|
||||
|
||||
<a href="#{{item.editPath}}" ng-repeat="item in mediaItems" ng-style="item.flexStyle" class="umb-media-grid__item">
|
||||
|
||||
<div class="umb-media-grid__select" ng-click="toggleSelectItem(item)" ng-class="{'-selected': item.selected}" prevent-default>
|
||||
<i class="icon-check umb-media-grid__select-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="umb-media-grid__item-overlay">{{item.name}}</div>
|
||||
|
||||
<img class="umb-media-grid__item-image" ng-if="item.thumbnail" ng-src="{{item.thumbnail}}" alt="{{item.name}}" ng-class="{'-faded': item.selected}" />
|
||||
|
||||
<img class="umb-media-grid__item-image" ng-if="!item.thumbnail" src="assets/img/transparent.png" alt="{{item.name}}" />
|
||||
|
||||
<i class="umb-media-grid__item-icon {{ item.icon }}" ng-if="!item.thumbnail"></i>
|
||||
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -7,7 +7,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
searchText = value + "...";
|
||||
});
|
||||
|
||||
$scope.relateToOriginal = false;
|
||||
$scope.relateToOriginal = true;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.busy = false;
|
||||
$scope.searchInfo = {
|
||||
@@ -42,7 +42,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
$scope.target = args.node;
|
||||
$scope.target.selected = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function nodeExpandedHandler(ev, args) {
|
||||
@@ -50,7 +50,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
|
||||
//iterate children
|
||||
_.each(args.children, function (child) {
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
//check if any of the items are list views, if so we need to add a custom
|
||||
// child: A node to activate the search
|
||||
if (child.metaData.isContainer) {
|
||||
child.hasChildren = true;
|
||||
@@ -78,18 +78,18 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
$scope.searchInfo.results = [];
|
||||
}
|
||||
|
||||
// method to select a search result
|
||||
// method to select a search result
|
||||
$scope.selectResult = function (evt, result) {
|
||||
result.selected = result.selected === true ? false : true;
|
||||
nodeSelectHandler(evt, { event: evt, node: result });
|
||||
};
|
||||
|
||||
//callback when there are search results
|
||||
//callback when there are search results
|
||||
$scope.onSearchResults = function (results) {
|
||||
$scope.searchInfo.results = results;
|
||||
$scope.searchInfo.showSearch = true;
|
||||
};
|
||||
|
||||
|
||||
$scope.copy = function () {
|
||||
|
||||
$scope.busy = true;
|
||||
@@ -129,4 +129,4 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler);
|
||||
$scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<i class="icon-alert red"></i> <strong class="red">2345 Documents</strong> will be deleted permanently if you delete this document type,
|
||||
please confirm you want to delete these as well.
|
||||
<i class="icon-alert red"></i> <strong class="red">All Documents</strong>
|
||||
using this document type will be deleted permanently, please confirm you want to delete these as well.
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" ng-model="confirmed" /> Delete all 2345 documents using {{currentNode.name}}
|
||||
<input type="checkbox" ng-model="confirmed" /> Delete {{currentNode.name}} and all documents using this type
|
||||
</label>
|
||||
|
||||
<umb-confirm ng-if="confirmed" on-confirm="performDelete" on-cancel="cancel">
|
||||
|
||||
@@ -24,23 +24,23 @@
|
||||
{
|
||||
"name": "Design",
|
||||
"icon": "icon-document-dashed-line",
|
||||
"view": "views/documentType/views/design/design.html",
|
||||
"view": "views/documenttypes/views/design/design.html",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"name": "List view",
|
||||
"icon": "icon-list",
|
||||
"view": "views/documentType/views/listview/listview.html"
|
||||
"view": "views/documenttypes/views/listview/listview.html"
|
||||
},
|
||||
{
|
||||
"name": "Permissions",
|
||||
"icon": "icon-keychain",
|
||||
"view": "views/documentType/views/permissions/permissions.html"
|
||||
"view": "views/documenttypes/views/permissions/permissions.html"
|
||||
},
|
||||
{
|
||||
"name": "Templates",
|
||||
"icon": "icon-layout",
|
||||
"view": "views/documentType/views/templates/templates.html"
|
||||
"view": "views/documenttypes/views/templates/templates.html"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -24,18 +24,18 @@
|
||||
{
|
||||
"name": "Design",
|
||||
"icon": "icon-document-dashed-line",
|
||||
"view": "views/mediaType/views/design/design.html",
|
||||
"view": "views/mediatypes/views/design/design.html",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"name": "List view",
|
||||
"icon": "icon-list",
|
||||
"view": "views/mediaType/views/listview/listview.html"
|
||||
"view": "views/mediatypes/views/listview/listview.html"
|
||||
},
|
||||
{
|
||||
"name": "Permissions",
|
||||
"icon": "icon-keychain",
|
||||
"view": "views/mediaType/views/permissions/permissions.html"
|
||||
"view": "views/mediatypes/views/permissions/permissions.html"
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
vm.currentNode = null;
|
||||
vm.contentType = {};
|
||||
vm.page = {};
|
||||
vm.page.loading = false;
|
||||
vm.page.saveButtonState = "init";
|
||||
vm.page.loading = false;
|
||||
vm.page.saveButtonState = "init";
|
||||
vm.page.navigation = [
|
||||
{
|
||||
"name": "Design",
|
||||
"icon": "icon-document-dashed-line",
|
||||
"view": "views/membertype/views/design/design.html",
|
||||
"view": "views/membertypes/views/design/design.html",
|
||||
"active": true
|
||||
}
|
||||
];
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<div>
|
||||
<input name="decimalField" class="umb-editor umb-number"
|
||||
type="number"
|
||||
ng-model="model.value"
|
||||
val-server="value"
|
||||
fix-number />
|
||||
|
||||
<span class="help-inline" val-msg-for="decimalField" val-toggle-msg="number">Not a number</span>
|
||||
<span class="help-inline" val-msg-for="decimalField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
|
||||
|
||||
</div>
|
||||
@@ -3,7 +3,7 @@
|
||||
type="number"
|
||||
ng-model="model.value"
|
||||
val-server="value"
|
||||
fix-number />
|
||||
fix-number />
|
||||
|
||||
<span class="help-inline" val-msg-for="numberField" val-toggle-msg="number">Not a number</span>
|
||||
<span class="help-inline" val-msg-for="numberField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<div class="umb-editor">
|
||||
<input name="decimalField"
|
||||
type="number"
|
||||
class="umb-editor umb-number"
|
||||
ng-model="model.value"
|
||||
val-server="value"
|
||||
fix-number min="{{model.config.min}}" max="{{model.config.max}}" step="{{model.config.step}}" />
|
||||
|
||||
<span class="help-inline" val-msg-for="decimalField" val-toggle-msg="number">Not a number</span>
|
||||
<span class="help-inline" val-msg-for="decimalField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
|
||||
</div>
|
||||
@@ -1,10 +1,11 @@
|
||||
<div class="umb-editor">
|
||||
<input name="integerField" type="number" class="umb-editor umb-number "
|
||||
ng-model="model.value"
|
||||
val-server="value"
|
||||
fix-number min="{{model.config.min}}" max="{{model.config.max}}" step="{{model.config.step}}" />
|
||||
<input name="integerField"
|
||||
type="number"
|
||||
class="umb-editor umb-number "
|
||||
ng-model="model.value"
|
||||
val-server="value"
|
||||
fix-number min="{{model.config.min}}" max="{{model.config.max}}" step="{{model.config.step}}" />
|
||||
|
||||
<span class="help-inline" val-msg-for="integerField" val-toggle-msg="number">Not a number</span>
|
||||
<span class="help-inline" val-msg-for="integerField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.PrevalueEditors.ListViewLayoutsPreValsController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for configuring layouts for list views
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function ListViewLayoutsPreValsController($scope) {
|
||||
|
||||
var vm = this;
|
||||
vm.focusLayoutName = false;
|
||||
|
||||
vm.layoutsSortableOptions = {
|
||||
distance: 10,
|
||||
tolerance: "pointer",
|
||||
opacity: 0.7,
|
||||
scroll: true,
|
||||
cursor: "move",
|
||||
handle: ".list-view-layout__sort-handle"
|
||||
};
|
||||
|
||||
vm.addLayout = addLayout;
|
||||
vm.removeLayout = removeLayout;
|
||||
vm.openIconPicker = openIconPicker;
|
||||
|
||||
function activate() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function addLayout() {
|
||||
|
||||
vm.focusLayoutName = false;
|
||||
|
||||
var layout = {
|
||||
"name": "",
|
||||
"path": "",
|
||||
"icon": "icon-stop",
|
||||
"selected": true
|
||||
};
|
||||
|
||||
$scope.model.value.push(layout);
|
||||
|
||||
}
|
||||
|
||||
function removeLayout($index, layout) {
|
||||
$scope.model.value.splice($index, 1);
|
||||
}
|
||||
|
||||
function openIconPicker(layout) {
|
||||
|
||||
vm.iconPickerDialog = {};
|
||||
vm.iconPickerDialog.view = "iconpicker";
|
||||
vm.iconPickerDialog.show = true;
|
||||
|
||||
vm.iconPickerDialog.pickIcon = function(icon, color) {
|
||||
|
||||
layout.icon = icon;
|
||||
vm.focusLayoutName = true;
|
||||
|
||||
vm.iconPickerDialog.show = false;
|
||||
vm.iconPickerDialog = null;
|
||||
};
|
||||
|
||||
|
||||
vm.iconPickerDialog.close = function(oldModel) {
|
||||
|
||||
vm.iconPickerDialog.show = false;
|
||||
vm.iconPickerDialog = null;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
activate();
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.PrevalueEditors.ListViewLayoutsPreValsController", ListViewLayoutsPreValsController);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,49 @@
|
||||
<div ng-controller="Umbraco.PrevalueEditors.ListViewLayoutsPreValsController as vm">
|
||||
|
||||
<div class="list-view-layouts" ui-sortable="vm.layoutsSortableOptions" ng-model="model.value">
|
||||
|
||||
<div class="list-view-layout" ng-repeat="layout in model.value">
|
||||
|
||||
<i class="icon-navigation list-view-layout__sort-handle"></i>
|
||||
|
||||
<div>
|
||||
|
||||
<a ng-if="layout.isSystem !== 1" href="" ng-click="vm.openIconPicker(layout)" class="list-view-layout__icon" umb-auto-focus>
|
||||
<i class="{{ layout.icon }}"></i>
|
||||
</a>
|
||||
|
||||
<div ng-if="layout.isSystem === 1" class="list-view-layout__icon">
|
||||
<i class="{{ layout.icon }}"></i>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="list-view-layout__name">
|
||||
<input ng-if="layout.isSystem !== 1" ng-model="layout.name" placeholder="Name..." class="-full-width-input" focus-when="{{ vm.focusLayoutName }}" />
|
||||
<span ng-if="layout.isSystem === 1" class="list-view-layout__name-text">{{ layout.name }}</span>
|
||||
<span ng-if="layout.isSystem === 1" class="list-view-layout__system">(system layout)</span>
|
||||
</div>
|
||||
|
||||
<div class="list-view-layout__path">
|
||||
<input ng-if="layout.isSystem !== 1" ng-model="layout.path" placeholder="Layout path..." class="-full-width-input" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input ng-if="layout.isSystem === 1" type="checkbox" ng-model="layout.selected" />
|
||||
<umb-confirm-delete ng-if="layout.isSystem !== 1" confirm-action="vm.removeLayout($index, layout)"></umbraco-confirm-delete>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<a href="" class="list-view-add-layout" ng-click="vm.addLayout()">Add layout</a>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="vm.iconPickerDialog.show"
|
||||
model="vm.iconPickerDialog"
|
||||
view="vm.iconPickerDialog.view"
|
||||
position="right">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
<div ng-controller="Umbraco.PropertyEditors.ListView.GridLayoutController as vm">
|
||||
|
||||
<div
|
||||
ng-if="entityType === 'media'"
|
||||
on-drag-leave="vm.dragLeave()"
|
||||
on-drag-end="vm.dragLeave()"
|
||||
on-drag-enter="vm.dragEnter()">
|
||||
|
||||
<umb-file-dropzone
|
||||
parent-id="{{vm.nodeId}}"
|
||||
files-uploaded="vm.onUploadComplete"
|
||||
accept="{{vm.acceptedFileTypes}}"
|
||||
hide-dropzone="{{!vm.activeDrag && listViewResultSet.items.length > 0 }}"
|
||||
compact="{{ listViewResultSet.items.length > 0 }}"
|
||||
files-queued="vm.onFilesQueue">
|
||||
</umb-file-dropzone>
|
||||
|
||||
<umb-media-grid
|
||||
items="listViewResultSet.items">
|
||||
</umb-media-grid>
|
||||
|
||||
<div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.Editors.DocumentType.EditController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for the content type editor
|
||||
*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function ListViewGridLayoutController($scope, $routeParams, mediaHelper) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.nodeId = $routeParams.id;
|
||||
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
|
||||
vm.activeDrag = false;
|
||||
|
||||
vm.dragEnter = dragEnter;
|
||||
vm.dragLeave = dragLeave;
|
||||
vm.onFilesQueue = onFilesQueue;
|
||||
vm.onUploadComplete = onUploadComplete;
|
||||
|
||||
function dragEnter(el, event) {
|
||||
vm.activeDrag = true;
|
||||
}
|
||||
|
||||
function dragLeave(el, event) {
|
||||
vm.activeDrag = false;
|
||||
}
|
||||
|
||||
function onFilesQueue() {
|
||||
vm.activeDrag = false;
|
||||
}
|
||||
|
||||
function onUploadComplete() {
|
||||
|
||||
// call reload function on list view parent controller
|
||||
$scope.reloadView($scope.contentId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.GridLayoutController", ListViewGridLayoutController);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,51 @@
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="width: 35px">
|
||||
<input type="checkbox" ng-click="selectAll($event)" ng-checked="isSelectedAll()">
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" ng-click="sort('Name', true)" prevent-default class="sortable">
|
||||
<localize key="general_name">Name</localize>
|
||||
<i class="icon" ng-class="{'icon-navigation-up': isSortDirection('Name', 'asc'), 'icon-navigation-down': isSortDirection('Name', 'desc')}"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td ng-repeat="column in options.includeProperties">
|
||||
<a href="#" ng-click="sort(column.alias, column.allowSorting)" ng-class="{'sortable':column.allowSorting}" prevent-default>
|
||||
<span ng-bind="column.header"></span>
|
||||
<i class="icon" ng-class="{'icon-navigation-up': isSortDirection(column.alias, 'asc'), 'icon-navigation-down': isSortDirection(column.alias, 'desc')}"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody ng-show="listViewResultSet.totalItems === 0">
|
||||
<tr>
|
||||
<td colspan="{{options.includeProperties.length + 2}}">
|
||||
<p><localize key="content_listViewNoItems">There are no items show in the list.</localize></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-show="listViewResultSet.totalItems > 0">
|
||||
<tr ng-repeat="result in listViewResultSet.items"
|
||||
ng-class="{selected:result.selected}">
|
||||
|
||||
<td>
|
||||
<i class="icon {{result.icon}}" ng-class="getIcon(result)"></i>
|
||||
<input type="checkbox" ng-model="result.selected" no-dirty-check>
|
||||
</td>
|
||||
<td>
|
||||
<a ng-class="{inactive: (entityType === 'content' && !result.published) || isTrashed}"
|
||||
href="#{{result.editPath}}"
|
||||
ng-bind="result.name"></a>
|
||||
</td>
|
||||
|
||||
<td ng-repeat="column in options.includeProperties">
|
||||
<span>{{result[column.alias]}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
@@ -51,6 +51,8 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific
|
||||
$scope.pagination = [];
|
||||
$scope.isNew = false;
|
||||
$scope.actionInProgress = false;
|
||||
$scope.layout = {};
|
||||
$scope.layout.activeLayout = {};
|
||||
$scope.listViewResultSet = {
|
||||
totalPages: 0,
|
||||
items: []
|
||||
@@ -71,6 +73,9 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific
|
||||
allowBulkDelete: true,
|
||||
};
|
||||
|
||||
// set active layout
|
||||
$scope.layout.activeLayout = getFirstAllowedLayout($scope.model.config.layouts);
|
||||
|
||||
//update all of the system includeProperties to enable sorting
|
||||
_.each($scope.options.includeProperties, function(e, i) {
|
||||
|
||||
@@ -91,6 +96,24 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific
|
||||
}
|
||||
});
|
||||
|
||||
function getFirstAllowedLayout(layouts) {
|
||||
|
||||
var firstAllowedLayout = {};
|
||||
|
||||
for (var i = 0; layouts.length > i; i++) {
|
||||
|
||||
var layout = layouts[i];
|
||||
|
||||
if (layout.selected === true) {
|
||||
firstAllowedLayout = layout;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return firstAllowedLayout;
|
||||
}
|
||||
|
||||
function showNotificationsAndReset(err, reload, successMsg) {
|
||||
|
||||
//check if response is ysod
|
||||
|
||||
@@ -5,37 +5,56 @@
|
||||
</div>
|
||||
|
||||
<div class="row-fluid" ng-switch-when="false">
|
||||
<div class="umb-sub-header">
|
||||
|
||||
<div class="btn-group" ng-show="listViewAllowedTypes && listViewAllowedTypes.length > 0">
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<localize key="actions_create">Create</localize>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="contentType in listViewAllowedTypes">
|
||||
<a href="#/{{entityType}}/{{entityType}}/edit/{{contentId}}?doctype={{contentType.alias}}&create=true">
|
||||
<i class="icon-{{contentType.cssClass}}"></i>
|
||||
{{contentType.name}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="umb-sub-header clearfix">
|
||||
<div class="pull-left">
|
||||
<div class="btn-group" ng-show="listViewAllowedTypes && listViewAllowedTypes.length > 0">
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<localize key="actions_create">Create</localize>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="contentType in listViewAllowedTypes">
|
||||
<a href="#/{{entityType}}/{{entityType}}/edit/{{contentId}}?doctype={{contentType.alias}}&create=true">
|
||||
<i class="icon-{{contentType.cssClass}}"></i>
|
||||
{{contentType.name}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" ng-show="isAnythingSelected()" ng-if="entityType === 'content' && !isTrashed && options.allowBulkPublish">
|
||||
<a class="btn btn-success" ng-disabled="actionInProgress" ng-click="publish()" prevent-default>
|
||||
<localize key="actions_publish">Publish</localize>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group" ng-show="isAnythingSelected()" ng-if="entityType === 'content' && !isTrashed && options.allowBulkUnpublish">
|
||||
<a class="btn btn-warning" ng-disabled="actionInProgress" ng-click="unpublish()" prevent-default>
|
||||
<localize key="actions_unpublish">Unpublish</localize>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group" ng-show="isAnythingSelected()" ng-if="options.allowBulkDelete">
|
||||
<a class="btn btn-danger" ng-disabled="actionInProgress" ng-click="delete()" prevent-default>
|
||||
<localize key="actions_delete">Delete</localize>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" ng-show="isAnythingSelected()" ng-if="entityType === 'content' && !isTrashed && options.allowBulkPublish">
|
||||
<a class="btn btn-success" ng-disabled="actionInProgress" ng-click="publish()" prevent-default>
|
||||
<localize key="actions_publish">Publish</localize>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group" ng-show="isAnythingSelected()" ng-if="entityType === 'content' && !isTrashed && options.allowBulkUnpublish">
|
||||
<a class="btn btn-warning" ng-disabled="actionInProgress" ng-click="unpublish()" prevent-default>
|
||||
<localize key="actions_unpublish">Unpublish</localize>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group" ng-show="isAnythingSelected()" ng-if="options.allowBulkDelete">
|
||||
<a class="btn btn-danger" ng-disabled="actionInProgress" ng-click="delete()" prevent-default>
|
||||
<localize key="actions_delete">Delete</localize>
|
||||
</a>
|
||||
<div class="pull-right">
|
||||
|
||||
<form class="form-search pull-right" novalidate ng-show="!actionInProgress">
|
||||
<div class="inner-addon left-addon">
|
||||
<i class="icon icon-search" ng-click="enterSearch($event)"></i>
|
||||
<input type="text" class="form-control" localize="placeholder" placeholder="@general_typeToSearch" ng-model="options.filter" prevent-enter-submit no-dirty-check>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<umb-layout-selector
|
||||
ng-if="model.config.layouts"
|
||||
layouts="model.config.layouts"
|
||||
active-layout="layout.activeLayout">
|
||||
</umb-layout-selector>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-loader-wrapper" ng-show="actionInProgress">
|
||||
@@ -44,96 +63,36 @@
|
||||
|
||||
<span ng-bind="bulkStatus" ng-show="isAnythingSelected()" class="pull-right"></span>
|
||||
|
||||
<form class="form-search pull-right" novalidate ng-show="!actionInProgress">
|
||||
<div class="inner-addon left-addon">
|
||||
<i class="icon icon-search" ng-click="enterSearch($event)"></i>
|
||||
<input type="text" class="form-control" localize="placeholder" placeholder="@general_typeToSearch" ng-model="options.filter" prevent-enter-submit no-dirty-check>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="width: 35px">
|
||||
<input type="checkbox" ng-click="selectAll($event)" ng-checked="isSelectedAll()">
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" ng-click="sort('Name', true)" prevent-default class="sortable">
|
||||
<localize key="general_name">Name</localize>
|
||||
<i class="icon" ng-class="{'icon-navigation-up': isSortDirection('Name', 'asc'), 'icon-navigation-down': isSortDirection('Name', 'desc')}"></i>
|
||||
</a>
|
||||
</td>
|
||||
<div ng-include="layout.activeLayout.path"></div>
|
||||
|
||||
<td ng-repeat="column in options.includeProperties">
|
||||
<a href="#" ng-click="sort(column.alias, column.allowSorting)" ng-class="{'sortable':column.allowSorting}" prevent-default>
|
||||
<span ng-bind="column.header"></span>
|
||||
<i class="icon" ng-class="{'icon-navigation-up': isSortDirection(column.alias, 'asc'), 'icon-navigation-down': isSortDirection(column.alias, 'desc')}"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<div class="pagination" ng-show="pagination.length > 1">
|
||||
|
||||
<tbody ng-show="listViewResultSet.totalItems === 0">
|
||||
<tr>
|
||||
<td colspan="{{options.includeProperties.length + 2}}">
|
||||
<p><localize key="content_listViewNoItems">There are no items show in the list.</localize></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<ul>
|
||||
<li ng-class="{disabled:options.pageNumber <= 1}">
|
||||
<a href="#" ng-click="prev()" prevent-default>
|
||||
<localize key="general_previous">Previous</localize>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<tbody ng-show="listViewResultSet.totalItems > 0">
|
||||
<tr ng-repeat="result in listViewResultSet.items"
|
||||
ng-class="{selected:result.selected}">
|
||||
<li ng-repeat="pgn in pagination"
|
||||
ng-class="{active:pgn.isActive}">
|
||||
|
||||
<td>
|
||||
<i class="icon {{result.icon}}" ng-class="getIcon(result)"></i>
|
||||
<input type="checkbox" ng-model="result.selected" no-dirty-check>
|
||||
</td>
|
||||
<td>
|
||||
<a ng-class="{inactive: (entityType === 'content' && !result.published) || isTrashed}"
|
||||
href="#{{result.editPath}}"
|
||||
ng-bind="result.name"></a>
|
||||
</td>
|
||||
<a href="#" ng-click="goToPage(pgn.val - 1)" prevent-default
|
||||
ng-bind="pgn.name ? pgn.name : pgn.val"
|
||||
ng-if="pgn.val != '...'"></a>
|
||||
<span ng-bind="pgn.val" ng-if="pgn.val == '...'"></span>
|
||||
</li>
|
||||
|
||||
<td ng-repeat="column in options.includeProperties">
|
||||
<span>{{result[column.alias]}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<li ng-class="{disabled:options.pageNumber >= listViewResultSet.totalPages}">
|
||||
<a href="#" ng-click="next()" prevent-default>
|
||||
<localize key="general_next">Next</localize>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<tfoot ng-show="pagination.length > 1">
|
||||
<tr>
|
||||
<th colspan="{{options.includeProperties.length + 2}}">
|
||||
<div class="pull-left">
|
||||
</div>
|
||||
<div class="pagination pagination-right">
|
||||
<ul>
|
||||
<li ng-class="{disabled:options.pageNumber <= 1}">
|
||||
<a href="#" ng-click="prev()" prevent-default>
|
||||
<localize key="general_previous">Previous</localize>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
|
||||
<li ng-repeat="pgn in pagination"
|
||||
ng-class="{active:pgn.isActive}">
|
||||
|
||||
<a href="#" ng-click="goToPage(pgn.val - 1)" prevent-default
|
||||
ng-bind="pgn.name ? pgn.name : pgn.val"
|
||||
ng-if="pgn.val != '...'"></a>
|
||||
<span ng-bind="pgn.val" ng-if="pgn.val == '...'"></span>
|
||||
</li>
|
||||
|
||||
<li ng-class="{disabled:options.pageNumber >= listViewResultSet.totalPages}">
|
||||
<a href="#" ng-click="next()" prevent-default>
|
||||
<localize key="general_next">Next</localize>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user