Compare commits

...

26 Commits

Author SHA1 Message Date
per ploug 306a30265e Remove ace from bower and directives folder 2014-11-10 13:36:57 +01:00
per ploug 1ee6fc8514 Update build.bat to beta2 2014-11-10 13:33:42 +01:00
Rune Hem Strand 1003ac42df Grid template preview
New template preview for content section
2014-11-10 12:17:39 +01:00
Per Ploug Krogslund db4495cf50 Grid mock data and modified tests
all client side changes, will not affect live sites
2014-11-07 11:13:28 +01:00
per ploug ed8cccdf5a Minor visual annoyances + changed output html
changes made due to feedback from Adam, Rune and Simon on how to make
the grid as flexible as possible
2014-11-06 22:58:35 +01:00
per ploug 9cd8ce5626 Grid layout changes to support breaking rows 2014-11-06 14:13:27 +01:00
per ploug 990f271c63 Merge 2014-11-05 20:10:06 +01:00
per ploug adfdbaec46 Adds support for grid row configuration and styling 2014-11-05 15:44:29 +01:00
Stephan 0f4436a465 U4-5728 - Do not run KeepAlive, ScheduledPublishing, without an url 2014-11-03 20:20:10 +01:00
Sebastiaan Janssen 8ccbf70b39 Making sure lower-case "Change password" is also removed 2014-11-03 18:05:12 +01:00
antoine ddd26f3ad4 Move/remove row button hover wasn't correct, point on control's methods instead of row's 2014-11-03 14:04:59 +01:00
Sebastiaan Janssen 316e7531a0 #U4-5738 Fixed Due in version 7.2.0
Umbraco 7.2 installation via NuGet fails
2014-11-03 13:13:23 +01:00
Shannon Deminick 0f068f5fb1 Merge pull request #524 from Odie20XX/patch-1
Update MembershipHelper.cs
2014-11-01 05:53:52 +10:00
antoine 8f6b76f9fc U4-5730 7.2.0 Grid - edit parameters of macro added into grid content 2014-10-31 16:29:22 +01:00
Odie20XX 468c281d7d Update MembershipHelper.cs
The parameter "logMemberIn" wasn't used so setting "LoginOnSuccess" on the RegisterModel didn't have any effect. By checking the parameter you can disable automatically logging in the user after registration. If registration failed, it would have returned null in an earlier stage so it's safe to say registration succeeded at this point.
2014-10-31 15:30:20 +01:00
Antoine Giraud f7cb188210 Merge pull request #522 from arknu/U4-5638-grid-prevalue-editor
U4-5638: Replace style with ng-style to ensure styling is applied in IE
2014-10-31 12:55:18 +01:00
antoine 00518d0de7 Add the startNodeId option for the grid media editor 2014-10-31 09:59:13 +01:00
Sebastiaan Janssen 892a8d2a8a Update gruntFile.js 2014-10-30 10:12:43 +01:00
arknu ced6c011aa U4-5638: Also replace style with ng-style in the property editor 2014-10-29 15:25:59 +01:00
arknu efc2008783 U4-5638: Replace style with ng-style to ensure styling is applied in IE 2014-10-29 12:58:38 +01:00
Shannon acb987a451 Merge branch '7.2.0' of https://github.com/umbraco/Umbraco-CMS into 7.2.0 2014-10-29 18:20:10 +10:00
Shannon 4a1ea6e2d8 Fixes: U4-5710 UmbracoVirtualNodeRouteHandler does not allow for SurfaceController forms 2014-10-29 18:20:01 +10:00
Antoine Giraud cc23d57803 Merge pull request #521 from enricleon/7.2.0
Add new colorpicker directive to the canvasdesigner to improve reusability into the canvasdesigner editors
2014-10-29 09:18:32 +01:00
Enric León 81fdae3dc4 Change spectrumpicker to colorpicker in all editors 2014-10-28 16:27:04 +01:00
Enric León 2859eb560c Add new directive colorpicker that wraps spectrumpicker into a dialog 2014-10-28 16:27:03 +01:00
Sebastiaan Janssen 7c5ad67a9f Update to config transform adding a <remove /> too late and assembly bindings not transforming correctly 2014-10-28 14:41:52 +01:00
54 changed files with 1438 additions and 734 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ IF NOT EXIST UmbracoVersion.txt (
GOTO :showerror
)
SET /p release=<UmbracoVersion.txt
SET comment=beta
SET comment=beta2
SET version=%release%
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
@@ -53,6 +53,7 @@
views/dashboard/default/startupdashboardintro.html
</control>
</tab>
<tab caption="Change password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Change Password" xdt:Transform="Insert">
<control showOnce="false" addPanel="false" panelCaption="">
+19 -19
View File
@@ -52,8 +52,6 @@
<compilation>
<assemblies xdt:Transform="InsertIfMissing" />
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
<add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)"
xdt:Transform="InsertIfMissing" />
<add assembly="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
@@ -71,6 +69,13 @@
</assemblies>
</compilation>
<compilation>
<assemblies>
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
</assemblies>
</compilation>
<xhtmlConformance xdt:Transform="Remove" />
<httpModules xdt:Transform="InsertIfMissing" />
@@ -126,36 +131,31 @@
<runtime xdt:Transform="InsertIfMissing" />
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" xdt:Transform="SetAttributes()">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="InsertIfMissing">
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="InsertIfMissing">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="InsertIfMissing">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.1" />
</dependentAssembly>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" xdt:Transform="InsertIfMissing" />
</runtime>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Remove" />
</assemblyBinding>
</runtime>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Replace">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Replace">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Replace">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.1" />
</dependentAssembly>
</dependentAssembly>
</assemblyBinding>
</runtime>
+4 -8
View File
@@ -63,8 +63,7 @@ if ($project) {
$consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow])
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
$prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1
if ($prop -eq $null) { return }
@@ -91,10 +90,8 @@ if ($project) {
# get reference to the window, then smart output console provider
# copy web.config if messages in buffered console contains "installing...UmbracoCms" in last operation
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor `
[System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
if ($instanceField -eq $null -or $consoleField -eq $null) { return }
$instance = $instanceField.GetValue($null)
@@ -105,8 +102,7 @@ if ($project) {
$console = $consoleProvider.CreateOutputConsole($false)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic)
if ($messagesField -eq $null) { return }
$messages = $messagesField.GetValue($console)
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return "beta"; } }
public static string CurrentComment { get { return "beta2"; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
@@ -17,37 +17,30 @@ namespace Umbraco.Core.Sync
/// status. This will attempt to determine the internal umbraco base url that can be used by the current
/// server to send a request to itself if it is in a load balanced environment.
/// </summary>
/// <returns>The full base url including schema (i.e. http://myserver:80/umbraco )</returns>
/// <returns>The full base url including schema (i.e. http://myserver:80/umbraco ) - or <c>null</c> if the url
/// cannot be determined at the moment (usually because the first request has not properly completed yet).</returns>
public static string GetCurrentServerUmbracoBaseUrl()
{
var status = GetStatus();
if (status == CurrentServerEnvironmentStatus.Single)
{
//if it's a single install, then the base url has to be the first url registered. Use HTTP or HTTPS as appropriate.
if (GlobalSettings.UseSSL)
{
return string.Format("https://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
else
{
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
// single install, return null if no original url, else use original url as base
// use http or https as appropriate
return string.IsNullOrWhiteSpace(ApplicationContext.Current.OriginalRequestUrl)
? null // not initialized yet
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", ApplicationContext.Current.OriginalRequestUrl);
}
var servers = UmbracoConfig.For.UmbracoSettings().DistributedCall.Servers.ToArray();
if (servers.Any() == false)
{
//cannot be determined, then the base url has to be the first url registered. Use HTTP or HTTPS as appropriate.
if (GlobalSettings.UseSSL)
{
return string.Format("https://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
else
{
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
// cannot be determined, return null if no original url, else use original url as base
// use http or https as appropriate
return string.IsNullOrWhiteSpace(ApplicationContext.Current.OriginalRequestUrl)
? null // not initialized yet
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", ApplicationContext.Current.OriginalRequestUrl);
}
foreach (var server in servers)
@@ -72,15 +65,11 @@ namespace Umbraco.Core.Sync
}
}
//cannot be determined, then the base url has to be the first url registered. Use HTTP or HTTPS as appropriate.
if (GlobalSettings.UseSSL)
{
return string.Format("https://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
else
{
return string.Format("http://{0}", ApplicationContext.Current.OriginalRequestUrl);
}
// cannot be determined, return null if no original url, else use original url as base
// use http or https as appropriate
return string.IsNullOrWhiteSpace(ApplicationContext.Current.OriginalRequestUrl)
? null // not initialized yet
: string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", ApplicationContext.Current.OriginalRequestUrl);
}
/// <summary>
-1
View File
@@ -17,7 +17,6 @@
],
"dependencies": {
"typeahead.js": "~0.10.5",
"ace-builds": "~1.1.3",
"rgrove-lazyload": "*"
}
}
+10 -6
View File
@@ -18,8 +18,9 @@ module.exports = function (grunt) {
//triggered from grunt dev or grunt
grunt.registerTask('build', ['clean', 'concat', 'recess:min', 'recess:installer', 'recess:canvasdesigner', 'bower', 'copy']);
//build-dev doesn't min - we are trying to speed this up and we don't want minified stuff when we are in dev mode
grunt.registerTask('build-dev', ['clean', 'concat', 'recess:build', 'recess:installer', 'copy']);
//build-dev doesn't min - we are trying to speed this up and we don't want minified stuff when we are in dev mode
grunt.registerTask('build-dev', ['clean', 'concat', 'recess:build', 'recess:installer', 'copy']);
//utillity tasks
grunt.registerTask('docs', ['ngdocs']);
@@ -31,9 +32,9 @@ module.exports = function (grunt) {
grunt.log.subhead(Date());
});
// Custom task to run the bower dependency installer
// tried, a few other things but this seems to work the best.
// https://coderwall.com/p/xnkdqw
// Custom task to run the bower dependency installer
// tried, a few other things but this seems to work the best.
// https://coderwall.com/p/xnkdqw
grunt.registerTask('bower', 'Get js packages listed in bower.json',
function () {
var bower = require('bower');
@@ -108,7 +109,7 @@ module.exports = function (grunt) {
vsdir: '../Umbraco.Web.UI/umbraco',
pkg: grunt.file.readJSON('package.json'),
banner:
'/*! <%= pkg.title || pkg.name %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
'/*! <%= pkg.title || pkg.name %>\n' +
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
@@ -137,6 +138,9 @@ module.exports = function (grunt) {
files: [{ dest: '<%= distdir %>/assets', src : '**', expand: true, cwd: 'src/assets/' }]
},
config: {
files: [{ dest: '<%= distdir %>/../config', src : '**', expand: true, cwd: 'src/config/' }]
},
// Copies over the files downloaded by bower
bower: {
@@ -3,7 +3,7 @@
/* Canvasdesigner panel app and controller */
/*********************************************************************************************************/
var app = angular.module("Umbraco.canvasdesigner", ['spectrumcolorpicker', 'ui.slider', 'umbraco.resources', 'umbraco.services'])
var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider', 'umbraco.resources', 'umbraco.services'])
.controller("Umbraco.canvasdesignerController", function ($scope, $http, $window, $timeout, $location, dialogService) {
@@ -2,8 +2,8 @@
<div ng-controller="Umbraco.canvasdesigner.background">
<div class="box-slider">
<spectrum colorselected="item.values.color"></spectrum>
</div>
<div colorpicker ng-model="item.values.color"></div>
</div>
<div class="box-slider">
<div class="imagePickerPreview" ng-click="open(item.values)" style="background-image:{{ item.values.imageorpattern }}">
@@ -10,7 +10,7 @@ angular.module("Umbraco.canvasdesigner")
if (!$scope.item.values) {
$scope.item.values = {
imageorpattern: '',
color:''
color: ''
};
}
@@ -4,12 +4,11 @@
<div class="box-slider">
<ul class="box-preview">
<li ng-repeat="border in borderList" class="border-{{border}}" ng-class="{selected: selectedBorder.name == border}" ng-click="setselectedBorder(border)"></li>
</ul>
</div>
<div class="box-slider">
<spectrum colorselected="selectedBorder.color"></spectrum>
<div class="box-slider" ng-repeat="border in borderList" ng-show="selectedBorder.name == border">
<div colorpicker ng-model="item.values[(border !== 'all' ? border : '') + 'bordercolor']"></div>
<select class="borderStyleSelect" ng-model="selectedBorder.type" ng-options="bordertype for bordertype in bordertypes"></select>
<!--<i ng-if="selectedBorder.color != ''" ng-click="selectedBorder.color= ''" class="icon icon-delete colorPickerDelete"></i>-->
</div>
@@ -92,35 +92,30 @@ angular.module("Umbraco.canvasdesigner")
$scope.setselectedBorder($scope.borderList[0]);
}, false);
$scope.$watch( "selectedBorder", function () {
$scope.$watch("selectedBorder", function () {
if ($scope.selectedBorder.name == "all") {
$scope.item.values.bordersize = $scope.selectedBorder.size;
$scope.item.values.bordercolor = $scope.selectedBorder.color;
$scope.item.values.bordertype =$scope.selectedBorder.type;
$scope.item.values.bordertype = $scope.selectedBorder.type;
}
if ($scope.selectedBorder.name == "left") {
$scope.item.values.leftbordersize = $scope.selectedBorder.size;
$scope.item.values.leftbordercolor = $scope.selectedBorder.color;
$scope.item.values.leftbordertype = $scope.selectedBorder.type;
}
if ($scope.selectedBorder.name == "right") {
$scope.item.values.rightbordersize = $scope.selectedBorder.size;
$scope.item.values.rightbordercolor = $scope.selectedBorder.color;
$scope.item.values.rightbordertype = $scope.selectedBorder.type;
}
if ($scope.selectedBorder.name == "top") {
$scope.item.values.topbordersize = $scope.selectedBorder.size;
$scope.item.values.topbordercolor = $scope.selectedBorder.color;
$scope.item.values.topbordertype = $scope.selectedBorder.type;
}
if ($scope.selectedBorder.name == "bottom") {
$scope.item.values.bottombordersize = $scope.selectedBorder.size;
$scope.item.values.bottombordercolor = $scope.selectedBorder.color;
$scope.item.values.bottombordertype = $scope.selectedBorder.type;
}
@@ -1,8 +1,3 @@
<div ng-controller="Umbraco.canvasdesigner.color">
<div class="box-slider">
<spectrum colorselected="item.values.color"></spectrum>
</div>
<div class="box-slider">
<div colorpicker ng-model="item.values.color"></div>
</div>
@@ -9,7 +9,7 @@ angular.module("Umbraco.canvasdesigner")
if (!$scope.item.values) {
$scope.item.values = {
color: '',
color: ''
};
}
@@ -0,0 +1,69 @@
/*********************************************************************************************************/
/* spectrum color picker directive */
/*********************************************************************************************************/
angular.module('colorpicker', ['spectrumcolorpicker'])
.directive('colorpicker', ['dialogService', function (dialogService) {
return {
restrict: 'EA',
scope: {
ngModel: '='
},
link: function (scope, $element) {
scope.openColorDialog = function () {
var config = {
template: "colorModal.html",
change: function (data) {
scope.ngModel = data;
},
callback: function (data) {
scope.ngModel = data;
},
cancel: function (data) {
scope.ngModel = data;
},
dialogItem: scope.ngModel,
scope: scope
};
dialogService.open(config);
}
scope.setColor = false;
scope.submitAndClose = function () {
if (scope.ngModel != "") {
scope.setColor = true;
scope.submit(scope.ngModel);
} else {
scope.cancel();
}
};
scope.cancelAndClose = function () {
scope.cancel();
}
},
template:
'<div>' +
'<div class="color-picker-preview" ng-click="openColorDialog()" style="background: {{ngModel}} !important;"></div>' +
'<script type="text/ng-template" id="colorModal.html">' +
'<div class="modal-header">' +
'<h1>Header</h1>' +
'</div>' +
'<div class="modal-body">' +
'<spectrum colorselected="ngModel" set-color="setColor" flat="true" show-palette="true"></spectrum>' +
'</div>' +
'<div class="right">' +
'<a class="btn" href="#" ng-click="cancelAndClose()">Cancel</a>' +
'<a class="btn btn-success" href="#" ng-click="submitAndClose()">Done</a>' +
'</div>' +
'</script>' +
'</div>',
replace: true
};
}])
@@ -5,12 +5,14 @@
angular.module("Umbraco.canvasdesigner").factory('dialogService', function ($rootScope, $q, $http, $timeout, $compile, $templateCache) {
function closeDialog(dialog) {
function closeDialog(dialog, destroyScope) {
if (dialog.element) {
dialog.element.removeClass("selected");
dialog.element.html("");
dialog.scope.$destroy();
if (destroyScope) {
dialog.scope.$destroy();
}
}
}
@@ -32,7 +34,11 @@ angular.module("Umbraco.canvasdesigner").factory('dialogService', function ($roo
};
var dialog = angular.extend(defaults, options);
var destroyScope = true;
if (options && options.scope) {
destroyScope = false;
}
var scope = (options && options.scope) || $rootScope.$new();
// Save original value for cancel action
@@ -42,10 +48,11 @@ angular.module("Umbraco.canvasdesigner").factory('dialogService', function ($roo
/************************************/
// Close dialog if the user clicks outside the dialog. (Not working well with colorpickers and datepickers)
$(document).mousedown(function (e) {
var container = dialog.element;
if (!container.is(e.target) && container.has(e.target).length === 0) {
closeDialog(dialog);
closeDialog(dialog, destroyScope);
}
});
/************************************/
@@ -66,7 +73,7 @@ angular.module("Umbraco.canvasdesigner").factory('dialogService', function ($roo
if (dialog.cancel) {
dialog.cancel(originalDialogItem);
}
closeDialog(dialog);
closeDialog(dialog, destroyScope);
}
scope.change = function (data) {
@@ -79,11 +86,11 @@ angular.module("Umbraco.canvasdesigner").factory('dialogService', function ($roo
if (dialog.callback) {
dialog.callback(data);
}
closeDialog(dialog);
closeDialog(dialog, destroyScope);
};
scope.close = function () {
closeDialog(dialog);
closeDialog(dialog, destroyScope);
}
scope.dialogData = dialog.dialogData;
@@ -9,7 +9,10 @@ angular.module('spectrumcolorpicker', [])
restrict: 'E',
transclude: true,
scope: {
colorselected: '='
colorselected: '=',
setColor: '=',
flat: '=',
showPalette: '='
},
link: function (scope, $element) {
@@ -18,9 +21,13 @@ angular.module('spectrumcolorpicker', [])
$element.find("input").spectrum({
color: scope.colorselected,
allowEmpty: true,
preferredFormat: "rgb",
preferredFormat: "hex",
showAlpha: true,
showInput: true,
flat: scope.flat,
localStorageKey: "spectrum.panel",
showPalette: scope.showPalette,
palette: [],
change: function (color) {
if (color) {
@@ -45,8 +52,10 @@ angular.module('spectrumcolorpicker', [])
});
scope.$watch('colorselected', function () {
$element.find("input").spectrum("set", scope.colorselected);
scope.$watch('setcolor', function (setColor) {
if (scope.$eval(setColor) === true) {
$element.find("input").spectrum("set", scope.colorselected);
}
}, true);
},
@@ -1,269 +0,0 @@
angular.module('umbraco')
.constant('uiAceConfig', {})
.directive('uiAce', ['uiAceConfig', function (uiAceConfig) {
if (angular.isUndefined(window.ace)) {
throw new Error('ui-ace need ace to work... (o rly?)');
}
/**
* Sets editor options such as the wrapping mode or the syntax checker.
*
* The supported options are:
*
* <ul>
* <li>showGutter</li>
* <li>useWrapMode</li>
* <li>onLoad</li>
* <li>theme</li>
* <li>mode</li>
* </ul>
*
* @param acee
* @param session ACE editor session
* @param {object} opts Options to be set
*/
var setOptions = function(acee, session, opts) {
// Boolean options
if (angular.isDefined(opts.showGutter)) {
acee.renderer.setShowGutter(opts.showGutter);
}
if (angular.isDefined(opts.useWrapMode)) {
session.setUseWrapMode(opts.useWrapMode);
}
if (angular.isDefined(opts.showInvisibles)) {
acee.renderer.setShowInvisibles(opts.showInvisibles);
}
if (angular.isDefined(opts.showIndentGuides)) {
acee.renderer.setDisplayIndentGuides(opts.showIndentGuides);
}
if (angular.isDefined(opts.useSoftTabs)) {
session.setUseSoftTabs(opts.useSoftTabs);
}
// commands
if (angular.isDefined(opts.disableSearch) && opts.disableSearch) {
acee.commands.addCommands([
{
name: 'unfind',
bindKey: {
win: 'Ctrl-F',
mac: 'Command-F'
},
exec: function () {
return false;
},
readOnly: true
}
]);
}
// onLoad callback
if (angular.isFunction(opts.onLoad)) {
opts.onLoad(acee);
}
// Basic options
if (angular.isString(opts.theme)) {
acee.setTheme('ace/theme/' + opts.theme);
}
if (angular.isString(opts.mode)) {
session.setMode('ace/mode/' + opts.mode);
}
};
return {
restrict: 'EA',
require: '?ngModel',
link: function (scope, elm, attrs, ngModel) {
/**
* Corresponds the uiAceConfig ACE configuration.
* @type object
*/
var options = uiAceConfig.ace || {};
/**
* uiAceConfig merged with user options via json in attribute or data binding
* @type object
*/
var opts = angular.extend({}, options, scope.$eval(attrs.uiAce));
/**
* ACE editor
* @type object
*/
var acee = window.ace.edit(elm[0]);
/**
* ACE editor session.
* @type object
* @see [EditSession]{@link http://ace.c9.io/#nav=api&api=edit_session}
*/
var session = acee.getSession();
/**
* Reference to a change listener created by the listener factory.
* @function
* @see listenerFactory.onChange
*/
var onChangeListener;
/**
* Reference to a blur listener created by the listener factory.
* @function
* @see listenerFactory.onBlur
*/
var onBlurListener;
/**
* Calls a callback by checking its existing. The argument list
* is variable and thus this function is relying on the arguments
* object.
* @throws {Error} If the callback isn't a function
*/
var executeUserCallback = function () {
/**
* The callback function grabbed from the array-like arguments
* object. The first argument should always be the callback.
*
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
* @type {*}
*/
var callback = arguments[0];
/**
* Arguments to be passed to the callback. These are taken
* from the array-like arguments object. The first argument
* is stripped because that should be the callback function.
*
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
* @type {Array}
*/
var args = Array.prototype.slice.call(arguments, 1);
if (angular.isDefined(callback)) {
scope.$apply(function () {
if (angular.isFunction(callback)) {
callback(args);
} else {
throw new Error('ui-ace use a function as callback.');
}
});
}
};
/**
* Listener factory. Until now only change listeners can be created.
* @type object
*/
var listenerFactory = {
/**
* Creates a change listener which propagates the change event
* and the editor session to the callback from the user option
* onChange. It might be exchanged during runtime, if this
* happens the old listener will be unbound.
*
* @param callback callback function defined in the user options
* @see onChangeListener
*/
onChange: function (callback) {
return function (e) {
var newValue = session.getValue();
if (newValue !== scope.$eval(attrs.value) && !scope.$$phase && !scope.$root.$$phase) {
if (angular.isDefined(ngModel)) {
scope.$apply(function () {
ngModel.$setViewValue(newValue);
});
}
executeUserCallback(callback, e, acee);
}
};
},
/**
* Creates a blur listener which propagates the editor session
* to the callback from the user option onBlur. It might be
* exchanged during runtime, if this happens the old listener
* will be unbound.
*
* @param callback callback function defined in the user options
* @see onBlurListener
*/
onBlur: function (callback) {
return function () {
executeUserCallback(callback, acee);
};
}
};
attrs.$observe('readonly', function (value) {
acee.setReadOnly(value === 'true');
});
// Value Blind
if (angular.isDefined(ngModel)) {
ngModel.$formatters.push(function (value) {
if (angular.isUndefined(value) || value === null) {
return '';
}
else if (angular.isObject(value) || angular.isArray(value)) {
throw new Error('ui-ace cannot use an object or an array as a model');
}
return value;
});
ngModel.$render = function () {
session.setValue(ngModel.$viewValue);
};
}
// set the options here, even if we try to watch later, if this
// line is missing things go wrong (and the tests will also fail)
setOptions(acee, session, opts);
// Listen for option updates
scope.$watch( attrs.uiAce, function() {
opts = angular.extend({}, options, scope.$eval(attrs.uiAce));
// unbind old change listener
session.removeListener('change', onChangeListener);
// bind new change listener
onChangeListener = listenerFactory.onChange(opts.onChange);
session.on('change', onChangeListener);
// unbind old blur listener
//session.removeListener('blur', onBlurListener);
acee.removeListener('blur', onBlurListener);
// bind new blur listener
onBlurListener = listenerFactory.onBlur(opts.onBlur);
acee.on('blur', onBlurListener);
setOptions(acee, session, opts);
}, /* deep watch */ true );
// EVENTS
onChangeListener = listenerFactory.onChange(opts.onChange);
session.on('change', onChangeListener);
onBlurListener = listenerFactory.onBlur(opts.onBlur);
acee.on('blur', onBlurListener);
elm.on('$destroy', function () {
acee.session.$stopWorker();
acee.destroy();
});
scope.$watch(function() {
return [elm[0].offsetWidth, elm[0].offsetHeight];
}, function() {
acee.resize();
acee.renderer.updateFull();
}, true);
}
};
}]);
@@ -0,0 +1,99 @@
/*
example usage: <textarea json-edit="myObject" rows="8" class="form-control"></textarea>
jsonEditing is a string which we edit in a textarea. we try parsing to JSON with each change. when it is valid, propagate model changes via ngModelCtrl
use isolate scope to prevent model propagation when invalid - will update manually. cannot replace with template, or will override ngModelCtrl, and not hide behind facade
will override element type to textarea and add own attribute ngModel tied to jsonEditing
*/
angular.module("umbraco.directives")
.directive('umbRawModel', function () {
return {
restrict: 'A',
require: 'ngModel',
template: '<textarea ng-model="jsonEditing"></textarea>',
replace : true,
scope: {
model: '=umbRawModel',
validateOn:'='
},
link: function (scope, element, attrs, ngModelCtrl) {
function setEditing (value) {
scope.jsonEditing = angular.copy( jsonToString(value));
}
function updateModel (value) {
scope.model = stringToJson(value);
}
function setValid() {
ngModelCtrl.$setValidity('json', true);
}
function setInvalid () {
ngModelCtrl.$setValidity('json', false);
}
function stringToJson(text) {
try {
return angular.fromJson(text);
} catch (err) {
setInvalid();
return text;
}
}
function jsonToString(object) {
// better than JSON.stringify(), because it formats + filters $$hashKey etc.
// NOTE that this will remove all $-prefixed values
return angular.toJson(object, true);
}
function isValidJson(model) {
var flag = true;
try {
angular.fromJson(model);
} catch (err) {
flag = false;
}
return flag;
}
//init
setEditing(scope.model);
var onInputChange = function(newval,oldval){
if (newval !== oldval) {
if (isValidJson(newval)) {
setValid();
updateModel(newval);
} else {
setInvalid();
}
}
};
if(scope.validateOn){
element.on(scope.validateOn, function(){
scope.$apply(function(){
onInputChange(scope.jsonEditing);
});
});
}else{
//check for changes going out
scope.$watch('jsonEditing', onInputChange, true);
}
//check for changes coming in
scope.$watch('model', function (newval, oldval) {
if (newval !== oldval) {
setEditing(newval);
}
}, true);
}
};
});
@@ -55,11 +55,91 @@ angular.module('umbraco.mocks').
allowedActions: ["U", "H", "A"],
tabs: [
{
label: "Child documents",
label: "Grid",
id: 1,
active: true,
properties: [
{ alias: "list", label: "List", view: "listview", value: "", hideLabel: true, config:{entityType: "content"} },
{ alias: "grid",
label: "Grid",
view: "grid",
value: "",
hideLabel: true,
config: {
items:{
styles:[
{
label: "Set a background image",
description: "Set a row background",
key: "background-image",
view: "imagepicker",
modifier: "url({0})"
}
],
config:[
{
label: "Class",
description: "Set a css class",
key: "class",
view: "textstring"
}
],
columns: 12,
templates:[
{
name: "1 column layout",
sections: [
{
grid: 12,
}
]
},
{
name: "2 column layout",
sections: [
{
grid: 4,
},
{
grid: 8
}
]
}
],
layouts:[
{
name: "Headline",
areas: [
{
grid: 12,
editors: ["headline"]
}
]
},
{
name: "Article",
areas: [
{
grid: 12
},
{
grid: 4
},
{
grid: 8
},
{
grid: 12
}
]
}
]
}
}
},
]
},
{
@@ -111,22 +191,6 @@ angular.module('umbraco.mocks').
]
},
{
label: "Tab # 7",
id: 7,
properties: [
{ alias: "valTest7", label: "Validation test", view: "validationtest", value: "asdfasdf" },
{ alias: "bodyText7", label: "Body Text", description: "Here you enter the primary article contents", view: "rte", value: "<p>askjdkasj lasjd</p>", config: {} },
{ alias: "textarea7", label: "textarea", view: "textarea", value: "ajsdka sdjkds", config: { rows: 4 } },
{ alias: "content7", label: "Content picker", view: "contentpicker", value: "1234,23242,23232,23231" }
]
},
{
label: "Grid",
id: 8,
properties: [
{ alias: "canvas", label: "Grid", view: "canvas", value: "test", hideLabel: true }
]
}, {
label: "Generic Properties",
id: 0,
properties: [
@@ -78,7 +78,7 @@ angular.module('umbraco.mocks').
{ name: "Multiple textstring", childNodesUrl: null, id: 11, icon: "icon-document", children: [], expanded: false, hasChildren: false, level: 1, menuUrl: null },
{ name: "Yes/No", childNodesUrl: null, id: 12, icon: "icon-document", children: [], expanded: false, hasChildren: false, level: 1, menuUrl: null },
{ name: "Rich Text Editor", childNodesUrl: null, id: 13, icon: "icon-document", children: [], expanded: false, hasChildren: false, level: 1, menuUrl: null }
];
];
return [200, children, null];
}
@@ -20,6 +20,7 @@ function initBackEnd($httpBackend, contentMocks, mediaMocks, treeMocks, userMock
prevaluesMocks.register();
entityMocks.register();
$httpBackend.whenGET(/^..\/config\//).passThrough();
$httpBackend.whenGET(/^views\//).passThrough();
$httpBackend.whenGET(/^js\//).passThrough();
$httpBackend.whenGET(/^lib\//).passThrough();
@@ -0,0 +1,46 @@
[
{
"name": "Rich text editor",
"alias": "rte",
"view": "rte",
"icon": "icon-article"
},
{
"name": "Image",
"alias": "media",
"view": "media",
"icon": "icon-picture"
},
{
"name": "Macro",
"alias": "macro",
"view": "macro",
"icon": "icon-settings-alt"
},
{
"name": "Embed",
"alias": "embed",
"view": "embed",
"icon": "icon-movie-alt"
},
{
"name": "Headline",
"alias": "headline",
"view": "textstring",
"icon": "icon-coin",
"config": {
"style": "font-size: 36px; line-height: 45px; font-weight: bold",
"markup": "<h1>#value#</h1>"
}
},
{
"name": "Quote",
"alias": "quote",
"view": "textstring",
"icon": "icon-quote",
"config": {
"style": "border-left: 3px solid #ccc; padding: 10px; color: #ccc; font-family: serif; font-variant: italic; font-size: 18px",
"markup": "<blockquote>#value#</blockquote>"
}
}
]
@@ -700,6 +700,46 @@ h4.panel-title {
display: block;
}
.canvasdesigner .color-picker-preview {
height: 26px;
border: 1px solid #CDCDCD;
border-radius: 1px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
cursor: pointer;
}
.canvasdesigner .spectrumcolorpicker {
}
.canvasdesigner .float-panel .sp-container.sp-flat {
background-color: transparent;
border: none;
padding: 10px;
width: 100%;
}
.canvasdesigner .float-panel .sp-container.sp-flat .sp-picker-container {
padding: 0;
margin: 0px;
margin-bottom: 10px;
border: none;
width: 100%;
}
.canvasdesigner .float-panel .sp-container.sp-flat .sp-palette-container {
padding: 0;
height: 32px;
width: 100%;
float: left;
margin: 0;
border: none;
}
.canvasdesigner .float-panel .sp-container.sp-flat .sp-button-container {
display: none;
}
.colorPickerDelete {
position: absolute;
margin: -23px 0 0 0;
@@ -987,7 +1027,7 @@ iframe {
height: 24px;
}
.bordereditor .spectrumcolorpicker {
.bordereditor .color-picker-preview {
display: inline-block;
width: 120px;
float: left;
+198 -74
View File
@@ -5,7 +5,7 @@
overflow-y:hidden!important;
}
IFRAME {overflow:hidden;}
IFRAME {overflow:hidden;}
// Sortabel
@@ -18,7 +18,7 @@
width: 160px !important;
overflow: hidden;
padding: 5px;
border-radius:50px;
border-radius:5px;
-webkit-box-shadow: 3px 3px 12px 0px rgba(50, 50, 50, 0.45);
-moz-box-shadow: 3px 3px 12px 0px rgba(50, 50, 50, 0.45);
box-shadow: 3px 3px 12px 0px rgba(50, 50, 50, 0.45);
@@ -29,7 +29,7 @@
background: none !important;
color: #999 !important;
padding: 0 !important;
margin: 0 !important;
margin: 0 !important;
}
.usky-grid .ui-sortable-helper .cell-tools{
@@ -66,20 +66,22 @@
.usky-grid .right {
float:right;
}
// general layout components
// -------------------------
.usky-grid .tb {
display:table;
width: 100%;
table-layout: fixed;
}
.usky-grid .td {
display:table-cell;
width: 100%;
display: inline-block;
vertical-align:top;
border-right:1px dashed rgba(182, 182, 182, 0.0);
box-sizing: border-box;
}
.usky-grid .tb:hover .td{
border-right:1px dashed rgba(182, 182, 182, 0.3);
}
@@ -87,31 +89,16 @@
border-right:1px dashed rgba(182, 182, 182, 0.0) !important;
}
.usky-grid .tr {
display:table-row;
}
.usky-grid .td2{
width: 50%;
}
.usky-grid .td3{
width: 33.33%;
}
.usky-grid .td4{
width: 25%;
}
.usky-grid .td5{
width: 20%;
}
.usky-grid .td6{
width: 16.6%;
}
.usky-grid .middle {
text-align: center;
}
.usky-grid .mainTb {
.usky-grid .mainTb {
border-collapse: separate;
}
.usky-grid .mainTd {
.usky-grid .mainTd {
position:relative;
}
@@ -120,10 +107,10 @@
// COLUMN
// -------------------------
.usky-grid .usky-column {
}
.usky-grid .usky-column.last {
}
@@ -162,6 +149,7 @@
right: 0;
width: 150px;
opacity: 0.3;
z-index: 50;
}
.usky-grid .cell-tools:hover{
@@ -171,11 +159,9 @@
.usky-grid .cell-tools-add {
position: absolute;
text-align: center;
bottom: -20px;
bottom: 0px;
left: 0;
right: 0;
z-index: 500;
opacity: 0.3;
}
.usky-grid .usky-control:hover .cell-tools-add{
@@ -206,6 +192,11 @@
cursor: move
}
.usky-grid .cell-tools-edit{
position: absolute;
top: 80px;
right: 5px;
}
// CONTROL
@@ -216,9 +207,9 @@
-webkit-transition: all .20s ease-in-out;*/
position:relative;
display:block;
/*
border: 1px dashed rgba(255, 0, 0, .0);
border: 1px dashed rgba(255, 0, 0, .0);
border-bottom-width: 1px;
*/
@@ -247,7 +238,7 @@
}
.usky-grid .usky-control-inner{
min-height: 60px;
min-height: 60px;
}
@@ -255,7 +246,7 @@
// CONTROL PLACEHOLDER
// -------------------------
.usky-grid .usky-control-placeholder {
min-height: 50px;
min-height: 20px;
position: relative;
text-align: center;
text-align: -moz-center;
@@ -266,7 +257,7 @@
font-size: 14px; opacity: 0.7; text-align: left;
padding: 5px;
border:1px solid rgba(182, 182, 182, 0.3);
height: 50px;
height: 20px;
}
.usky-grid .usky-control-placeholder:hover .placeholder{
@@ -293,7 +284,7 @@
.usky-grid .usky-editor-placeholder i{
color: @grayLight;
font-size: 85px;
line-height: 85px;
line-height: 85px;
display: block;
margin-bottom: 10px;
}
@@ -326,7 +317,7 @@
resize: none;
font-style: italic;
}
.usky-grid .cellPanelRte {
min-height:60px;
}
@@ -382,7 +373,7 @@
}
.usky-grid ul {
@@ -450,7 +441,7 @@
background-color: #F7F7F7 !important;
}
// MEDIA EDITOR
// -------------------------
.usky-grid .fullSizeImage {
@@ -488,18 +479,18 @@
/**************************************************************************************************/
.usky-grid .usky-cell{
padding-bottom: 20px;
}
.usky-grid .usky-row{
}
.usky-grid .usky-control{
margin: 10px 0 0 0;
padding: 5px;
}
.usky-grid .usky-templates-columns{
margin-top: 30px;
}
@@ -526,7 +517,7 @@
overflow:hidden;
width:100%;
}
.usky-grid .uSky-templates-template {
display:inline-block;
width:100px;
@@ -538,9 +529,9 @@
border:5px solid @blue;
}
.usky-grid .uSky-templates-template .tb {
width:100%;
height:150px;
.usky-grid .uSky-templates-template .tb {
width:100%;
height:150px;
padding:10px;
background-color: @grayLighter;
border: 5px solid @grayLight;
@@ -548,11 +539,11 @@
position: relative;
}
.usky-grid .uSky-templates-template .tr {
.usky-grid .uSky-templates-template .tr {
height: 100%;
position: relative;
}
.usky-grid .uSky-templates-template .tb .uSky-templates-column {
height:100%;
border: 1px dashed @grayLight;
@@ -577,33 +568,154 @@
vertical-align: middle;
}
.usky-grid .usky-templates-columns .td i{
.usky-grid .usky-templates-columns .td i{
color: @gray;
opacity: 0.8
}
}
.usky-grid .mainTbpt:hover {
.usky-grid .mainTbpt:hover {
border-color:@blue;
}
}
.usky-grid .mainTbpt {
.usky-grid .mainTbpt {
cursor:pointer;
border-spacing: 3px;
border-collapse: separate;
height: 35px;
border: 2px solid @grayLight;
min-height: 35px;
border: 2px solid @grayLight;
margin:0px;
background-color: @grayLighter;
}
.usky-grid .mainTdpt {
height: 35px;
border: 1px dashed @grayLight;
margin:0px;
background-color: rgba(228, 228, 228, 0.41);
overflow: hidden;
}
padding: 1px;
}
.usky-grid .mainTdpt {
padding: 1px;
}
.usky-grid .mainTbpt {
height: auto;
}
.usky-grid .mainTdpt {
height: 11px;
margin: 0;
overflow: hidden;
border: 1px dashed #d9d9d9;
display: block;
float: left;
}
.mainTdpt span{
width: 100%;
display: block;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0 1px;
height: 10px;
background: @grayLight
}
/* New template preview */
.usky-grid {
.templates-preview {
display: inline-block;
width: 100%;
text-align: center;
small {
position: absolute;
width: 100%;
left: 0;
bottom: -25px;
padding-top: 15px;
}
.help-text {
margin: 35px 35px 0 0;
}
}
.preview-rows {
display: inline-block;
position: relative;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 125px;
margin: 35px 40px 15px 0;
border: 2px solid @grayLight; /* @grayLight */
transition: border 200ms linear;
&:hover {
border-color: @blue;
cursor: pointer;
}
.preview-row {
display: inline-block;
width: 100%;
vertical-align: bottom;
}
}
.preview-rows.layout {
height: 180px;
padding: 2px;
.preview-row {
height: 100%;
}
.preview-col {
height: 100%;
border: dashed 1px @grayLight;
}
.preview-cell {
background-color: @grayLighter;
}
.preview-overlay {
display: none;
}
}
.preview-rows.columns {
min-height: 18px;
line-height: 11px;
padding: 1px;
}
.preview-col {
display: block;
float: left;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 33.3%; /* temp value */
height: 10px;
margin: 0;
border: 1px solid @white; /* @white */
.preview-cell {
display: block;
width: 100%;
height: 100%;
background-color: @grayLight; /* @grayLight */
margin: 0 1px 1px 0;
}
}
.preview-overlay {
display: block;
width: 100%;
position: absolute;
height: 100%;
top: 0;
box-sizing: border-box;
left: 0;
border: 3px solid white;
}
}
/**************************************************************************************************/
/* overlay */
@@ -614,14 +726,13 @@
height: 380px;
overflow: auto;
border: 1px solid #ccc;
margin-top: -190px;
margin-top: -270px;
margin-left: -150px;
background: white;
padding: 7px;
top: 0;
left: 50%;
z-index: 666;
z-index: 6660;
-webkit-box-shadow: 3px 3px 12px 0px rgba(50, 50, 50, 0.45);
-moz-box-shadow: 3px 3px 12px 0px rgba(50, 50, 50, 0.45);
box-shadow: 3px 3px 12px 0px rgba(50, 50, 50, 0.45);
@@ -674,7 +785,7 @@
/**************************************************************************************************/
.usky-grid-configuration .uSky-templates{
text-align: left;
}
}
.usky-grid-configuration ul{
display: block;
@@ -688,14 +799,21 @@
.usky-grid-configuration .uSky-templates .uSky-templates-template{
margin: 0px 20px 20px 0px;
width: 60px;
width: 80px;
}
.usky-grid-configuration .uSky-templates .uSky-templates-template .tb{
height: 50px;
max-height: 50px;
border-width: 2px !important;
padding: 0px;
border-spacing:2px;
overflow: hidden;
}
.usky-grid-configuration .uSky-templates .uSky-templates-template span{
background: @grayLight;
display: inline-block;
}
.usky-grid-configuration .uSky-templates .uSky-templates-template .tb:hover{
@@ -706,6 +824,8 @@
display: block;
float: left;
margin-left: -1px;
border: 1px white solid !important;
background: @grayLighter;
}
.usky-grid-configuration .uSky-templates-column.last{
@@ -717,9 +837,14 @@
font-size: 20px;
line-height: 70px;
color: #ccc;
text-decoration: none
text-decoration: none;
background: white;
}
.usky-grid-configuration .mainTdpt{
height: initial;
border: none;
}
.usky-grid-configuration .uSky-templates-rows .uSky-templates-row{
margin: 0px 50px 20px 0px;
@@ -737,4 +862,3 @@
}
.usky-grid-configuration a.uSky-templates-column{height: 70px !important;}
@@ -0,0 +1,14 @@
function imageFilePickerController($scope, dialogService, mediaHelper) {
$scope.pick = function() {
dialogService.mediaPicker({
multiPicker: false,
callback: function(data) {
$scope.model.value = mediaHelper.resolveFile(data, false);
}
});
};
}
angular.module('umbraco').controller("Umbraco.PrevalueEditors.ImageFilePickerController",imageFilePickerController);
@@ -0,0 +1,14 @@
<div ng-controller="Umbraco.PrevalueEditors.ImageFilePickerController" class="umb-editor umb-mediapicker">
<ul class="umb-sortable-thumbnails">
<li style="width: 120px; height: 100px; overflow: hidden;">
<a href ng-click="pick()" class="icon-holder" ng-hide="model.value">
<i class="icon icon-add large" ></i>
<small>Choose...</small>
</a>
<img ng-src="{{model.value}}" alt="" ng-show="model.value">
<a href class="picked-image" ng-click="model.value = null" ng-show="model.value"><i class="icon icon-delete"></i></a>
</li>
</ul>
</div>
@@ -1,11 +1,45 @@
var uSkyGridConfig = [
{
style:[
{
label: "Set a background image",
description: "Set a row background",
key: "background-image",
view: "imagepicker",
modifier: "url({0})"
},
{
label: "Set a font color",
description: "Pick a color",
key: "color",
view: "colorpicker"
}
],
config:[
{
label: "Preview",
description: "Display a live preview",
key: "preview",
view: "boolean"
},
{
label: "Class",
description: "Set a css class",
key: "class",
view: "textstring"
}
],
layouts: [
{
grid: 12,
percentage: 100,
rows: [
{
name: "Single column",
@@ -13,7 +47,7 @@ var uSkyGridConfig = [
grid: 12,
percentage: 100
}]
},
},
{
name: "Article",
@@ -96,7 +130,7 @@ var uSkyGridConfig = [
{
grid: 9,
percentage: 70,
cellModels: [
{
models: [{
@@ -326,4 +360,4 @@ var uSkyGridConfig = [
}
]
}
];
];
@@ -0,0 +1,73 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.GridController.Dialogs.Config",
function ($scope, $http) {
var placeHolder = "{0}";
var addModifier = function(val, modifier){
if (!modifier || modifier.indexOf(placeHolder) < 0) {
return val;
} else {
return modifier.replace(placeHolder, val);
}
}
var stripModifier = function (val, modifier) {
if (!val || !modifier || modifier.indexOf(placeHolder) < 0) {
return val;
} else {
var paddArray = modifier.split(placeHolder);
if(paddArray.length == 1){
if (modifier.indexOf(placeHolder) === 0) {
return val.slice(0, -paddArray[0].length);
} else {
return val.slice(paddArray[0].length, 0);
}
}else{
return val.slice(paddArray[0].length, -paddArray[1].length);
}
}
}
$scope.styles = angular.copy($scope.dialogOptions.config.items.styles);
$scope.config = angular.copy($scope.dialogOptions.config.items.config);
var element = $scope.dialogOptions.gridItem;
if(angular.isObject(element.config)){
_.each($scope.config, function(cfg){
var val = element.config[cfg.key];
if(val){
cfg.value = stripModifier(val, cfg.modifier);
}
});
}
if(angular.isObject(element.styles)){
_.each($scope.styles, function(style){
var val = element.styles[style.key];
if(val){
style.value = stripModifier(val, style.modifier);
}
});
}
$scope.saveAndClose = function(){
var styleObject = {};
var configObject = {};
_.each($scope.styles, function(style){
if(style.value){
styleObject[style.key] = addModifier(style.value, style.modifier);
}
});
_.each($scope.config, function (cfg) {
if (cfg.value) {
configObject[cfg.key] = addModifier(cfg.value, cfg.modifier);
}
});
$scope.submit({config: configObject, styles: styleObject});
};
});
@@ -0,0 +1,40 @@
<div class="umb-panel" ng-controller="Umbraco.PropertyEditors.GridController.Dialogs.Config">
<div class="umb-panel-body no-header with-footer compact">
<umb-pane>
<div ng-if="config">
<h4>Settings</h4>
<umb-property
property="configValue"
ng-repeat="configValue in config">
<umb-editor model="configValue" is-pre-value="true"></umb-editor>
</umb-property>
</div>
<div ng-if="styles">
<h4>Style</h4>
<umb-property
property="styleValue"
ng-repeat="styleValue in styles">
<umb-editor model="styleValue" is-pre-value="true"></umb-editor>
</umb-property>
</div>
</umb-pane>
</div>
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">
<a href ng-click="saveAndClose()" class="btn btn-primary">
<localize key="buttons_save">Save</localize>
</a>
</div>
</div>
</div>
</div>
@@ -0,0 +1,15 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.GridPrevalueEditorController.Dialogs.EditConfig",
function ($scope, $http) {
$scope.renderModel = {};
$scope.renderModel.name = $scope.dialogOptions.name;
$scope.renderModel.config = $scope.dialogOptions.config;
$scope.saveAndClose = function(isValid){
if(isValid){
$scope.submit($scope.renderModel.config);
}
};
});
@@ -0,0 +1,31 @@
<form name="gridConfigEditor">
<div class="umb-panel" ng-controller="Umbraco.PropertyEditors.GridPrevalueEditorController.Dialogs.EditConfig">
<div class="umb-panel-body no-header with-footer compact">
<umb-pane>
<h4>{{renderModel.name}}</h4>
<p>Settings will only save if the entered json configuration is valid</p>
<textarea name="configSource"
validate-on="'blur'"
rows="20" class="umb-editor umb-textarea"
umb-raw-model="renderModel.config"></textarea>
<div class="alert alert-error" ng-show="gridConfigEditor.$invalid === true">
This configuration is not valid json, and will not be saved.
</div>
</umb-pane>
</div>
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">
<a href ng-click="saveAndClose(gridConfigEditor.$valid)" class="btn btn-primary">
<localize key="buttons_save">Save</localize>
</a>
</div>
</div>
</div>
</div>
</form>
@@ -3,8 +3,12 @@ angular.module("umbraco")
function ($scope, $rootScope, $timeout, dialogService, macroResource, macroService, $routeParams) {
$scope.title = "Click to insert macro";
$scope.setMacro = function(){
dialogService.macroPicker({
dialogService.macroPicker({
dialogData: {
macroData: $scope.control.value
},
callback: function (data) {
$scope.control.value = {
@@ -3,7 +3,8 @@ angular.module("umbraco")
function ($scope, $rootScope, $timeout, dialogService) {
$scope.setImage = function(){
dialogService.mediaPicker({
dialogService.mediaPicker({
startNodeId: $scope.control.editor.config && $scope.control.editor.config.startNodeId ? $scope.control.editor.config.startNodeId : undefined,
multiPicker: false,
callback: function (data) {
$scope.control.value = {
@@ -1,5 +1,6 @@
<div ng-controller="Umbraco.PropertyEditors.Grid.TextStringController">
<textarea
rows="1"
class="textstring input-block-level" id="{{control.uniqueId}}_text"
ng-keyup="adjustSize($event)" ng-model="control.value"
ng-attr-style="{{control.editor.config.style}}" placeholder="Write here..."></textarea>
@@ -8,7 +8,7 @@ angular.module("umbraco")
$scope.currentToolsControl = null;
$scope.currentControl = null;
$scope.openRTEToolbarId = null;
$scope.hasSettings = false;
// *********************************************
// Sortable options
@@ -99,8 +99,8 @@ angular.module("umbraco")
start: function (e, ui) {
ui.item.find('.mceNoEditor').each(function () {
notIncludedRte = []
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'))
notIncludedRte = [];
tinyMCE.execCommand('mceRemoveEditor', false, $(this).attr('id'));
});
},
@@ -119,7 +119,7 @@ angular.module("umbraco")
}, 500, false);
}
}
};
// *********************************************
// Add items overlay menu
@@ -184,9 +184,15 @@ angular.module("umbraco")
$scope.currentRow = null;
};
$scope.setCurrentRemoveRow = function (Row) {
$scope.currentRemoveRow = Row;
};
$scope.disableCurrentRemoveRow = function (Row) {
$scope.currentRemoveRow = null;
};
$scope.setCurrentMovedRow = function (Row) {
$scope.currentRow = null;
$scope.currentRemoveControl = null;
$scope.currentMovedRow = Row;
};
@@ -218,18 +224,32 @@ angular.module("umbraco")
if(row){
section.rows.push(row);
}
};
$scope.removeRow = function (section, $index) {
if (section.rows.length > 0) {
section.rows.splice($index, 1);
$scope.openRTEToolbarId = null;
$scope.initContent();
}
};
$scope.editGridItemSettings = function (gridItem) {
dialogService.open(
{
template: "views/propertyeditors/grid/dialogs/config.html",
gridItem: gridItem,
config: $scope.model.config,
callback: function(data){
gridItem.styles = data.styles;
gridItem.config = data.config;
}
});
};
// *********************************************
// Cell management functions
@@ -365,6 +385,11 @@ angular.module("umbraco")
$scope.initContent = function() {
var clear = true;
//settings indicator shortcut
if($scope.model.config.items.config || $scope.model.config.items.styles){
$scope.hasSettings = true;
}
if ($scope.model.value && $scope.model.value.sections && $scope.model.value.sections.length > 0) {
_.forEach($scope.model.value.sections, function(section){
@@ -401,6 +426,7 @@ angular.module("umbraco")
_.forEach(section.rows, function(row, index){
if(!row.$initialized){
var initd = $scope.initRow(row);
//if init fails, remove
if(!initd){
section.rows.splic(index, 1);
@@ -420,18 +446,26 @@ angular.module("umbraco")
//merge the layout data with the original config data
//if there are no config info on this, splice it out
var original = _.find($scope.model.config.items.layouts, function(o){ return o.name === row.name; });
var original = _.find($scope.model.config.items.layouts, function (o) { return o.name === row.name; });
if(!original){
return null;
}else{
//make a copy to not touch the original config
original = angular.copy(original);
original.styles = row.styles;
original.config = row.config;
//sync area configuration
_.each(original.areas, function(area, areaIndex){
var currentArea = row.areas[areaIndex];
area.config = currentArea.config;
area.styles = currentArea.styles;
//copy over existing controls into the new areas
if(row.areas.length > areaIndex && row.areas[areaIndex].controls){
area.controls = row.areas[areaIndex].controls;
area.controls = currentArea.controls;
_.forEach(area.controls, function(control, controlIndex){
$scope.initControl(control, controlIndex);
@@ -1,28 +1,42 @@
<div ng-controller="Umbraco.PropertyEditors.GridController" class="usky-grid">
<div ng-if="contentReady">
<!-- Template picker -->
<div class="uSky-templates tb" ng-show="!model.value || model.value == ''">
<div class="tr">
<div class="td middle">
<div class="uSky-templates-template"
ng-repeat="template in model.config.items.templates" style="">
<div class="tb" ng-click="addTemplate(template)">
<div class="tr">
<div class="td uSky-templates-column"
<div class="templates-preview"
ng-show="!model.value || model.value == ''">
<div class="preview-rows layout"
ng-repeat="template in model.config.items.templates"
ng-click="addTemplate(template)">
<div class="preview-row">
<div class="preview-col"
ng-class="{last:$last}"
ng-repeat="section in template.sections"
style="width:{{ percentage(section.grid) }}%">
</div>
</div>
ng-style="{width: percentage(section.grid) + '%'}">
<div class="preview-cell">
</div>
</div>
<br/>
<div class="help-text">To start, select a layout for your grid</div>
</div>
</div>
</div>
<div class="preview-overlay">
</div>
<small>{{layout.name}}</small>
</div> <!-- .templates-preview-rows -->
<p><span class="help-text">Add rows to your layout</span></p>
</div> <!-- .templates-preview -->
<!-- template picker end -->
<!-- Grids -->
@@ -34,16 +48,15 @@
ng-class="{last:$last}"
ng-repeat="section in model.value.sections"
ng-init="initSection(section)"
style="width:{{section.$percentage}}%">
ng-style="{width: section.$percentage + '%'}">
<div ui-sortable="sortableOptions" ng-model="section.rows">
<!-- for each row in template section -->
<div ng-repeat="row in section.rows"
class="usky-row"
ng-mouseover="setCurrentRow(row)"
ng-mouseleave="disableCurrentRow()"
ng-class="{'selectedControl':currentRow == row && currentControl === null}">
ng-mouseenter="setCurrentRow(row)"
ng-mouseleave="disableCurrentRow()">
<!-- Row tool -->
<div class="row-tools" ng-animate="'fade'" ng-if="currentRow == row && currentControl === null">
@@ -52,8 +65,8 @@
<div class="cell-tools-remove">
<div class="iconBox"
ng-click="deletePrompt = true"
ng-mouseover="setCurrentRemoveControl(row)"
ng-mouseover="disableCurrentRemoveControl(row)">
ng-mouseenter="setCurrentRemoveControl(row)"
ng-mouseleave="disableCurrentRemoveControl(row)">
<span ng-if="deletePrompt">
Are you sure?
@@ -65,73 +78,34 @@
</div>
<div class="cell-tools-move">
<div class="iconBox"
ng-mouseover="setCurrentMovedRow(row)"
ng-mouseleave="disableCurrentMovedRow(row)">
<a class="iconBox"
href>
<i class="icon icon-navigation"></i>
</div>
</a>
</div>
<div class="cell-tools-edit" ng-if="hasSettings">
<a href class="iconBox" ng-click="editGridItemSettings(row)">
<i class="icon icon-settings"></i>
</a>
</div>
</div>
<!-- row container -->
<div class="{{row.cssClass}} mainContainer usky-row-inner"
ng-class="{last:$last,first:$first,warnhighlight:currentRemoveControl == row, infohighlight:currentMovedRow == row}">
ng-class="{last:$last,first:$first,warnhighlight:currentRemoveRow == row, infohighlight:currentMovedRow == row}">
<div class="mainTb">
<div class="tb">
<div class="tr">
<!-- cells in row -->
<div style="width:{{ area.$percentage }}%"
<div ng-style="{width: area.$percentage + '%'}"
ng-class="{last:$last,first:$first}"
class="td mainTd usky-cell"
ng-repeat="area in row.areas" ui-sortable="sortableOptionsCell" ng-model="area.controls">
<!-- if area is empty tools -->
<div class="usky-control usky-control-placeholder"
ng-if="area.controls.length == 0">
<div ng-if="area.allowed && area.allowed.length === 1"
ng-init="singleEditor = area.$allowedEditors[0]"
class="cell-tools-add-single single-editor-{{singleEditor.alias}}">
<div class="help-text" style="margin-bottom: 15px">
To start, click the <i class=" icon {{singleEditor.icon}} blue">
</i> below and add your first {{singleEditor.name}}
</div><br/>
<div class="iconBox">
<a href ng-click="addControl(singleEditor, area)">
<i class="icon {{singleEditor.icon}}"></i>
</a>
</div>
</div>
<div ng-if="!area.allowed || area.allowed.length > 1">
<div class="help-text" style="margin-bottom: 15px">
To start, click the <i class=" icon icon-add blue">
</i> below and add your first element
</div><br/>
<div class="cell-tools-add"
ng-if="!currentToolsControl"
ng-animate="'fade'">
<div class="iconBox">
<a href ng-click="addItemOverlay($event, area, 0, area.$uniqueId);">
<i class=" icon icon-add"></i>
</a>
</div>
<div ng-if="overlayMenu.show && overlayMenu.key == area.$uniqueId" ng-include="'views/propertyeditors/grid/dialogs/additem.html'"></div>
</div>
</div>
</div>
<!-- Controls in cell -->
<div ng-repeat="control in area.controls"
ng-mouseover="setCurrentControl(control)"
@@ -151,12 +125,12 @@
ng-mouseover="setCurrentRemoveControl(control)"
ng-mouseleave="disableCurrentRemoveControl(control)">
<span ng-show="deletePrompt">
Are you sure?
<a href style="text-decoration: underline" ng-click="removeControl(area, $index)">Yes</a>
</span>
<span ng-show="deletePrompt">
Are you sure?
<a href style="text-decoration: underline" ng-click="removeControl(area, $index)">Yes</a>
</span>
<i ng-show="!deletePrompt" class="icon icon-trash"></i>
<i ng-show="!deletePrompt" class="icon icon-trash"></i>
</div>
</div>
@@ -169,6 +143,11 @@
</div>
</div>
<div class="cell-tools-edit" ng-if="hasSettings && $first">
<a href class="iconBox" ng-click="editGridItemSettings(area)">
<i class="icon icon-settings"></i>
</a>
</div>
</div>
<div class="usky-control-inner" ng-class="{last:$last,
@@ -181,24 +160,31 @@
class="usky-cell usky-cell-{{control.editor.view}}">
</div>
</div>
<!-- add stuff -->
<div class="cell-tools-add"
ng-show="!currentToolsControl && control===currentControl && (area.max === undefined || area.max < area.controls.length)"
ng-animate="'fade'">
<div class="iconBox">
<a href ng-click="addItemOverlay($event, area, control.$index, control.$uniqueId)">
<i class=" icon icon-add"></i>
</a>
</div>
<div ng-show="overlayMenu.show && overlayMenu.key == control.$uniqueId" ng-include="'views/propertyeditors/grid/dialogs/additem.html'"></div>
</div>
</div>
<!-- Controls repeat end -->
<!-- if area is empty tools -->
<div class="usky-control usky-control-placeholder"
ng-if="area.controls.length == 0">
<div class="help-text" style="margin-bottom: 15px">
To start, click the <i class=" icon icon-add blue">
</i> below and add your first element
</div><br />
</div>
<div class="cell-tools-add"
ng-if="!currentToolsControl"
ng-animate="'fade'">
<div class="iconBox">
<a href ng-click="addItemOverlay($event, area, 0, area.$uniqueId);">
<i class=" icon icon-add"></i>
</a>
</div>
<div ng-if="overlayMenu.show && overlayMenu.key == area.$uniqueId" ng-include="'views/propertyeditors/grid/dialogs/additem.html'"></div>
</div>
</div>
<!-- cells repeat end -->
</div>
@@ -212,35 +198,43 @@
</div>
<!-- row sortable end -->
<!-- column tools -->
<div class="usky-templates-columns tb">
<div class="tr">
<div class="td middle">
<ul>
<li ng-repeat="layout in section.$allowedLayouts" ng-show="layout.areas.length > 0">
<div class="tb mainTbpt" ng-click="addRow(section, layout)">
<div class="tr">
<div style="width:{{ percentage(area.grid); }}%"
class="middle mainTdpt td"
ng-repeat="area in layout.areas">
<i class="icon {{cellPreview(area)}}"></i>
</div>
</div>
</div>
<small>{{layout.name}}</small>
</li>
</ul>
<div class="templates-preview">
<div class="preview-rows columns"
ng-repeat="layout in section.$allowedLayouts"
ng-show="layout.areas.length > 0"
ng-click="addRow(section, layout)">
<div class="preview-row">
<div class="preview-col" ng-style="{width: percentage(area.grid) + '%'}" ng-repeat="area in layout.areas">
<div class="preview-cell">
</div>
</div>
</div>
</div>
<div class="tr">
<div class="td middle">
<br />
<span class="help-text">Add rows to your layout</span>
<div class="preview-overlay">
</div>
</div>
</div>
<small>{{layout.name}}</small>
</div> <!-- .templates-preview-rows -->
<p>
<span class="help-text">Add rows to your layout</span>
</p>
</div> <!-- .templates-preview -->
<!-- column tools end -->
</div>
@@ -249,7 +243,4 @@
</div>
</div>
</div>
</div>
@@ -3,6 +3,25 @@ angular.module("umbraco")
function ($scope, $http, assetsService, $rootScope, dialogService, mediaResource, gridService, imageHelper, $timeout) {
var emptyModel = {
styles:[
{
label: "Set a background image",
description: "Set a row background",
key: "background-image",
view: "imagepicker",
modifier: "url({0})"
}
],
config:[
{
label: "Class",
description: "Set a css class",
key: "class",
view: "textstring"
}
],
columns: 12,
templates:[
{
@@ -160,10 +179,17 @@ angular.module("umbraco")
delete $scope.currentArea;
}else{
if(area === undefined){
var space = ($scope.availableLayoutSpace > 4) ? 4 : $scope.availableLayoutSpace;
var available = $scope.availableLayoutSpace;
var space = 4;
if(available < 4 && available > 0){
space = available;
}
area = {
grid: space
};
layout.areas.push(area);
}
$scope.currentArea = area;
@@ -180,8 +206,12 @@ angular.module("umbraco")
/****************
utillities
*****************/
$scope.scaleUp = function(section, max){
var add = (max > 1) ? 1 : max;
$scope.scaleUp = function(section, max, overflow){
var add = 1;
if(overflow !== true){
add = (max > 1) ? 1 : max;
}
//var add = (max > 1) ? 1 : max;
section.grid = section.grid+add;
};
$scope.scaleDown = function(section){
@@ -195,11 +225,42 @@ angular.module("umbraco")
delete collection;
}
};
$scope.percentage = function(spans){
return ((spans / $scope.model.value.columns) * 100).toFixed(1);
};
$scope.removeConfigValue = function(collection, index){
collection.splice(index, 1);
};
var editConfigCollection = function(configValues, title, callbackOnSave){
dialogService.open(
{
template: "views/propertyeditors/grid/dialogs/editconfig.html",
config: configValues,
name: title,
callback: function(data){
callbackOnSave(data);
}
});
};
$scope.editConfig = function(){
editConfigCollection($scope.model.value.config, "Settings", function(data){
$scope.model.value.config = data;
});
};
$scope.editStyles = function(){
editConfigCollection($scope.model.value.styles, "Styling", function(data){
$scope.model.value.styles = data;
});
};
/****************
watchers
*****************/
@@ -236,9 +297,19 @@ angular.module("umbraco")
if (!$scope.model.value || $scope.model.value === "" || !$scope.model.value.templates) {
$scope.model.value = emptyModel;
} else {
if (!$scope.model.value.columns) {
$scope.model.value.columns = emptyModel.columns;
}
if (!$scope.model.value.config) {
$scope.model.value.config = [];
}
if (!$scope.model.value.styles) {
$scope.model.value.styles = [];
}
}
});
@@ -1,7 +1,6 @@
<div ng-controller="Umbraco.PropertyEditors.GridPrevalueEditorController" class="usky-grid usky-grid-configuration">
<div style="width: 600px">
<div class="control-group uSky-templates" ng-if="!currentTemplate">
<umb-control-group label="Grid layouts" description="Layouts are the overall work area for the grid editor, usually you only need one or two differnt layouts" hide-label="false">
@@ -12,22 +11,22 @@
<li ng-repeat="template in model.value.templates">
<div class="uSky-templates-template" style="float: left">
<a href class="tb" ng-click="configureTemplate(template)">
<div class="tr">
<div class="td uSky-templates-column"
ng-class="{last:$last}"
ng-repeat="section in template.sections"
style="width:{{ percentage(section.grid) }}%">
</div>
<a class="uSky-templates-template tb mainTbpt" style="float: left"
ng-click="configureTemplate(template)">
<div class="tr">
<div
ng-style="{width: percentage(section.grid) + '%'}"
class="mainTdpt td"
ng-class="{last:$last}"
ng-repeat="section in template.sections">
<span style="height: 50px"></span>
</div>
</a>
</div>
</div>
</a>
<div>
<a ng-click="configureTemplate(template)" href>{{template.name}}</a><br />
<small>{{template.sections.length}} layout areas</small><br />
<small>{{template.sections.length}} sections</small><br />
<a class="btn btn-small btn-link" href ng-click="deleteTemplate($index)"><i class="icon-delete red"></i> Delete layout </a>
</div>
@@ -39,20 +38,21 @@
<button class="btn btn-small"
prevent-default
ng-click="configureTemplate()">
<i class="icon-add"></i>Add layout
<i class="icon-add"></i>Add new layout
</button>
</umb-control-group>
</div>
<div ng-if="currentTemplate">
<h5>Layout</h5>
<umb-control-group label="Name" hide-label="false">
<input type="text" class="" ng-model="currentTemplate.name" />
</umb-control-group>
<umb-control-group label="Sections" description="Choose an area in the layout to edit" hide-label="false">
<umb-control-group label="Sections" description="Choose a section in the layout to edit" hide-label="false">
<div class="uSky-templates-template"
style="margin: 0; width: 350px; position: relative;">
<div class="tb" style="height: 70px; border-width: 2px; padding: 2px">
@@ -74,8 +74,7 @@
</div>
<div ng-if="currentSection" style="padding-bottom: 50px;">
<h5>Modify layout area</h5>
<umb-control-group label="Size" hide-label="false">
<umb-control-group label="Width" hide-label="false">
<div class="grid-size-scaler">
<a href ng-click="scaleDown(currentSection)">
<i class="icon icon-remove"></i>
@@ -128,7 +127,7 @@
<div>
{{layout.name}}<br />
<small>{{layout.areas.length}} configurable columns</small><br />
<small>{{layout.areas.length}} configurable sections</small><br />
</div>
<br style="clear: both" />
@@ -138,11 +137,11 @@
</div>
</umb-control-group>
<button prevent-default ng-click="closeSection()" class="btn btn-small">Finish editing area</button>
<button prevent-default ng-click="closeSection()" class="btn btn-small">Finish editing section</button>
<a class="btn btn-small btn-link"
href
ng-click="deleteSection($index)"><i class="icon-delete red"></i>Delete area</a>
ng-click="deleteSection($index)"><i class="icon-delete red"></i>Delete section</a>
</div>
</umb-control-group>
@@ -163,10 +162,10 @@
<div style="max-width: 600px">
<div class="control-group uSky-templates" ng-if="!currentLayout">
<div class="control-group uSky-templates" ng-if="!currentTemplate">
<umb-control-group
label="Row configurations"
description="Rows are predefined columns of editors arranged horizontally"
description="Rows are predefined cells arranged horizontally"
hide-label="false">
<div class="control-group uSky-templates-rows">
@@ -176,19 +175,24 @@
<li ng-repeat="layout in model.value.layouts">
<div class="uSky-templates-row" style="float: left">
<a href class="tb mainTbpt" ng-click="configureLayout(layout)">
<div class="tr">
<div style="width:{{ percentage(area.grid); }}%" class="middle mainTdpt td" ng-repeat="area in layout.areas">
<i class="icon {{areaPreview(area)}}"></i>
</div>
<a class="uSky-templates-template tb mainTbpt" style="float: left"
ng-click="configureLayout(layout)">
<div class="tr">
<div
ng-style="{width: percentage(area.grid) + '%'}"
class="mainTdpt td"
ng-class="{last:$last}"
ng-repeat="area in layout.areas">
<span style="height: 20px"></span>
</div>
</a>
</div>
</div>
</a>
<div>
<a ng-click="configureLayout(layout)" href>{{layout.name}}</a><br />
<small>{{layout.areas.length}} columns</small><br />
<small>{{layout.areas.length}} cells</small><br />
<a class="btn btn-small btn-link" href ng-click="deleteLayout($index)"><i class="icon-delete red"></i> Delete row </a>
</div>
@@ -214,11 +218,14 @@
<input type="text" class="" ng-model="currentLayout.name" />
</umb-control-group>
<umb-control-group label="Layout areas" hide-label="false" description="Choose column from the row to edit">
<umb-control-group label="Layout areas" hide-label="false" description="Choose a cell from the row to edit">
<div class="uSky-templates-template"
style="margin: 0; width: 350px; position: relative;">
<div class="tb" style="height: 70px; border-width: 2px; padding: 2px">
<div class="tb" style="height: auto; border: none !important; background: none">
<div class="tr">
<a class="td uSky-templates-column"
ng-class="{last:$last, selected:area==currentArea}"
ng-repeat="area in currentLayout.areas"
@@ -226,7 +233,7 @@
style="width:{{ percentage(area.grid) }}%">
</a>
<a class="td uSky-templates-column add" ng-if="availableLayoutSpace > 0"
<a class="td uSky-templates-column add"
ng-click="configureArea(undefined, currentLayout)"
style="width:{{ percentage(availableLayoutSpace) }}%">
<i class="icon icon-add"></i>
@@ -236,23 +243,19 @@
</div>
<div ng-if="currentArea" style="padding-bottom: 50px;">
<h5>Modify column</h5>
<umb-control-group label="Size" hide-label="false">
<umb-control-group label="Width" hide-label="false">
<div class="grid-size-scaler">
<a href ng-click="scaleDown(currentArea)">
<i class="icon icon-remove"></i>
</a>
{{currentArea.grid}}
<a href ng-click="scaleUp(currentArea, availableLayoutSpace)">
<a href ng-click="scaleUp(currentArea, availableLayoutSpace, true)">
<i class="icon icon-add"></i>
</a>
</div>
</umb-control-group>
<umb-control-group hide-label="true">
<ul class="unstyled">
<li>
<label>
@@ -280,25 +283,80 @@
</div>
</umb-control-group>
<button prevent-default ng-click="closeArea()" class="btn btn-small">Finish editing column</button>
<button prevent-default ng-click="closeArea()" class="btn btn-small">Finish editing cell</button>
<a class="btn btn-small btn-link"
href
ng-click="deleteArea($index)"><i class="icon-delete red"></i> Delete column </a>
ng-click="deleteArea($index)"><i class="icon-delete red"></i> Delete cell </a>
</div>
</umb-control-group>
<umb-control-group hide-label="false" ng-if="!currentArea">
<button prevent-default ng-click="closeLayout()" class="btn btn-small">Finish editing row</button>
</umb-control-group>
</div>
</div>
<div style="max-width: 600px">
<div style="max-width: 600px" ng-if="!currentTemplate && !currentLayout">
<umb-control-group label="Columns" hide-label="false" description="Total combined number of columns in the grid layout">
<input type="text" class="" ng-model="model.value.columns" />
</umb-control-group>
<umb-control-group label="Settings" hide-label="false" description="Configure what settings editors can change">
<ul class="unstyled list-icons umb-contentpicker"
ui-sortable
ng-model="model.config">
<li ng-repeat="configValue in model.value.config">
<i class="icon icon-navigation handle"></i>
<a href="#" prevent-default ng-click="removeConfigValue(model.value.config, $index)">
<i class="icon icon-delete red hover-show"></i>
<i class="icon-settings-alt-2 hover-hide"></i>
{{configValue.label}}
</a>
</li>
</ul>
<ul class="unstyled list-icons">
<li>
<i class="icon icon-add blue"></i>
<a href="#" ng-click="editConfig()" prevent-default>
Edit settings
</a>
</li>
</ul>
</umb-control-group>
<umb-control-group label="Styles" hide-label="false" description="Configure what styling editors can change">
<ul class="unstyled list-icons umb-contentpicker"
ui-sortable
ng-model="model.value.styles">
<li ng-repeat="style in model.value.styles">
<i class="icon icon-navigation handle"></i>
<a href="#" prevent-default ng-click="removeConfigValue(model.value.styles, $index)">
<i class="icon icon-delete red hover-show"></i>
<i class="icon-brush hover-hide"></i>
{{style.label}}
</a>
</li>
</ul>
<ul class="unstyled list-icons">
<li>
<i class="icon icon-add blue"></i>
<a href="#" ng-click="editStyles()" prevent-default>
Edit style configuration
</a>
</li>
</ul>
</umb-control-group>
</div>
</div>
@@ -48,7 +48,7 @@ describe('edit content controller tests', function () {
});
it('it should have a tabs collection', function () {
expect(scope.content.tabs.length).toBe(9);
expect(scope.content.tabs.length).toBe(7);
});
it('it should have a properties collection on each tab', function () {
@@ -229,7 +229,7 @@ describe('contentEditingHelper tests', function () {
//assert
expect(changed.length).toBe(2);
expect(changed[0].alias).toBe("list");
expect(changed[0].alias).toBe("grid");
expect(changed[1].alias).toBe("bodyText");
});
@@ -1,47 +1,78 @@
@inherits UmbracoViewPage<dynamic>
@using Umbraco.Web.Templates
@using Newtonsoft.Json.Linq;
@using Newtonsoft.Json.Linq
@functions {
public static MvcHtmlString RenderElementAttributes(dynamic contentItem)
{
var attrs = new List<string>();
JObject cfg = contentItem.config;
if(cfg != null)
foreach (JProperty property in cfg.Properties())
attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
JObject style = contentItem.styles;
if (style != null) {
var cssVals = new List<string>();
foreach (JProperty property in style.Properties())
cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
if (cssVals.Any())
attrs.Add("style='" + string.Join(" ", cssVals) + "'");
}
return new MvcHtmlString(string.Join(" ", attrs));
}
}
@if (Model != null && !string.IsNullOrEmpty(Model.ToString()))
{
var onlyOneColumn = Model.sections != null ? ((System.Collections.ICollection)Model.sections).Count : 0;
<div class="uSky-grid @(onlyOneColumn > 1 ? "container-fluid" : "")">
<div class="row-fluid clearfix">
@foreach (var s in Model.sections)
{
<div class="@("span" + s.grid)">
@foreach (var row in s.rows)
{
<div class="gridrow_@row.uniqueId" >
<div>
<div class="row-fluid clearfix">
<div class="uSky-grid @(onlyOneColumn > 1 ? "container-fluid" : "")">
<div class="row-fluid clearfix">
@foreach (var area in row.areas)
{
<div class="@("span" + area.grid)">
@foreach (var s in Model.sections){
<div class="@("span" + s.grid) column"> <!-- section -->
<div class="grid-section">
<div @RenderElementAttributes(s)>
<div class="@(onlyOneColumn == 1 ? "container-fluid" : "")"><!-- remove container class -->
<!-- foreach row in section -->
@foreach (var row in s.rows){
<div class="row-fluid clearfix">
<div class="grid-row grid-row-@row.uniqueId">
<div @RenderElementAttributes(row)>
@foreach (var area in row.areas){
<div class="@("span" + area.grid) column">
<div class="grid-cell">
<div @RenderElementAttributes(area)>
@foreach (var control in area.controls)
{
if (control != null && control.editor != null && control.editor.view != null)
{
string editor = "grid/editors/" + control.editor.view.ToString();
<text>
@Html.Partial(editor, (object)control)
</text>
@foreach (var control in area.controls){
if (control != null && control.editor != null && control.editor.view != null){
string editor = "grid/editors/" + control.editor.view.ToString();
<text>@Html.Partial(editor, (object)control)</text>
}
}
}
</div>
</div>
</div>
}
</div>
</div>
</div>
}
}
</div>
</div>
}
</div>
</div>
}
</div>
}
</div>
}
@@ -1,45 +1,78 @@
@inherits UmbracoViewPage<dynamic>
@using Umbraco.Web.Templates
@using Newtonsoft.Json.Linq
@functions {
public static MvcHtmlString RenderElementAttributes(dynamic contentItem)
{
var attrs = new List<string>();
JObject cfg = contentItem.config;
if(cfg != null)
foreach (JProperty property in cfg.Properties())
attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
JObject style = contentItem.styles;
if (style != null) {
var cssVals = new List<string>();
foreach (JProperty property in style.Properties())
cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
if (cssVals.Any())
attrs.Add("style='" + string.Join(" ", cssVals) + "'");
}
return new MvcHtmlString(string.Join(" ", attrs));
}
}
@if (Model != null && !string.IsNullOrEmpty(Model.ToString()))
{
var onlyOneColumn = Model.sections != null ? ((System.Collections.ICollection)Model.sections).Count : 0;
<div class="uSky-grid @(onlyOneColumn > 1 ? "container" : "")">
<div class="row clearfix">
@foreach (var s in Model.sections)
{
<div class="col-md-@s.grid column">
@foreach (var row in s.rows)
{
<div class="gridrow_@row.uniqueId" >
<div class="container">
<div class="row clearfix">
<div class="uSky-grid @(onlyOneColumn > 1 ? "container" : "")">
<div class="row clearfix">
@foreach (var area in row.areas)
{
<div class="col-md-@area.grid column">
@foreach (var s in Model.sections){
<div class="col-md-@s.grid column"> <!-- section -->
<div class="grid-section">
<div @RenderElementAttributes(s)>
<div class="@(onlyOneColumn == 1 ? "container" : "")"><!-- remove container class -->
<!-- foreach row in section -->
@foreach (var row in s.rows){
<div class="row clearfix">
<div class="grid-row grid-row-@row.uniqueId">
<div @RenderElementAttributes(row)>
@foreach (var area in row.areas){
<div class="col-md-@area.grid column">
<div class="grid-cell">
<div @RenderElementAttributes(area)>
@foreach (var control in area.controls)
{
if (control != null && control.editor != null && control.editor.view != null)
{
string editor = "grid/editors/" + control.editor.view.ToString();
<text>
@Html.Partial(editor, (object)control)
</text>
@foreach (var control in area.controls){
if (control != null && control.editor != null && control.editor.view != null){
string editor = "grid/editors/" + control.editor.view.ToString();
<text>@Html.Partial(editor, (object)control)</text>
}
}
}
</div>
</div>
</div>
}
</div>
</div>
</div>
}
}
</div>
</div>
}
</div>
</div>
}
</div>
}
</div>
}
@@ -4,12 +4,12 @@ using System.Web.Mvc;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// Redirects to the current URL rendering an Umbraco page
/// Redirects to the current URL rendering an Umbraco page including it's query strings
/// </summary>
/// <remarks>
/// this is useful if you need to redirect
/// This is useful if you need to redirect
/// to the current page but the current page is actually a rewritten URL normally done with something like
/// Server.Transfer.
/// Server.Transfer. It is also handy if you want to persist the query strings.
/// </remarks>
public class RedirectToUmbracoUrlResult : ActionResult
{
+2 -2
View File
@@ -117,7 +117,7 @@ namespace Umbraco.Web.Mvc
/// </summary>
/// <param name="requestContext"></param>
/// <returns></returns>
private static PostedDataProxyInfo GetFormInfo(RequestContext requestContext)
internal static PostedDataProxyInfo GetFormInfo(RequestContext requestContext)
{
if (requestContext == null) throw new ArgumentNullException("requestContext");
@@ -201,7 +201,7 @@ namespace Umbraco.Web.Mvc
/// </summary>
/// <param name="requestContext"></param>
/// <param name="postedInfo"></param>
private IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo)
internal static IHttpHandler HandlePostedValues(RequestContext requestContext, PostedDataProxyInfo postedInfo)
{
if (requestContext == null) throw new ArgumentNullException("requestContext");
if (postedInfo == null) throw new ArgumentNullException("postedInfo");
@@ -34,6 +34,25 @@ namespace Umbraco.Web.Mvc
requestContext.RouteData.DataTokens.Add("umbraco", renderModel);
requestContext.RouteData.DataTokens.Add("umbraco-doc-request", umbracoContext.PublishedContentRequest);
requestContext.RouteData.DataTokens.Add("umbraco-context", umbracoContext);
//this is used just for a flag that this is an umbraco custom route
requestContext.RouteData.DataTokens.Add("umbraco-custom-route", true);
//Here we need to detect if a SurfaceController has posted
var formInfo = RenderRouteHandler.GetFormInfo(requestContext);
if (formInfo != null)
{
var def = new RouteDefinition
{
ActionName = requestContext.RouteData.GetRequiredString("action"),
ControllerName = requestContext.RouteData.GetRequiredString("controller"),
PublishedContentRequest = umbracoContext.PublishedContentRequest
};
//set the special data token to the current route definition
requestContext.RouteData.DataTokens["umbraco-route-def"] = def;
return RenderRouteHandler.HandlePostedValues(requestContext, formInfo);
}
return new MvcHandler(requestContext);
}
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Web.Routing
{
/// <summary>
/// This url provider is used purely to deal with umbraco custom routes that utilize UmbracoVirtualNodeRouteHandler and will return
/// the URL returned from the current PublishedContentRequest.PublishedContent (virtual node) if the request is in fact a virtual route and
/// the id that is being requested matches the id of the current PublishedContentRequest.PublishedContent.
/// </summary>
internal class CustomRouteUrlProvider : IUrlProvider
{
/// <summary>
/// This will simply return the URL that is returned by the assigned IPublishedContent if this is a custom route
/// </summary>
/// <param name="umbracoContext"></param>
/// <param name="id"></param>
/// <param name="current"></param>
/// <param name="mode"></param>
/// <returns></returns>
public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
{
if (umbracoContext == null) return null;
if (umbracoContext.PublishedContentRequest == null) return null;
if (umbracoContext.PublishedContentRequest.PublishedContent == null) return null;
if (umbracoContext.HttpContext == null) return null;
if (umbracoContext.HttpContext.Request == null) return null;
if (umbracoContext.HttpContext.Request.RequestContext == null) return null;
if (umbracoContext.HttpContext.Request.RequestContext.RouteData == null) return null;
if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens == null) return null;
if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey("umbraco-custom-route") == false) return null;
//ok so it's a custom route with published content assigned, check if the id being requested for is the same id as the assigned published content
return id == umbracoContext.PublishedContentRequest.PublishedContent.Id
? umbracoContext.PublishedContentRequest.PublishedContent.Url
: null;
}
/// <summary>
/// This always returns null because this url provider is used purely to deal with Umbraco custom routes with
/// UmbracoVirtualNodeRouteHandler, we really only care about the normal URL so that RedirectToCurrentUmbracoPage() works
/// with SurfaceControllers
/// </summary>
/// <param name="umbracoContext"></param>
/// <param name="id"></param>
/// <param name="current"></param>
/// <returns></returns>
public IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
{
return null;
}
}
}
@@ -133,7 +133,7 @@ namespace Umbraco.Web.Routing
{
if (mode == UrlProviderMode.Auto)
{
if (current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
if (current != null && domainUri.Uri.GetLeftPart(UriPartial.Authority) == current.GetLeftPart(UriPartial.Authority))
mode = UrlProviderMode.Relative;
else
mode = UrlProviderMode.Absolute;
+16 -9
View File
@@ -14,18 +14,25 @@ namespace Umbraco.Web.Scheduling
{
var umbracoBaseUrl = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl();
var url = string.Format("{0}/ping.aspx", umbracoBaseUrl);
try
if (string.IsNullOrWhiteSpace(umbracoBaseUrl))
{
using (var wc = new WebClient())
{
wc.DownloadString(url);
}
LogHelper.Warn<KeepAlive>("No url for service (yet), skip.");
}
catch (Exception ee)
else
{
LogHelper.Error<KeepAlive>("Error in ping", ee);
var url = string.Format("{0}/ping.aspx", umbracoBaseUrl);
try
{
using (var wc = new WebClient())
{
wc.DownloadString(url);
}
}
catch (Exception ee)
{
LogHelper.Error<KeepAlive>("Error in ping", ee);
}
}
}
@@ -27,13 +27,21 @@ namespace Umbraco.Web.Scheduling
try
{
var umbracoBaseUrl = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl();
var url = string.Format("{0}/RestServices/ScheduledPublish/Index", umbracoBaseUrl);
using (var wc = new WebClient())
{
//pass custom the authorization header
wc.Headers.Set("Authorization", AdminTokenAuthorizeAttribute.GetAuthHeaderTokenVal(appContext));
var result = wc.UploadString(url, "");
if (string.IsNullOrWhiteSpace(umbracoBaseUrl))
{
LogHelper.Warn<ScheduledPublishing>("No url for service (yet), skip.");
}
else
{
var url = string.Format("{0}/RestServices/ScheduledPublish/Index", umbracoBaseUrl);
using (var wc = new WebClient())
{
//pass custom the authorization header
wc.Headers.Set("Authorization", AdminTokenAuthorizeAttribute.GetAuthHeaderTokenVal(appContext));
var result = wc.UploadString(url, "");
}
}
}
catch (Exception ee)
+8 -5
View File
@@ -172,11 +172,14 @@ namespace Umbraco.Web.Security
if (status != MembershipCreateStatus.Success) return null;
}
//Set member online
provider.GetUser(model.Username, true);
//Log them in
FormsAuthentication.SetAuthCookie(membershipUser.UserName, model.CreatePersistentLoginCookie);
if (logMemberIn)
{
//Set member online
provider.GetUser(model.Username, true);
//Log them in
FormsAuthentication.SetAuthCookie(membershipUser.UserName, model.CreatePersistentLoginCookie);
}
return membershipUser;
}
+1
View File
@@ -492,6 +492,7 @@
<Compile Include="PublishedContentQuery.cs" />
<Compile Include="ImageCropperTemplateExtensions.cs" />
<Compile Include="Mvc\UmbracoVirtualNodeRouteHandler.cs" />
<Compile Include="Routing\CustomRouteUrlProvider.cs" />
<Compile Include="Routing\UrlProviderExtensions.cs" />
<Compile Include="Strategies\Migrations\ClearCsrfCookiesAfterUpgrade.cs" />
<Compile Include="Strategies\Migrations\ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs" />
+3 -2
View File
@@ -352,8 +352,9 @@ namespace Umbraco.Web
});
UrlProviderResolver.Current = new UrlProviderResolver(
//typeof(AliasUrlProvider), // not enabled by default
typeof(DefaultUrlProvider)
//typeof(AliasUrlProvider), // not enabled by default
typeof(DefaultUrlProvider),
typeof(CustomRouteUrlProvider)
);
ContentLastChanceFinderResolver.Current = new ContentLastChanceFinderResolver(