Compare commits

...

23 Commits

Author SHA1 Message Date
Sebastiaan Janssen 98684e6292 Add 100 to the ClientDependency.config version to avoid conflicts with older caches 2014-02-03 10:23:13 +01:00
perploug 9687b2abee Special rule for installer password change 2014-01-31 13:03:46 +01:00
perploug 4ea589e954 Missing changes on ContentPickerControler re-added 2014-01-31 11:38:24 +01:00
perploug 621a19d4bd Final tweaks to TreeSource picker
Better help text, polish icons and margins, made sure it toggles UI
correctly for each type of tree

(cherry picked from commit 9ce79e98a3)

Conflicts:
	src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html
2014-01-31 11:38:23 +01:00
perploug 5821444678 Fixes inconsistently named private method
Replaces delegates with lambdas

(cherry picked from commit 2a81162756)
2014-01-31 11:38:22 +01:00
perploug 7533baf368 fixes mntp filtering
(cherry picked from commit 3e22598f4a)
2014-01-31 11:38:21 +01:00
perploug d691e525b3 Adds support for xpath root node selection on mntp
(cherry picked from commit d842f0f5b7)

Conflicts:
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
2014-01-31 11:38:20 +01:00
perploug 02d9d42ae2 adds getByQuery to entityService
(cherry picked from commit 8258619055)

Conflicts:
	src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js
	src/Umbraco.Web/Editors/EntityController.cs
2014-01-31 11:38:19 +01:00
perploug 17838e044c Addss template clearing when in debugmode
(cherry picked from commit 7d2f6c13c3)
2014-01-31 11:38:18 +01:00
Stephan 73173f92d6 U4-4144 - fix 2014-01-31 10:33:23 +01:00
Stephan 2ab1cf59a6 U4-2317 - issue with domains & languages management 2014-01-30 16:19:09 +01:00
Stephan 56cd1cee81 U4-4160 - make sure string properties are returned as strings 2014-01-30 15:08:13 +01:00
Stephan 002988ce86 U4-4144 - Media Cache dies due to new 'key' property in XML 2014-01-30 08:48:35 +01:00
perploug 81c32716fe Removes pre-checkpassword check 2014-01-29 22:04:37 +01:00
Shannon c2f34cefb5 Merge branch '7.0.2' of https://github.com/rsoeteman/Umbraco-CMS into rsoeteman-7.0.2 2014-01-29 11:26:05 +11:00
Shannon 2f7727af68 Fixes: U4-3894 Date picker with time resets to "måndag januari 1, 0001" on Republish entire site 2014-01-29 11:20:25 +11:00
Shannon 5a9874bfad Fixes U4-3894 Date picker with time resets to "måndag januari 1, 0001" on Republish entire site 2014-01-29 11:19:59 +11:00
Shannon 68b4a493c6 updates versions and port 2014-01-29 09:46:25 +11:00
Shannon 6338d57959 Cherry picked - Removes hard coded api url from rte embed 2014-01-29 09:34:07 +11:00
Shannon 7de1b2d09d Fixes ServerVariablesParser to have a proper event declared! :P 2014-01-29 09:33:14 +11:00
Richard Soeteman 06ae6ad15e Fix media.save throws an error in Umbraco 7.0.x
See http://issues.umbraco.org/issue/U4-3928 width and Height properties
are assigned on the file media types.  This was because of always
assigning a value to
content.getProperty(uploadFieldConfigNode.WidthFieldAlias).Value

Added an if statement to make sure the media item is an image when
assigning those values.
2014-01-27 10:15:14 +01:00
Shandem 81dac97917 Merge pull request #284 from markvantilburg/patch-1
Update booting.aspx
2014-01-23 17:33:22 -08:00
markvantilburg 4a8a09c78a Update booting.aspx
Throw the exception immediately if the parameter is not there or empty.

If the parameter is not there it's defaulted to the current url, and this will redirect to itself and create an endless loop here.
2014-01-13 11:33:24 +01:00
30 changed files with 399 additions and 188 deletions
+1
View File
@@ -107,3 +107,4 @@ src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/umbraco/plugins/*
src/Umbraco.Web.UI/umbraco/js/init.js
build/ApiDocs/*
+1 -1
View File
@@ -1,5 +1,5 @@
@ECHO OFF
SET release=7.0.2
SET release=7.0.3
SET comment=
SET version=%release%
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Configuration
int oldVersion;
int.TryParse(versionAttribute.Value, out oldVersion);
var newVersion = oldVersion + 1;
var newVersion = oldVersion + 100;
versionAttribute.SetValue(newVersion);
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.0.2");
private static readonly Version Version = new Version("7.0.3");
/// <summary>
/// Gets the current version of Umbraco.
+15 -2
View File
@@ -292,7 +292,20 @@ namespace Umbraco.Core
else if (destinationType == typeof(DateTime))
{
DateTime value;
return DateTime.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
if (DateTime.TryParse(input, out value))
{
switch (value.Kind)
{
case DateTimeKind.Unspecified:
case DateTimeKind.Utc:
return Attempt<object>.Succeed(value);
case DateTimeKind.Local:
return Attempt<object>.Succeed(value.ToUniversalTime());
default:
throw new ArgumentOutOfRangeException();
}
}
return Attempt<object>.Fail();
}
else if (destinationType == typeof(DateTimeOffset))
{
@@ -526,7 +539,7 @@ namespace Umbraco.Core
if (type == typeof(bool)) return XmlConvert.ToString((bool)value);
if (type == typeof(byte)) return XmlConvert.ToString((byte)value);
if (type == typeof(char)) return XmlConvert.ToString((char)value);
if (type == typeof(DateTime)) return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
if (type == typeof(DateTime)) return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.Unspecified);
if (type == typeof(DateTimeOffset)) return XmlConvert.ToString((DateTimeOffset)value);
if (type == typeof(decimal)) return XmlConvert.ToString((decimal)value);
if (type == typeof(double)) return XmlConvert.ToString((double)value);
@@ -26,13 +26,14 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
if (source == null) return DateTime.MinValue;
// in XML a DateTime is: string - format "yyyy-MM-ddTHH:mm:ss"
// Actually, not always sometimes it is formatted in UTC style with 'Z' suffixed on the end but that is due to this bug:
// http://issues.umbraco.org/issue/U4-4145, http://issues.umbraco.org/issue/U4-3894
// We should just be using TryConvertTo instead.
var sourceString = source as string;
if (sourceString != null)
{
DateTime value;
return DateTime.TryParseExact(sourceString, "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out value)
? value
: DateTime.MinValue;
var attempt = sourceString.TryConvertTo<DateTime>();
return attempt.Success == false ? DateTime.MinValue : attempt.Result;
}
// in the database a DateTime is: DateTime
@@ -47,7 +48,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public override object ConvertSourceToXPath(PublishedPropertyType propertyType, object source, bool preview)
{
// source should come from ConvertSource and be a DateTime already
return XmlConvert.ToString((DateTime) source, "yyyy-MM-ddTHH:mm:ss");
return XmlConvert.ToString((DateTime)source, XmlDateTimeSerializationMode.Unspecified);
}
}
}
@@ -0,0 +1,38 @@
using System.Linq;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
/// <summary>
/// Ensures that no matter what is selected in (editor), the value results in a string.
/// </summary>
/// <remarks>
/// <para>For more details see issues http://issues.umbraco.org/issue/U4-3776 (MNTP)
/// and http://issues.umbraco.org/issue/U4-4160 (media picker).</para>
/// <para>The cache level is set to .Content because the string is supposed to depend
/// on the source value only, and not on any other content. It is NOT appropriate
/// to use that converter for values whose .ToString() would depend on other content.</para>
/// </remarks>
[DefaultPropertyValueConverter]
[PropertyValueType(typeof(string))]
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
public class MustBeStringValueConverter : PropertyValueConverterBase
{
private static readonly string[] Aliases =
{
Constants.PropertyEditors.MultiNodeTreePickerAlias,
Constants.PropertyEditors.MultipleMediaPickerAlias
};
public override bool IsConverter(PublishedPropertyType propertyType)
{
return Aliases.Contains(propertyType.PropertyEditorAlias);
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null) return null;
return source.ToString();
}
}
}
@@ -711,6 +711,11 @@ namespace Umbraco.Core.Security
var decrypted = DecryptPassword(dbPassword);
return decrypted == password;
case MembershipPasswordFormat.Hashed:
//only triggered when we set the initial installer password
if (dbPassword == "default" && password == dbPassword)
return true;
string salt;
var storedHashedPass = StoredPassword(dbPassword, out salt);
var hashed = EncryptOrHashPassword(password, salt);
+1
View File
@@ -368,6 +368,7 @@
<Compile Include="PropertyEditors\ValueConverters\JsonValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MultipleTextStringValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MarkdownEditorValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MustBeStringValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\TextStringValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\TinyMceValueConverter.cs" />
<Compile Include="PropertyEditors\IPropertyValueConverter.cs" />
+14 -20
View File
@@ -104,30 +104,24 @@ namespace Umbraco.Tests
}
}
[Test]
public virtual void CanConvertStringToDateTime()
[TestCase("2012-11-10", true)]
[TestCase("2012/11/10", true)]
[TestCase("10/11/2012", true)]// assuming your culture uses DD/MM/YYYY
[TestCase("11/10/2012", false)]// assuming your culture uses DD/MM/YYYY
[TestCase("Sat 10, Nov 2012", true)]
[TestCase("Saturday 10, Nov 2012", true)]
[TestCase("Sat 10, November 2012", true)]
[TestCase("Saturday 10, November 2012", true)]
[TestCase("2012-11-10 13:14:15", true)]
[TestCase("2012-11-10T13:14:15Z", true)]
public virtual void CanConvertStringToDateTime(string date, bool outcome)
{
var dateTime = new DateTime(2012, 11, 10, 13, 14, 15);
var testCases = new Dictionary<string, bool>
{
{"2012-11-10", true},
{"2012/11/10", true},
{"10/11/2012", true}, // assuming your culture uses DD/MM/YYYY
{"11/10/2012", false}, // assuming your culture uses DD/MM/YYYY
{"Sat 10, Nov 2012", true},
{"Saturday 10, Nov 2012", true},
{"Sat 10, November 2012", true},
{"Saturday 10, November 2012", true},
{"2012-11-10 13:14:15", true}
};
foreach (var testCase in testCases)
{
var result = testCase.Key.TryConvertTo<DateTime>();
var result = date.TryConvertTo<DateTime>();
Assert.IsTrue(result.Success, testCase.Key);
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), testCase.Value, testCase.Key);
}
Assert.IsTrue(result.Success, date);
Assert.AreEqual(DateTime.Equals(dateTime.Date, result.Result.Date), outcome, date);
}
[Test]
@@ -235,8 +235,9 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
//set the root as the current active tree
scope.activeTree = scope.tree.root;
emitEvent("treeLoaded", { tree: scope.tree.root });
emitEvent("treeLoaded", { tree: scope.tree });
emitEvent("treeNodeExpanded", { tree: scope.tree, node: scope.tree.root, children: scope.tree.root.children });
}, function(reason) {
scope.loading = false;
notificationsService.error("Tree Error", reason);
@@ -99,6 +99,16 @@ function entityResource($q, $http, umbRequestHelper) {
'Failed to retreive entity data for id ' + id);
},
getByQuery: function (query, nodeContextId, type) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetByQuery",
[{query: query},{ nodeContextId: nodeContextId}, {type: type }])),
'Failed to retreive entity data for query ' + query);
},
/**
* @ngdoc method
* @name umbraco.resources.entityResource#getByIds
+9
View File
@@ -47,6 +47,15 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService',
$location.path(rejection.path).search(rejection.search);
});
/** For debug mode, always clear template cache to cut down on
dev frustration and chrome cache on templates */
if(Umbraco.Sys.ServerVariables.isDebuggingEnabled){
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
});
}
/* this will initialize the navigation service once the application has started */
navigationService.init();
@@ -1,4 +1,4 @@
angular.module("umbraco").controller("Umbraco.Dialogs.RteEmbedController", function ($scope, $http) {
angular.module("umbraco").controller("Umbraco.Dialogs.RteEmbedController", function ($scope, $http, umbRequestHelper) {
$scope.form = {};
$scope.form.url = "";
$scope.form.width = 360;
@@ -20,7 +20,7 @@
$scope.form.info = "";
$scope.form.success = false;
$http({ method: 'GET', url: '/umbraco/UmbracoApi/RteEmbed/GetEmbed', params: { url: $scope.form.url, width: $scope.form.width, height: $scope.form.height } })
$http({ method: 'GET', url: umbRequestHelper.getApiUrl("embedApiBaseUrl", "GetEmbed"), params: { url: $scope.form.url, width: $scope.form.width, height: $scope.form.height } })
.success(function (data) {
$scope.form.preview = "";
@@ -40,11 +40,11 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
//Configures filtering
if (dialogOptions.filter) {
dialogOptions.filterExclude = true;
dialogOptions.filterExclude = false;
dialogOptions.filterAdvanced = false;
if(dialogOptions.filter[0] === "!"){
dialogOptions.filterExclude = false;
dialogOptions.filterExclude = true;
dialogOptions.filter = dialogOptions.filter.substring(1);
}
@@ -112,8 +112,10 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
angular.forEach(nodes, function (value, key) {
var found = a.indexOf(value.metaData.contentType) >= 0;
if ((dialogOptions.filterExclude && found) || !found) {
value.filtered = true;
if (!dialogOptions.filterExclude && !found || dialogOptions.filterExclude && found){
value.filtered = true;
if(dialogOptions.filterCssClass){
value.cssClasses.push(dialogOptions.filterCssClass);
}
@@ -37,10 +37,13 @@ angular.module('umbraco')
};
$scope.clear = function() {
$scope.model.value.id = undefined;
$scope.node = undefined;
$scope.model.value.id = undefined;
$scope.node = undefined;
$scope.model.value.query = undefined;
};
//we always need to ensure we dont submit anything broken
$scope.$on("formSubmitting", function (ev, args) {
if($scope.model.value.type === "member"){
$scope.model.value.id = -1;
@@ -1,30 +1,77 @@
<div ng-controller="Umbraco.PrevalueEditors.TreeSourceController" class="umb-editor umb-contentpicker">
<select ng-model="model.value.type">
<select ng-model="model.value.type" class="umb-editor" ng-change="clear()">
<option value="content">Content</option>
<option value="media">Media</option>
<option value="member">Members</option>
</select>
<br/><br/>
<ul class="unstyled list-icons" ng-if="node" style="margin-top: 30px">
<li>
<i class="icon icon-delete red hover-show pull-right" ng-click="clear()"></i>
<i class="icon {{node.icon}} hover-hide"></i>
<a href prevent-default ng-click="openContentPicker()" >{{node.name}}</a>
</li>
</ul>
<div ng-hide="model.value.type === 'member'">
<ul class="unstyled list-icons" ng-if="node" >
<li>
<i class="icon icon-delete red hover-show pull-right" ng-click="clear()"></i>
<i class="icon {{node.icon}} hover-hide"></i>
<a href prevent-default ng-click="openContentPicker()" >{{node.name}}</a>
</li>
</ul>
<div ng-if="!node && model.value.type !== 'member'" style="margin-top: 30px">
<span ng-hide="showSearch || model.value.query">
<ul class="unstyled list-icons">
<li>
<i class="icon icon-add blue"></i>
<a href ng-click="openContentPicker()" prevent-default>
<localize key="general_choose">Choose a root node</localize>...
</a>
</li>
<li ng-show="model.value.type == 'content'">
<i class="icon icon-search"></i>
<a href ng-click="showSearch = true">Query for root node with xpath</a>
</li>
</ul>
</span>
<ul class="unstyled list-icons" ng-show="multipicker || !node">
<li ng-hide="showSearch">
<i class="icon icon-add blue"></i>
<a href ng-click="openContentPicker()" prevent-default>
<localize key="general_choose">Choose</localize>...
</a>
</li>
</ul>
<span ng-show="showSearch || model.value.query">
<input type="text"
ng-model="model.value.query"
class="umb-editor umb-textstring"
placeholder="Enter xpath query">
<ul class="unstyled list-icons" style="margin-top: 15px">
<li style="max-width: 600px">
<i class="icon icon-help-alt"></i>
<a href ng-click="showHelp = 1" prevent-default>
Show xpath query help
</a>
<small ng-if="showHelp">
<p>
Use Xpath query to set a root node on the tree, either based on a search from the root of the content tree, or by using a context-aware placeholder.
</p>
<p>
Placeholders finds the nearest published ID and runs its query from there. so for instance:
<pre>$parent/newsArticle</pre>
Will try to get the parent if available, but will then fall back to the nearest ancestor and query for all news articles there.
</p>
<p>
Available placeholders: <br/>
<code>$current</code>: current page or closest found ancestor<br/>
<code>$parent</code>: parent page or closest found ancestor<br/>
<code>$root</code>: root of the content tree<br/>
<code>$site</code>: Ancestor node at level 1 <br/>
</p>
</small>
</li>
<li>
<i class="icon icon-delete red"></i>
<a href ng-click="showSearch = false; model.value.query = ''"> Cancel and clear query</a>
</li>
</ul>
</span>
</div>
</div>
@@ -2,69 +2,80 @@
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco')
.controller("Umbraco.PropertyEditors.ContentPickerController",
function($scope, dialogService, entityResource, $log, iconHelper){
$scope.renderModel = [];
$scope.ids = $scope.model.value ? $scope.model.value.split(',') : [];
//configuration
$scope.cfg = {
multiPicker: "0",
entityType: "Document",
startNode:{
type: "content",
id: -1
}
};
if($scope.model.config){
$scope.cfg = angular.extend($scope.cfg, $scope.model.config);
}
function ($scope, dialogService, entityResource, editorState, $log, iconHelper, $routeParams) {
$scope.renderModel = [];
$scope.ids = $scope.model.value ? $scope.model.value.split(',') : [];
//configuration
$scope.cfg = {
multiPicker: "0",
entityType: "Document",
filterCssClass: "not-allowed not-published",
startNode: {
query: "",
type: "content",
id: -1
}
};
if ($scope.model.config) {
$scope.cfg = angular.extend($scope.cfg, $scope.model.config);
}
//Umbraco persists boolean for prevalues as "0" or "1" so we need to convert that!
$scope.cfg.multiPicker = ($scope.cfg.multiPicker === "0" ? false : true);
$scope.cfg.multiPicker = ($scope.cfg.multiPicker === "0" ? false : true);
if($scope.cfg.startNode.type === "member"){
$scope.cfg.entityType = "Member";
}
else if ($scope.cfg.startNode.type === "media") {
$scope.cfg.entityType = "Media";
}
if ($scope.cfg.startNode.type === "member") {
$scope.cfg.entityType = "Member";
}
else if ($scope.cfg.startNode.type === "media") {
$scope.cfg.entityType = "Media";
}
$scope.cfg.callback = populate;
$scope.cfg.treeAlias = $scope.cfg.startNode.type;
$scope.cfg.section = $scope.cfg.startNode.type;
$scope.cfg.startNodeId = $scope.cfg.startNode.id;
$scope.cfg.filterCssClass = "not-allowed not-published";
//load current data
entityResource.getByIds($scope.ids, $scope.cfg.entityType).then(function(data){
_.each(data, function (item, i) {
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon});
});
});
//if we have a query for the startnode, we will use that.
if ($scope.cfg.startNode.query) {
var rootId = $routeParams.id;
entityResource.getByQuery($scope.cfg.startNode.query, rootId, "Document").then(function (ent) {
$scope.cfg.startNodeId = ent.id;
});
} else {
$scope.cfg.startNodeId = $scope.cfg.startNode.id;
}
$scope.cfg.callback = populate;
$scope.cfg.treeAlias = $scope.cfg.startNode.type;
$scope.cfg.section = $scope.cfg.startNode.type;
//load current data
entityResource.getByIds($scope.ids, $scope.cfg.entityType).then(function (data) {
_.each(data, function (item, i) {
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon });
});
});
//dialog
$scope.openContentPicker =function(){
var d = dialogService.treePicker($scope.cfg);
};
//dialog
$scope.openContentPicker = function () {
var d = dialogService.treePicker($scope.cfg);
};
$scope.remove =function(index){
$scope.renderModel.splice(index, 1);
};
$scope.remove = function (index) {
$scope.renderModel.splice(index, 1);
};
$scope.add =function(item){
if($scope.ids.indexOf(item.id) < 0){
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.renderModel.push({name: item.name, id: item.id, icon: item.icon});
}
};
$scope.add = function (item) {
if ($scope.ids.indexOf(item.id) < 0) {
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
$scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon });
}
};
$scope.clear = function() {
$scope.clear = function () {
$scope.renderModel = [];
};
@@ -72,10 +83,10 @@ angular.module('umbraco')
// because the ui-sortable doesn't dispatch an event after the digest of the sort operation. Any of the events for UI sortable
// occur after the DOM has updated but BEFORE the digest has occured so the model has NOT changed yet - it even states so in the docs.
// In their source code there is no event so we need to just subscribe to our model changes here.
//This also makes it easier to manage models, we update one and the rest will just work.
$scope.$watch(function() {
//This also makes it easier to manage models, we update one and the rest will just work.
$scope.$watch(function () {
//return the joined Ids as a string to watch
return _.map($scope.renderModel, function(i) {
return _.map($scope.renderModel, function (i) {
return i.id;
}).join();
}, function (newVal) {
@@ -86,22 +97,22 @@ angular.module('umbraco')
});
$scope.$on("formSubmitting", function (ev, args) {
$scope.model.value = trim($scope.ids.join(), ",");
$scope.model.value = trim($scope.ids.join(), ",");
});
function trim(str, chr) {
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^'+chr+'+|'+chr+'+$', 'g');
return str.replace(rgxtrim, '');
}
function trim(str, chr) {
var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^' + chr + '+|' + chr + '+$', 'g');
return str.replace(rgxtrim, '');
}
function populate(data){
if(angular.isArray(data)){
_.each(data, function (item, i) {
$scope.add(item);
});
}else{
$scope.clear();
$scope.add(data);
}
}
});
function populate(data) {
if (angular.isArray(data)) {
_.each(data, function (item, i) {
$scope.add(item);
});
} else {
$scope.clear();
$scope.add(data);
}
}
});
@@ -23,5 +23,4 @@
</a>
</li>
</ul>
</div>
+2 -2
View File
@@ -2643,9 +2643,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7020</DevelopmentServerPort>
<DevelopmentServerPort>7030</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7020</IISUrl>
<IISUrl>http://localhost:7030</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -2,7 +2,7 @@
<%
// NH: Adds this inline check to avoid a simple codebehind file in the legacy project!
if (!umbraco.cms.helpers.url.ValidateProxyUrl(Request["url"], Request.Url.AbsoluteUri))
if (Request["url"].ToLower().Contains("booting.aspx") || !umbraco.cms.helpers.url.ValidateProxyUrl(Request["url"], Request.Url.AbsoluteUri))
{
throw new ArgumentException("Can't redirect to the requested url - it's not local or an approved proxy url",
"url");
@@ -110,6 +110,10 @@ namespace Umbraco.Web.Editors
{"manifestAssetList", Url.Action("GetManifestAssetList", "BackOffice")},
{"serverVarsJs", Url.Action("Application", "BackOffice")},
//API URLs
{
"embedApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RteEmbedController>(
controller => controller.GetEmbed("",0,0))
},
{
"contentApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<ContentController>(
controller => controller.PostSave(null))
+101
View File
@@ -25,6 +25,7 @@ using Examine;
using Examine.LuceneEngine.SearchCriteria;
using Examine.SearchCriteria;
using Umbraco.Web.Dynamics;
using umbraco;
namespace Umbraco.Web.Editors
{
@@ -128,6 +129,106 @@ namespace Umbraco.Web.Editors
return GetResultForKey(id, type);
}
/// <summary>
/// Gets an entity by a xpath query
/// </summary>
/// <param name="query"></param>
/// <param name="nodeContextId"></param>
/// <param name="type"></param>
/// <returns></returns>
public EntityBasic GetByQuery(string query, int nodeContextId, UmbracoEntityTypes type)
{
if (type != UmbracoEntityTypes.Document)
throw new ArgumentException("Get by query is only compatible with enitities of type Document");
var q = ParseXPathQuery(query, nodeContextId);
var node = Umbraco.TypedContentSingleAtXPath(q);
if (node == null)
return null;
return GetById(node.Id, type);
}
//PP: wip in progress on the query parser
private string ParseXPathQuery(string query, int id)
{
//no need to parse it
if (!query.StartsWith("$"))
return query;
//get full path
Func<int, IEnumerable<string>> getPath = delegate(int nodeid){
var ent = Services.EntityService.Get(nodeid);
return ent.Path.Split(',').Reverse();
};
//get nearest published item
Func<IEnumerable<string>, int> getClosestPublishedAncestor = (path =>
{
foreach (var _id in path)
{
var item = Umbraco.TypedContent(int.Parse(_id));
if (item != null)
return item.Id;
}
return -1;
});
var rootXpath = "descendant::*[@id={0}]";
//parseable items:
var vars = new Dictionary<string, Func<string, string>>();
vars.Add("$current", q => {
var _id = getClosestPublishedAncestor(getPath(id));
return q.Replace("$current", string.Format(rootXpath, _id));
});
vars.Add("$parent", q =>
{
//remove the first item in the array if its the current node
//this happens when current is published, but we are looking for its parent specifically
var path = getPath(id);
if(path.ElementAt(0) == id.ToString()){
path = path.Skip(1);
}
var _id = getClosestPublishedAncestor(path);
return q.Replace("$parent", string.Format(rootXpath, _id));
});
vars.Add("$site", q =>
{
var _id = getClosestPublishedAncestor(getPath(id));
return q.Replace("$site", string.Format(rootXpath, _id) + "/ancestor-or-self::*[@level = 1]");
});
vars.Add("$root", q =>
{
return q.Replace("$root", string.Empty);
});
foreach (var varible in vars)
{
if (query.StartsWith(varible.Key))
{
query = varible.Value.Invoke(query);
break;
}
}
return query;
}
public EntityBasic GetById(int id, UmbracoEntityTypes type)
{
return GetResultForId(id, type);
@@ -1,29 +0,0 @@
using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors.ValueConverters
{
/// <summary>
/// Ensures that no matter what is selected in MNTP that the value results in a string
/// </summary>
/// <remarks>
/// See here for full details:http://issues.umbraco.org/issue/U4-3776
/// </remarks>
[DefaultPropertyValueConverter]
[PropertyValueType(typeof (string))]
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Request)]
public class MntpStringValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
{
return propertyType.PropertyEditorAlias == Constants.PropertyEditors.MultiNodeTreePickerAlias;
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null) return null;
return source.ToString();
}
}
}
@@ -478,6 +478,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
// I'm not sure that _properties contains all properties including those without a value,
// neither that GetProperty will return a property without a value vs. null... @zpqrtbnk
// List of properties that will appear in the XML and do not match
// anything in the ContentType, so they must be ignored.
private static readonly string[] IgnoredKeys = { "version", "isDoc", "key" };
public DictionaryPublishedContent(
IDictionary<string, string> valueDictionary,
Func<DictionaryPublishedContent, IPublishedContent> getParent,
@@ -528,8 +532,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
{
IPublishedProperty property = null;
// must ignore that one
if (i.Key == "version" || i.Key == "isDoc") continue;
// must ignore those
if (IgnoredKeys.Contains(i.Key)) continue;
if (i.Key.InvariantStartsWith("__"))
{
@@ -540,6 +544,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
{
// use property type to ensure proper conversion
var propertyType = _contentType.GetPropertyType(i.Key);
if (propertyType == null)
throw new Exception("Internal error, property '" + i.Key + "' is not a valid property for that type of content.");
property = new XmlPublishedProperty(propertyType, false, i.Value); // false :: never preview a media
}
@@ -81,10 +81,15 @@ namespace Umbraco.Web.Strategies.DataTypes
var dimensions = isImageType ? GetDimensions(path, fileSystem) : null;
// only add dimensions to web images
content.getProperty(uploadFieldConfigNode.WidthFieldAlias).Value = isImageType ? dimensions.Item1.ToString(CultureInfo.InvariantCulture) : string.Empty;
content.getProperty(uploadFieldConfigNode.HeightFieldAlias).Value = isImageType ? dimensions.Item2.ToString(CultureInfo.InvariantCulture) : string.Empty;
content.getProperty(uploadFieldConfigNode.LengthFieldAlias).Value = size == default(long) ? string.Empty : size.ToString(CultureInfo.InvariantCulture);
if (isImageType)
{
// only add dimensions to web images
content.getProperty(uploadFieldConfigNode.WidthFieldAlias).Value = dimensions.Item1.ToString(CultureInfo.InvariantCulture);
content.getProperty(uploadFieldConfigNode.HeightFieldAlias).Value = dimensions.Item2.ToString(CultureInfo.InvariantCulture);
}
content.getProperty(uploadFieldConfigNode.LengthFieldAlias).Value = size == default(long) ? string.Empty : size.ToString(CultureInfo.InvariantCulture);
content.getProperty(uploadFieldConfigNode.ExtensionFieldAlias).Value = string.IsNullOrEmpty(extension) ? string.Empty : extension;
}
@@ -10,7 +10,7 @@ namespace Umbraco.Web.UI.JavaScript
/// <summary>
/// Could allow developers to add custom variables on startup
/// </summary>
public static EventHandler<Dictionary<string, object>> Parsing;
public static event EventHandler<Dictionary<string, object>> Parsing;
internal const string Token = "##Variables##";
@@ -24,7 +24,8 @@ namespace Umbraco.Web.UI.JavaScript
}
var json = JObject.FromObject(items);
return vars.Replace(Token, json.ToString());
return vars.Replace(Token, json.ToString());
}
}
-1
View File
@@ -397,7 +397,6 @@
<Compile Include="PropertyEditors\TagsPropertyEditor.cs" />
<Compile Include="PropertyEditors\UploadFileTypeValidator.cs" />
<Compile Include="PropertyEditors\UserPickerPropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueConverters\MntpStringValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\RelatedLinksEditorValueConvertor.cs" />
<Compile Include="PropertyEditors\ValueListPreValueEditor.cs" />
<Compile Include="PropertyEditors\DropDownPropertyEditor.cs" />
@@ -64,12 +64,14 @@ namespace Umbraco.Web.WebServices
// process domains
foreach (var domain in domains.Where(d => model.Domains.All(m => !m.Name.Equals(d.Name, StringComparison.OrdinalIgnoreCase))))
// delete every (non-wildcard) domain, that exists in the DB yet is not in the model
foreach (var domain in domains.Where(d => d.IsWildcard == false && model.Domains.All(m => m.Name.Equals(d.Name, StringComparison.OrdinalIgnoreCase) == false)))
domain.Delete();
var names = new List<string>();
foreach (var domainModel in model.Domains.Where(m => !string.IsNullOrWhiteSpace(m.Name)))
// create or update domains in the model
foreach (var domainModel in model.Domains.Where(m => string.IsNullOrWhiteSpace(m.Name) == false))
{
language = languages.FirstOrDefault(l => l.id == domainModel.Lang);
if (language == null)
@@ -90,7 +92,7 @@ namespace Umbraco.Web.WebServices
Domain.MakeNew(name, model.NodeId, domainModel.Lang);
}
model.Valid = model.Domains.All(m => !m.Duplicate);
model.Valid = model.Domains.All(m => m.Duplicate == false);
return model;
}
@@ -497,19 +497,6 @@ namespace umbraco.providers
return false;
}
//Due to the way this legacy provider worked, when it 'validated' a password passed in, it would allow
// having the already hashed/encrypted password checked directly - this is bad but hey, we gotta support legacy
// don't we.
//So, first we'll check if the user object's db stored password (already hashed/encrypted in the db) matches the password that
// has been passed in, if so then we will confirm that it is valid. If it doesn't we'll attempt to hash/encrypt the passed in
// password and then validate it - the way it is supposed to be done.
if (user.Password == password)
{
return true;
}
return CheckPassword(password, user.Password);
}
}