Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d052aeeac | |||
| 9b33c8a0e2 | |||
| 967178cb92 | |||
| fe44494936 | |||
| 793c9470c2 | |||
| 98b7467306 | |||
| 4bb75d73dd | |||
| dd8e43d80a | |||
| b4a0dadee9 | |||
| 014ac98d0b | |||
| 35a79a8598 | |||
| 3c4f052a27 | |||
| 97d7e3db84 | |||
| 0d2df4de81 | |||
| e2e0dd0c73 | |||
| 1a590664e7 | |||
| 64fd6ee7c5 | |||
| 2ed5b6c1ee | |||
| edf7038848 | |||
| bcac02861d | |||
| 79ecaecc9e | |||
| f604117c6d | |||
| dcf7f35078 | |||
| 2aa0dfb2c5 | |||
| e4b77416a6 | |||
| 3aed889e2a | |||
| 2c6e7e46c2 | |||
| 0a71a09d21 | |||
| 0c868fb72d | |||
| a96cbce9b1 | |||
| 5f3090c81e | |||
| 054a8b48fa | |||
| dfbc3c477a | |||
| 57426ae895 | |||
| b4aad19573 | |||
| 03012cf54d | |||
| 7ff339e18a | |||
| 0048b9c4c8 | |||
| 47f5e6bf17 | |||
| a8908c90bc | |||
| 9e5e8b539a | |||
| 45d292e196 | |||
| 6bafd3a254 | |||
| 564074a2bd | |||
| 4161d244c1 | |||
| 171e0d87db | |||
| eea87e411f | |||
| 89edfe5782 | |||
| cbd5071eed | |||
| 3dbc2944aa | |||
| 709dab6afd | |||
| 8749b030cf | |||
| 62fd15d54b | |||
| 66e71db85c | |||
| 469527da0a | |||
| 304e574bbc | |||
| 723644ace5 | |||
| 2b936a6d31 | |||
| 3121635e07 | |||
| f2a3a269ba | |||
| 557fc1bcdd | |||
| 617bdb2bd1 | |||
| 2c91f9bf14 | |||
| 1a5fe63638 | |||
| dfb0efbc98 | |||
| d399ad6e51 | |||
| eb06e62937 | |||
| 728bf8b52d | |||
| ca74100e12 | |||
| 3061dc4e6f | |||
| 5166dc08d6 | |||
| 05a9c44e9e | |||
| 8e0565e030 | |||
| ceb3ae361a | |||
| 4cee7b831a | |||
| f146262031 | |||
| ddae0d01e3 | |||
| b9ee85dabc | |||
| 29fa6061a9 | |||
| 8ee61312b6 | |||
| cfd4b8c7bf | |||
| 7ce3b6046c | |||
| 43d98c9682 | |||
| 62e4825a5e | |||
| 81d35c6079 | |||
| 7e15077f96 | |||
| 6543e3c058 | |||
| 7c73c379cf | |||
| 4bc9d96bce | |||
| 45fd54d046 | |||
| 4f062306a6 | |||
| 4a8730b925 | |||
| 0beda4b790 | |||
| d06b7edd84 | |||
| 466de5ee0b | |||
| 976e1e8a35 | |||
| da0a1c808a | |||
| 08965982fd | |||
| 732d3ef326 | |||
| 7019c9433b | |||
| b37197f66a | |||
| b2004057a5 | |||
| 3f1f67e323 | |||
| f1d37a5072 | |||
| 2dc6e395a8 | |||
| eedeb90673 | |||
| 977c390a95 |
+34
-1
@@ -24,6 +24,7 @@ Remember, we're a friendly bunch and are happy with whatever contribution you mi
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
[How do I even begin?](#how-do-i-even-begin)
|
||||
|
||||
@@ -114,6 +115,15 @@ Some parts of our source code is over 10 years old now. And when we say "old", w
|
||||
There's two big areas that you should know about:
|
||||
|
||||
1. The Umbraco backoffice is a extensible AngularJS app and requires you to run a `gulp dev` command while you're working with it, so changes are copied over to the appropriate directories and you can refresh your browser to view the results of your changes.
|
||||
You may need to run the following commands to set up gulp properly:
|
||||
```
|
||||
npm cache clean
|
||||
npm install -g bower
|
||||
npm install -g gulp
|
||||
npm install -g gulp-cli
|
||||
npm install
|
||||
gulp build
|
||||
```
|
||||
2. "The rest" is a C# based codebase, with some traces of our WebForms past but mostly ASP.NET MVC based these days. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
|
||||
|
||||
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
|
||||
@@ -137,6 +147,29 @@ Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the commun
|
||||
|
||||
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
|
||||
|
||||
### Keeping your Umbraco fork in sync with the main repository
|
||||
|
||||
We recommend you sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
|
||||
|
||||
Also, if you've submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
|
||||
|
||||
To sync your fork with this original one, you'll have to add the upstream url, you only have to do this once:
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
|
||||
```
|
||||
|
||||
Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/dev-v7
|
||||
```
|
||||
|
||||
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
|
||||
## How do I even begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
@@ -171,4 +204,4 @@ Did something not work as expected? Try leaving a note in the ["Contributing to
|
||||
|
||||
## Credits
|
||||
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
|
||||
@@ -30,7 +30,7 @@ As an Open Source platform, Umbraco is more than just a CMS. We are transparent
|
||||
|
||||
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
|
||||
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Xloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ function Get-UmbracoBuildEnv
|
||||
# store tools in the module's directory
|
||||
# and cache them for two days
|
||||
$path = "$PSScriptRoot\temp"
|
||||
$src = "$PSScriptRoot\..\..\..\src"
|
||||
$cache = 2
|
||||
|
||||
if (-not (test-path $path))
|
||||
@@ -37,7 +38,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $sevenZip))
|
||||
{
|
||||
Write-Host "Download 7-Zip..."
|
||||
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install 7-Zip.CommandLine -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
|
||||
$file = ls -path "$dir" -name 7za.exe -recurse
|
||||
$file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
|
||||
@@ -54,7 +55,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $vswhere))
|
||||
{
|
||||
Write-Host "Download VsWhere..."
|
||||
&$nuget install vswhere -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install vswhere -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\vswhere.*" | sort -property Name -descending | select -first 1
|
||||
$file = ls -path "$dir" -name vswhere.exe -recurse
|
||||
mv "$dir\$file" $vswhere
|
||||
@@ -70,7 +71,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $semver))
|
||||
{
|
||||
Write-Host "Download Semver..."
|
||||
&$nuget install semver -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install semver -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\semver.*" | sort -property Name -descending | select -first 1
|
||||
$file = "$dir\lib\net452\Semver.dll"
|
||||
if (-not (test-path $file))
|
||||
|
||||
@@ -445,7 +445,7 @@ function Restore-NuGet
|
||||
Write-Host ">> Restore NuGet"
|
||||
Write-Host "Logging to $tmp\nuget.restore.log"
|
||||
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" > "$tmp\nuget.restore.log"
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" -configfile "$src\NuGet.config" > "$tmp\nuget.restore.log"
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR 7.7 UPGRADES ***
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.9.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.9.2")]
|
||||
[assembly: AssemblyFileVersion("7.9.4")]
|
||||
[assembly: AssemblyInformationalVersion("7.9.4")]
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.9.2");
|
||||
private static readonly Version Version = new Version("7.9.4");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -140,8 +140,7 @@ namespace Umbraco.Core
|
||||
if (underlying != null)
|
||||
{
|
||||
// Special case for empty strings for bools/dates which should return null if an empty string.
|
||||
var inputString = input as string;
|
||||
if (inputString != null)
|
||||
if (input is string inputString)
|
||||
{
|
||||
//TODO: Why the check against only bool/date when a string is null/empty? In what scenario can we convert to another type when the string is null or empty other than just being null?
|
||||
if (string.IsNullOrEmpty(inputString) && (underlying == typeof(DateTime) || underlying == typeof(bool)))
|
||||
@@ -168,8 +167,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
// target is not a generic type
|
||||
|
||||
var inputString = input as string;
|
||||
if (inputString != null)
|
||||
if (input is string inputString)
|
||||
{
|
||||
// Try convert from string, returns an Attempt if the string could be
|
||||
// processed (either succeeded or failed), else null if we need to try
|
||||
@@ -218,8 +216,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
// Re-check convertables since we altered the input through recursion
|
||||
var convertible2 = input as IConvertible;
|
||||
if (convertible2 != null)
|
||||
if (input is IConvertible convertible2)
|
||||
{
|
||||
return Attempt.Succeed(Convert.ChangeType(convertible2, target));
|
||||
}
|
||||
@@ -277,8 +274,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (target == typeof(int))
|
||||
{
|
||||
int value;
|
||||
if (int.TryParse(input, out value))
|
||||
if (int.TryParse(input, out var value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
}
|
||||
@@ -286,30 +282,26 @@ namespace Umbraco.Core
|
||||
// Because decimal 100.01m will happily convert to integer 100, it
|
||||
// makes sense that string "100.01" *also* converts to integer 100.
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
decimal value2;
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out value2), Convert.ToInt32(value2));
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out var value2), Convert.ToInt32(value2));
|
||||
}
|
||||
|
||||
if (target == typeof(long))
|
||||
{
|
||||
long value;
|
||||
if (long.TryParse(input, out value))
|
||||
if (long.TryParse(input, out var value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
}
|
||||
|
||||
// Same as int
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
decimal value2;
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out value2), Convert.ToInt64(value2));
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out var value2), Convert.ToInt64(value2));
|
||||
}
|
||||
|
||||
// TODO: Should we do the decimal trick for short, byte, unsigned?
|
||||
|
||||
if (target == typeof(bool))
|
||||
{
|
||||
bool value;
|
||||
if (bool.TryParse(input, out value))
|
||||
if (bool.TryParse(input, out var value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
}
|
||||
@@ -322,53 +314,42 @@ namespace Umbraco.Core
|
||||
switch (Type.GetTypeCode(target))
|
||||
{
|
||||
case TypeCode.Int16:
|
||||
short value;
|
||||
return Attempt<object>.SucceedIf(short.TryParse(input, out value), value);
|
||||
return Attempt<object>.SucceedIf(short.TryParse(input, out var value), value);
|
||||
|
||||
case TypeCode.Double:
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
double valueD;
|
||||
return Attempt<object>.SucceedIf(double.TryParse(input2, out valueD), valueD);
|
||||
return Attempt<object>.SucceedIf(double.TryParse(input2, out var valueD), valueD);
|
||||
|
||||
case TypeCode.Single:
|
||||
var input3 = NormalizeNumberDecimalSeparator(input);
|
||||
float valueF;
|
||||
return Attempt<object>.SucceedIf(float.TryParse(input3, out valueF), valueF);
|
||||
return Attempt<object>.SucceedIf(float.TryParse(input3, out var valueF), valueF);
|
||||
|
||||
case TypeCode.Char:
|
||||
char valueC;
|
||||
return Attempt<object>.SucceedIf(char.TryParse(input, out valueC), valueC);
|
||||
return Attempt<object>.SucceedIf(char.TryParse(input, out var valueC), valueC);
|
||||
|
||||
case TypeCode.Byte:
|
||||
byte valueB;
|
||||
return Attempt<object>.SucceedIf(byte.TryParse(input, out valueB), valueB);
|
||||
return Attempt<object>.SucceedIf(byte.TryParse(input, out var valueB), valueB);
|
||||
|
||||
case TypeCode.SByte:
|
||||
sbyte valueSb;
|
||||
return Attempt<object>.SucceedIf(sbyte.TryParse(input, out valueSb), valueSb);
|
||||
return Attempt<object>.SucceedIf(sbyte.TryParse(input, out var valueSb), valueSb);
|
||||
|
||||
case TypeCode.UInt32:
|
||||
uint valueU;
|
||||
return Attempt<object>.SucceedIf(uint.TryParse(input, out valueU), valueU);
|
||||
return Attempt<object>.SucceedIf(uint.TryParse(input, out var valueU), valueU);
|
||||
|
||||
case TypeCode.UInt16:
|
||||
ushort valueUs;
|
||||
return Attempt<object>.SucceedIf(ushort.TryParse(input, out valueUs), valueUs);
|
||||
return Attempt<object>.SucceedIf(ushort.TryParse(input, out var valueUs), valueUs);
|
||||
|
||||
case TypeCode.UInt64:
|
||||
ulong valueUl;
|
||||
return Attempt<object>.SucceedIf(ulong.TryParse(input, out valueUl), valueUl);
|
||||
return Attempt<object>.SucceedIf(ulong.TryParse(input, out var valueUl), valueUl);
|
||||
}
|
||||
}
|
||||
else if (target == typeof(Guid))
|
||||
{
|
||||
Guid value;
|
||||
return Attempt<object>.SucceedIf(Guid.TryParse(input, out value), value);
|
||||
return Attempt<object>.SucceedIf(Guid.TryParse(input, out var value), value);
|
||||
}
|
||||
else if (target == typeof(DateTime))
|
||||
{
|
||||
DateTime value;
|
||||
if (DateTime.TryParse(input, out value))
|
||||
if (DateTime.TryParse(input, out var value))
|
||||
{
|
||||
switch (value.Kind)
|
||||
{
|
||||
@@ -388,24 +369,20 @@ namespace Umbraco.Core
|
||||
}
|
||||
else if (target == typeof(DateTimeOffset))
|
||||
{
|
||||
DateTimeOffset value;
|
||||
return Attempt<object>.SucceedIf(DateTimeOffset.TryParse(input, out value), value);
|
||||
return Attempt<object>.SucceedIf(DateTimeOffset.TryParse(input, out var value), value);
|
||||
}
|
||||
else if (target == typeof(TimeSpan))
|
||||
{
|
||||
TimeSpan value;
|
||||
return Attempt<object>.SucceedIf(TimeSpan.TryParse(input, out value), value);
|
||||
return Attempt<object>.SucceedIf(TimeSpan.TryParse(input, out var value), value);
|
||||
}
|
||||
else if (target == typeof(decimal))
|
||||
{
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
decimal value;
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out value), value);
|
||||
return Attempt<object>.SucceedIf(decimal.TryParse(input2, out var value), value);
|
||||
}
|
||||
else if (input != null && target == typeof(Version))
|
||||
{
|
||||
Version value;
|
||||
return Attempt<object>.SucceedIf(Version.TryParse(input, out value), value);
|
||||
return Attempt<object>.SucceedIf(Version.TryParse(input, out var value), value);
|
||||
}
|
||||
|
||||
// E_NOTIMPL IPAddress, BigInteger
|
||||
@@ -690,8 +667,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
|
||||
TypeConverter typeConverter;
|
||||
if (InputTypeConverterCache.TryGetValue(key, out typeConverter))
|
||||
if (InputTypeConverterCache.TryGetValue(key, out TypeConverter typeConverter))
|
||||
{
|
||||
return typeConverter;
|
||||
}
|
||||
@@ -711,8 +687,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
|
||||
TypeConverter typeConverter;
|
||||
if (DestinationTypeConverterCache.TryGetValue(key, out typeConverter))
|
||||
if (DestinationTypeConverterCache.TryGetValue(key, out TypeConverter typeConverter))
|
||||
{
|
||||
return typeConverter;
|
||||
}
|
||||
@@ -730,8 +705,7 @@ namespace Umbraco.Core
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Type GetCachedGenericNullableType(Type type)
|
||||
{
|
||||
Type underlyingType;
|
||||
if (NullableGenericCache.TryGetValue(type, out underlyingType))
|
||||
if (NullableGenericCache.TryGetValue(type, out Type underlyingType))
|
||||
{
|
||||
return underlyingType;
|
||||
}
|
||||
@@ -750,8 +724,7 @@ namespace Umbraco.Core
|
||||
private static bool GetCachedCanAssign(object input, Type source, Type target)
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
bool canConvert;
|
||||
if (AssignableTypeCache.TryGetValue(key, out canConvert))
|
||||
if (AssignableTypeCache.TryGetValue(key, out bool canConvert))
|
||||
{
|
||||
return canConvert;
|
||||
}
|
||||
@@ -770,8 +743,7 @@ namespace Umbraco.Core
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool GetCachedCanConvertToBoolean(Type type)
|
||||
{
|
||||
bool result;
|
||||
if (BoolConvertCache.TryGetValue(type, out result))
|
||||
if (BoolConvertCache.TryGetValue(type, out bool result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
+17
-7
@@ -6,6 +6,7 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZero
|
||||
@@ -343,15 +344,24 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
|
||||
|
||||
if (tables.InvariantContains("umbracoUserType") && tables.InvariantContains("umbracoUser"))
|
||||
{
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_umbracoUser_umbracoUserType_id")))
|
||||
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
{
|
||||
Delete.ForeignKey("FK_umbracoUser_umbracoUserType_id").OnTable("umbracoUser");
|
||||
//In MySql, this will drop the FK according to it's special naming rules
|
||||
Delete.ForeignKey().FromTable("umbracoUser").ForeignColumn("userType").ToTable("umbracoUserType").PrimaryColumn("id");
|
||||
}
|
||||
//This is the super old constraint name of the FK for user type so check this one too
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_user_userType")))
|
||||
else
|
||||
{
|
||||
Delete.ForeignKey("FK_user_userType").OnTable("umbracoUser");
|
||||
}
|
||||
//Delete the FK if it exists before dropping the column
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_umbracoUser_umbracoUserType_id")))
|
||||
{
|
||||
Delete.ForeignKey("FK_umbracoUser_umbracoUserType_id").OnTable("umbracoUser");
|
||||
}
|
||||
//This is the super old constraint name of the FK for user type so check this one too
|
||||
if (constraints.Any(x => x.Item1.InvariantEquals("umbracoUser") && x.Item3.InvariantEquals("FK_user_userType")))
|
||||
{
|
||||
Delete.ForeignKey("FK_user_userType").OnTable("umbracoUser");
|
||||
}
|
||||
}
|
||||
|
||||
Delete.Column("userType").FromTable("umbracoUser");
|
||||
Delete.Table("umbracoUserType");
|
||||
@@ -361,4 +371,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe
|
||||
public override void Down()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using System;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
@@ -14,19 +15,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null) return 0;
|
||||
|
||||
// in XML an integer is a string
|
||||
var sourceString = source as string;
|
||||
if (sourceString != null)
|
||||
{
|
||||
int i;
|
||||
return (int.TryParse(sourceString, out i)) ? i : 0;
|
||||
}
|
||||
|
||||
// in the database an integer is an integer
|
||||
// default value is zero
|
||||
return (source is int) ? source : 0;
|
||||
return source.TryConvertTo<int>().Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,15 +37,15 @@ namespace Umbraco.Core.Security
|
||||
var username = identity.GetUserName();
|
||||
var session = identity.FindFirstValue(Constants.Security.SessionIdClaimType);
|
||||
var securityStamp = identity.FindFirstValue(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType);
|
||||
var startContentId = identity.FindFirstValue(Constants.Security.StartContentNodeIdClaimType);
|
||||
var startContentId = identity.FindFirstValue(Constants.Security.StartContentNodeIdClaimType);
|
||||
var startMediaId = identity.FindFirstValue(Constants.Security.StartMediaNodeIdClaimType);
|
||||
|
||||
var culture = identity.FindFirstValue(ClaimTypes.Locality);
|
||||
var id = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var id = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var realName = identity.FindFirstValue(ClaimTypes.GivenName);
|
||||
|
||||
if (username == null || startContentId == null || startMediaId == null
|
||||
|| culture == null || id == null
|
||||
if (username == null || startContentId == null || startMediaId == null
|
||||
|| culture == null || id == null
|
||||
|| realName == null || session == null)
|
||||
throw new InvalidOperationException("Cannot create a " + typeof(UmbracoBackOfficeIdentity) + " from " + typeof(ClaimsIdentity) + " since there are missing required claims");
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Umbraco.Core.Security
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create a " + typeof(UmbracoBackOfficeIdentity) + " from " + typeof(ClaimsIdentity) + " since the data is not formatted correctly - either content or media start Ids could not be parsed as JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
var roles = identity.FindAll(x => x.Type == DefaultRoleClaimType).Select(role => role.Value).ToList();
|
||||
var allowedApps = identity.FindAll(x => x.Type == Constants.Security.AllowedApplicationsClaimType).Select(app => app.Value).ToList();
|
||||
@@ -165,7 +165,7 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
foreach (var claim in claimsIdentity.Claims)
|
||||
{
|
||||
//In one special case we will replace a claim if it exists already and that is the
|
||||
//In one special case we will replace a claim if it exists already and that is the
|
||||
// Forms auth claim for name which automatically gets added
|
||||
TryRemoveClaim(FindFirst(x => x.Type == claim.Type && x.Issuer == "Forms"));
|
||||
|
||||
@@ -187,15 +187,15 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
ClaimTypes.NameIdentifier, //id
|
||||
ClaimTypes.Name, //username
|
||||
ClaimTypes.GivenName,
|
||||
ClaimTypes.GivenName,
|
||||
Constants.Security.StartContentNodeIdClaimType,
|
||||
Constants.Security.StartMediaNodeIdClaimType,
|
||||
ClaimTypes.Locality,
|
||||
Constants.Security.StartMediaNodeIdClaimType,
|
||||
ClaimTypes.Locality,
|
||||
Constants.Security.SessionIdClaimType,
|
||||
Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds claims based on the UserData data
|
||||
@@ -222,23 +222,19 @@ namespace Umbraco.Core.Security
|
||||
AddClaim(new Claim(ClaimTypes.Locality, Culture, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
if (HasClaim(x => x.Type == Constants.Security.SessionIdClaimType) == false && SessionId.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.SessionIdClaimType, SessionId, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
{
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SecurityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SecurityStamp, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
//Add each app as a separate claim
|
||||
if (HasClaim(x => x.Type == Constants.Security.AllowedApplicationsClaimType) == false)
|
||||
{
|
||||
foreach (var application in AllowedApplications)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
AddClaim(new Claim(Constants.Security.AllowedApplicationsClaimType, application, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,8 +249,8 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected internal UserData UserData { get; private set; }
|
||||
@@ -332,4 +328,4 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,20 +207,17 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
return repository.GetByUsername(username, includeSecurityData: true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (DbException ex)
|
||||
{
|
||||
if (ex is SqlException || ex is SqlCeException)
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
//NOTE: this will not be cached
|
||||
return repository.GetByUsername(username, includeSecurityData: false);
|
||||
}
|
||||
//NOTE: this will not be cached
|
||||
return repository.GetByUsername(username, includeSecurityData: false);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
@@ -789,20 +786,17 @@ namespace Umbraco.Core.Services
|
||||
var result = repository.Get(id);
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (DbException ex)
|
||||
{
|
||||
if (ex is SqlException || ex is SqlCeException)
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
//we need to handle this one specific case which is when we are upgrading to 7.7 since the user group
|
||||
//tables don't exist yet. This is the 'easiest' way to deal with this without having to create special
|
||||
//version checks in the BackOfficeSignInManager and calling into other special overloads that we'd need
|
||||
//like "GetUserById(int id, bool includeSecurityData)" which may cause confusion because the result of
|
||||
//that method would not be cached.
|
||||
if (ApplicationContext.Current.IsUpgrading)
|
||||
{
|
||||
//NOTE: this will not be cached
|
||||
return repository.Get(id, includeSecurityData: false);
|
||||
}
|
||||
//NOTE: this will not be cached
|
||||
return repository.Get(id, includeSecurityData: false);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -142,10 +143,18 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
internal static bool IsClientSideRequest(this Uri url)
|
||||
{
|
||||
var ext = Path.GetExtension(url.LocalPath);
|
||||
if (ext.IsNullOrWhiteSpace()) return false;
|
||||
var toInclude = new[] { ".aspx", ".ashx", ".asmx", ".axd", ".svc" };
|
||||
return toInclude.Any(ext.InvariantEquals) == false;
|
||||
try
|
||||
{
|
||||
var ext = Path.GetExtension(url.LocalPath);
|
||||
if (ext.IsNullOrWhiteSpace()) return false;
|
||||
var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"};
|
||||
return toInclude.Any(ext.InvariantEquals) == false;
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(UriExtensions), "Failed to determine if request was client side", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -311,4 +320,4 @@ namespace Umbraco.Core
|
||||
return new Uri(uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,53 +93,59 @@ namespace Umbraco.Tests.Routing
|
||||
var result = uri.IsClientSideRequest();
|
||||
Assert.AreEqual(assert, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Client_Side_Request_InvalidPath_ReturnFalse()
|
||||
{
|
||||
//This url is invalid. Default to false when the extension cannot be determined
|
||||
var uri = new Uri("http://test.com/installing-modules+foobar+\"yipee\"");
|
||||
var result = uri.IsClientSideRequest();
|
||||
Assert.AreEqual(false, result);
|
||||
}
|
||||
|
||||
//NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
|
||||
// we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
|
||||
// to ensure that each one is individually tested.
|
||||
|
||||
//[TestCase("/", 1046)]
|
||||
//[TestCase("/home.aspx", 1046)]
|
||||
//[TestCase("/home/sub1.aspx", 1173)]
|
||||
//[TestCase("/home.aspx?altTemplate=blah", 1046)]
|
||||
//public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
|
||||
//{
|
||||
// var httpContextFactory = new FakeHttpContextFactory(url);
|
||||
// var httpContext = httpContextFactory.HttpContext;
|
||||
// var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
|
||||
// var contentStore = new ContentStore(umbracoContext);
|
||||
// var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
// umbracoContext.RoutingContext = new RoutingContext(
|
||||
// new IPublishedContentLookup[] {new LookupByNiceUrl()},
|
||||
// new DefaultLastChanceLookup(),
|
||||
// contentStore,
|
||||
// niceUrls);
|
||||
|
||||
// StateHelper.HttpContext = httpContext;
|
||||
|
||||
//NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
|
||||
// we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
|
||||
// to ensure that each one is individually tested.
|
||||
// //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
|
||||
// //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
|
||||
// Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
|
||||
|
||||
//[TestCase("/", 1046)]
|
||||
//[TestCase("/home.aspx", 1046)]
|
||||
//[TestCase("/home/sub1.aspx", 1173)]
|
||||
//[TestCase("/home.aspx?altTemplate=blah", 1046)]
|
||||
//public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
|
||||
//{
|
||||
// var httpContextFactory = new FakeHttpContextFactory(url);
|
||||
// var httpContext = httpContextFactory.HttpContext;
|
||||
// var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
|
||||
// var contentStore = new ContentStore(umbracoContext);
|
||||
// var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
// umbracoContext.RoutingContext = new RoutingContext(
|
||||
// new IPublishedContentLookup[] {new LookupByNiceUrl()},
|
||||
// new DefaultLastChanceLookup(),
|
||||
// contentStore,
|
||||
// niceUrls);
|
||||
// //need to create a template with id 1045
|
||||
// var template = Template.MakeNew("test", new User(0));
|
||||
|
||||
// StateHelper.HttpContext = httpContext;
|
||||
// SetupUmbracoContextForTest(umbracoContext, template);
|
||||
|
||||
// //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
|
||||
// //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
|
||||
// Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
|
||||
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
|
||||
|
||||
// //need to create a template with id 1045
|
||||
// var template = Template.MakeNew("test", new User(0));
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest);
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
|
||||
// Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
|
||||
|
||||
// SetupUmbracoContextForTest(umbracoContext, template);
|
||||
//}
|
||||
|
||||
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
|
||||
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest);
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
|
||||
// Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.UI;
|
||||
|
||||
@@ -1,605 +0,0 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', ['jshint:dev', 'build', 'karma:unit']);
|
||||
grunt.registerTask('dev', ['jshint:dev', 'build-dev', 'webserver', 'open:dev', 'watch']);
|
||||
grunt.registerTask('docserve', ['docs:api', 'connect:docserver', 'open:docs', 'watch:docs']);
|
||||
grunt.registerTask('vs', ['jshint:dev', 'build-dev', 'watch']);
|
||||
|
||||
//TODO: Too much watching, this brings windows to it's knees when in dev mode
|
||||
//run by the watch task
|
||||
grunt.registerTask('watch-js', ['jshint:dev', 'concat', 'copy:app', 'copy:mocks', 'copy:canvasdesigner', 'copy:vs', 'karma:unit']);
|
||||
grunt.registerTask('watch-less', ['recess:build', 'recess:installer', 'recess:nonodes', 'recess:canvasdesigner', 'postcss', 'copy:canvasdesigner', 'copy:assets', 'copy:vs']);
|
||||
grunt.registerTask('watch-html', ['copy:views', 'copy:vs']);
|
||||
grunt.registerTask('watch-installer', ['concat:install', 'concat:installJs', 'copy:installer', 'copy:vs']);
|
||||
grunt.registerTask('watch-canvasdesigner', ['copy:canvasdesigner', 'concat:canvasdesignerJs', 'copy:vs']);
|
||||
grunt.registerTask('watch-test', ['jshint:dev', 'karma:unit']);
|
||||
|
||||
//triggered from grunt
|
||||
grunt.registerTask('build', ['concat', 'recess:build', 'recess:installer', 'recess:nonodes', 'recess:canvasdesigner', 'postcss', 'bower-install-simple', 'bower', 'copy', 'clean:post']);
|
||||
|
||||
//triggered from grunt dev vs or grunt vs
|
||||
grunt.registerTask('build-dev', ['clean:pre', 'concat', 'recess:build', 'recess:installer', 'recess:nonodes', 'postcss', 'bower-install-simple', 'bower', 'copy']);
|
||||
|
||||
//utillity tasks
|
||||
grunt.registerTask('docs', ['ngdocs']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
|
||||
|
||||
// Print a timestamp (useful for when watching)
|
||||
grunt.registerTask('timestamp', function () {
|
||||
grunt.log.subhead(Date());
|
||||
});
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
buildVersion: grunt.option('buildversion') || '7',
|
||||
connect: {
|
||||
devserver: {
|
||||
options: {
|
||||
port: 9990,
|
||||
hostname: '0.0.0.0',
|
||||
base: './build',
|
||||
middleware: function(connect, options) {
|
||||
return [
|
||||
//uncomment to enable CSP
|
||||
// util.csp(),
|
||||
//util.rewrite(),
|
||||
connect.favicon('images/favicon.ico'),
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base)
|
||||
];
|
||||
}
|
||||
}
|
||||
},
|
||||
testserver: {},
|
||||
docserver: {
|
||||
options: {
|
||||
port: 8880,
|
||||
hostname: '0.0.0.0',
|
||||
base: './docs/api',
|
||||
middleware: function(connect, options) {
|
||||
return [
|
||||
//uncomment to enable CSP
|
||||
// util.csp(),
|
||||
//util.rewrite(),
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base)
|
||||
];
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
open: {
|
||||
dev: {
|
||||
path: 'http://localhost:9990/belle/'
|
||||
},
|
||||
docs: {
|
||||
path: 'http://localhost:8880/index.html'
|
||||
}
|
||||
},
|
||||
|
||||
distdir: 'build/belle',
|
||||
vsdir: '../Umbraco.Web.UI/umbraco',
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
banner:
|
||||
'/*! <%= 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',
|
||||
src: {
|
||||
js: ['src/**/*.js', 'src/*.js'],
|
||||
|
||||
common: ['src/common/**/*.js'],
|
||||
controllers: ['src/**/*.controller.js'],
|
||||
|
||||
specs: ['test/**/*.spec.js'],
|
||||
scenarios: ['test/**/*.scenario.js'],
|
||||
samples: ['sample files/*.js'],
|
||||
html: ['src/index.html', 'src/install.html'],
|
||||
|
||||
everything: ['src/**/*.*', 'test/**/*.*', 'docs/**/*.*'],
|
||||
|
||||
tpl: {
|
||||
app: ['src/views/**/*.html'],
|
||||
common: ['src/common/**/*.tpl.html']
|
||||
},
|
||||
less: ['src/less/belle.less'], // recess:build doesn't accept ** in its file patterns
|
||||
prod: ['<%= distdir %>/js/*.js']
|
||||
},
|
||||
|
||||
clean: {
|
||||
pre: ['<%= distdir %>/*'],
|
||||
post: ['<%= distdir %>/js/*.dev.js']
|
||||
},
|
||||
|
||||
copy: {
|
||||
assets: {
|
||||
files: [{ dest: '<%= distdir %>/assets', src: '**', expand: true, cwd: 'src/assets/' }]
|
||||
},
|
||||
|
||||
config: {
|
||||
files: [{ dest: '<%= distdir %>/../config', src: '**', expand: true, cwd: 'src/config/' }]
|
||||
},
|
||||
|
||||
installer: {
|
||||
files: [{ dest: '<%= distdir %>/views/install', src: '**/*.html', expand: true, cwd: 'src/installer/steps' }]
|
||||
},
|
||||
|
||||
canvasdesigner: {
|
||||
files: [
|
||||
{ dest: '<%= distdir %>/preview', src: '**/*.html', expand: true, cwd: 'src/canvasdesigner' },
|
||||
{ dest: '<%= distdir %>/preview/editors', src: '**/*.html', expand: true, cwd: 'src/canvasdesigner/editors' },
|
||||
{ dest: '<%= distdir %>/assets/less', src: '**/*.less', expand: true, cwd: 'src/canvasdesigner/editors' },
|
||||
{ dest: '<%= distdir %>/js', src: 'canvasdesigner.config.js', expand: true, cwd: 'src/canvasdesigner/config' },
|
||||
{ dest: '<%= distdir %>/js', src: 'canvasdesigner.palettes.js', expand: true, cwd: 'src/canvasdesigner/config' },
|
||||
{ dest: '<%= distdir %>/js', src: 'canvasdesigner.front.js', expand: true, cwd: 'src/canvasdesigner' }
|
||||
]
|
||||
},
|
||||
|
||||
vendor: {
|
||||
files: [{ dest: '<%= distdir %>/lib', src: '**', expand: true, cwd: 'lib/' }]
|
||||
},
|
||||
|
||||
views: {
|
||||
files: [{ dest: '<%= distdir %>/views', src: ['**/*.*', '!**/*.controller.js'], expand: true, cwd: 'src/views' }]
|
||||
},
|
||||
|
||||
app: {
|
||||
files: [
|
||||
{ dest: '<%= distdir %>/js', src: '*.js', expand: true, cwd: 'src/' }
|
||||
]
|
||||
},
|
||||
|
||||
mocks: {
|
||||
files: [{ dest: '<%= distdir %>/js', src: '*.js', expand: true, cwd: 'src/common/mocks/' }]
|
||||
},
|
||||
|
||||
vs: {
|
||||
files: [
|
||||
//everything except the index.html root file!
|
||||
//then we need to figure out how to not copy all the test stuff either!?
|
||||
{ dest: '<%= vsdir %>/assets', src: '**', expand: true, cwd: '<%= distdir %>/assets' },
|
||||
{ dest: '<%= vsdir %>/js', src: '**', expand: true, cwd: '<%= distdir %>/js' },
|
||||
{ dest: '<%= vsdir %>/views', src: '**', expand: true, cwd: '<%= distdir %>/views' },
|
||||
{ dest: '<%= vsdir %>/preview', src: '**', expand: true, cwd: '<%= distdir %>/preview' },
|
||||
{ dest: '<%= vsdir %>/lib', src: '**', expand: true, cwd: '<%= distdir %>/lib' }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
karma: {
|
||||
unit: { configFile: 'test/config/karma.conf.js', keepalive: true },
|
||||
e2e: { configFile: 'test/config/e2e.js', keepalive: true },
|
||||
watch: { configFile: 'test/config/unit.js', singleRun: false, autoWatch: true, keepalive: true }
|
||||
},
|
||||
|
||||
concat: {
|
||||
index: {
|
||||
src: ['src/index.html'],
|
||||
dest: '<%= distdir %>/index.html',
|
||||
options: {
|
||||
process: true
|
||||
}
|
||||
},
|
||||
install: {
|
||||
src: ['src/installer/installer.html'],
|
||||
dest: '<%= distdir %>/installer.html',
|
||||
options: {
|
||||
process: true
|
||||
}
|
||||
},
|
||||
|
||||
installJs: {
|
||||
src: ['src/installer/**/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.installer.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
canvasdesignerJs: {
|
||||
src: ['src/canvasdesigner/canvasdesigner.global.js', 'src/canvasdesigner/canvasdesigner.controller.js', 'src/canvasdesigner/editors/*.js', 'src/canvasdesigner/lib/*.js'],
|
||||
dest: '<%= distdir %>/js/canvasdesigner.panel.js'
|
||||
},
|
||||
|
||||
controllers: {
|
||||
src: ['src/controllers/**/*.controller.js', 'src/views/**/*.controller.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.controllers.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
services: {
|
||||
src: ['src/common/services/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.services.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
security: {
|
||||
src: ['src/common/security/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.security.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
resources: {
|
||||
src: ['src/common/resources/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.resources.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
testing: {
|
||||
src: ['src/common/mocks/*/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.testing.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
directives: {
|
||||
src: ['src/common/directives/**/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.directives.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
},
|
||||
|
||||
filters: {
|
||||
src: ['src/common/filters/*.js'],
|
||||
dest: '<%= distdir %>/js/umbraco.filters.js',
|
||||
options: {
|
||||
banner: "<%= banner %>\n(function() { \n\n",
|
||||
footer: "\n\n})();"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
options: {
|
||||
mangle: true
|
||||
},
|
||||
combine: {
|
||||
files: {
|
||||
'<%= distdir %>/js/umbraco.min.js': ['<%= distdir %>/js/umbraco.*.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
recess: {
|
||||
build: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/<%= pkg.name %>.css':
|
||||
['<%= src.less %>']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
nonodes: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/nonodes.style.min.css':
|
||||
['src/less/pages/nonodes.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
installer: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/installer.css':
|
||||
['src/less/installer.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
},
|
||||
canvasdesigner: {
|
||||
files: {
|
||||
'<%= distdir %>/assets/css/canvasdesigner.css':
|
||||
['src/less/canvas-designer.less', 'src/less/helveticons.less']
|
||||
},
|
||||
options: {
|
||||
compile: true,
|
||||
compress: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
postcss: {
|
||||
options: {
|
||||
processors: [
|
||||
// add vendor prefixes
|
||||
require('autoprefixer-core')({
|
||||
browsers: 'last 2 versions'
|
||||
})
|
||||
]
|
||||
},
|
||||
dist: {
|
||||
src: '<%= distdir %>/assets/css/<%= pkg.name %>.css'
|
||||
}
|
||||
},
|
||||
|
||||
ngTemplateCache: {
|
||||
views: {
|
||||
files: {
|
||||
'<%= distdir %>/js/umbraco.views.js': 'src/views/**/*.html'
|
||||
},
|
||||
options: {
|
||||
trim: 'src/',
|
||||
module: 'umbraco.views'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
docs: {
|
||||
files: ['docs/src/**/*.md'],
|
||||
tasks: ['watch-docs', 'timestamp']
|
||||
},
|
||||
css: {
|
||||
files: 'src/**/*.less',
|
||||
tasks: ['watch-less', 'timestamp'],
|
||||
options: {
|
||||
livereload: true,
|
||||
},
|
||||
},
|
||||
js: {
|
||||
files: ['src/**/*.js', 'src/*.js'],
|
||||
tasks: ['watch-js', 'timestamp'],
|
||||
},
|
||||
test: {
|
||||
files: ['test/**/*.js'],
|
||||
tasks: ['watch-test', 'timestamp'],
|
||||
},
|
||||
installer: {
|
||||
files: ['src/installer/**/*.*'],
|
||||
tasks: ['watch-installer', 'timestamp'],
|
||||
},
|
||||
canvasdesigner: {
|
||||
files: ['src/canvasdesigner/**/*.*'],
|
||||
tasks: ['watch-canvasdesigner', 'timestamp'],
|
||||
},
|
||||
html: {
|
||||
files: ['src/views/**/*.html', 'src/*.html'],
|
||||
tasks: ['watch-html', 'timestamp']
|
||||
},
|
||||
options: {
|
||||
interval: 500
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ngdocs: {
|
||||
options: {
|
||||
dest: 'docs/api',
|
||||
startPage: '/api',
|
||||
title: "Umbraco Backoffice UI API Documentation",
|
||||
html5Mode: false,
|
||||
styles: [
|
||||
'docs/umb-docs.css'
|
||||
],
|
||||
image: "https://our.umbraco.org/assets/images/logo.svg"
|
||||
},
|
||||
api: {
|
||||
src: ['src/common/**/*.js', 'docs/src/api/**/*.ngdoc'],
|
||||
title: 'API Documentation'
|
||||
},
|
||||
tutorials: {
|
||||
src: [],
|
||||
title: ''
|
||||
}
|
||||
},
|
||||
|
||||
eslint:{
|
||||
src: ['<%= src.common %>','<%= src.controllers %>'],
|
||||
options: {quiet: true}
|
||||
},
|
||||
|
||||
jshint: {
|
||||
dev: {
|
||||
files: {
|
||||
src: ['<%= src.common %>']
|
||||
},
|
||||
options: {
|
||||
curly: true,
|
||||
eqeqeq: true,
|
||||
immed: true,
|
||||
latedef: "nofunc",
|
||||
newcap: true,
|
||||
noarg: true,
|
||||
sub: true,
|
||||
boss: true,
|
||||
//NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
|
||||
es5: true,
|
||||
eqnull: true,
|
||||
//NOTE: we need to use eval sometimes so ignore it
|
||||
evil: true,
|
||||
//NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
|
||||
scripturl: true,
|
||||
//NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
|
||||
smarttabs: true,
|
||||
globals: {}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
files: {
|
||||
src: ['<%= src.prod %>']
|
||||
},
|
||||
options: {
|
||||
curly: true,
|
||||
eqeqeq: true,
|
||||
immed: true,
|
||||
latedef: "nofunc",
|
||||
newcap: true,
|
||||
noarg: true,
|
||||
sub: true,
|
||||
boss: true,
|
||||
//NOTE: This is required so it doesn't barf on reserved words like delete when doing $http.delete
|
||||
es5: true,
|
||||
eqnull: true,
|
||||
//NOTE: we need to use eval sometimes so ignore it
|
||||
evil: true,
|
||||
//NOTE: we need to check for strings such as "javascript:" so don't throw errors regarding those
|
||||
scripturl: true,
|
||||
//NOTE: we ignore tabs vs spaces because enforcing that causes lots of errors depending on the text editor being used
|
||||
smarttabs: true,
|
||||
globalstrict: true,
|
||||
globals: { $: false, jQuery: false, define: false, require: false, window: false }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
bower: {
|
||||
dev: {
|
||||
dest: '<%= distdir %>/lib',
|
||||
options: {
|
||||
expand: true,
|
||||
ignorePackages: ['bootstrap'],
|
||||
packageSpecific: {
|
||||
'moment': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['min/moment-with-locales.js']
|
||||
},
|
||||
'typeahead.js': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/typeahead.bundle.min.js']
|
||||
},
|
||||
'underscore': {
|
||||
files: ['underscore-min.js', 'underscore-min.map']
|
||||
},
|
||||
'rgrove-lazyload': {
|
||||
files: ['lazyload.js']
|
||||
},
|
||||
'bootstrap-social': {
|
||||
files: ['bootstrap-social.css']
|
||||
},
|
||||
'font-awesome': {
|
||||
files: ['css/font-awesome.min.css', 'fonts/*']
|
||||
},
|
||||
"jquery": {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/jquery.min.js', 'dist/jquery.min.map']
|
||||
},
|
||||
'jquery-ui': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['jquery-ui.min.js']
|
||||
},
|
||||
'jquery-migrate': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['jquery-migrate.min.js']
|
||||
},
|
||||
'tinymce': {
|
||||
files: ['plugins/**', 'themes/**', 'tinymce.min.js']
|
||||
},
|
||||
'angular-dynamic-locale': {
|
||||
files: ['tmhDynamicLocale.min.js', 'tmhDynamicLocale.min.js.map']
|
||||
},
|
||||
'ng-file-upload': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['ng-file-upload.min.js']
|
||||
},
|
||||
'angular-local-storage': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/angular-local-storage.min.js']
|
||||
},
|
||||
'codemirror': {
|
||||
files: [
|
||||
'lib/codemirror.js',
|
||||
'lib/codemirror.css',
|
||||
|
||||
'mode/css/*',
|
||||
'mode/javascript/*',
|
||||
'mode/xml/*',
|
||||
'mode/htmlmixed/*',
|
||||
|
||||
'addon/search/*',
|
||||
'addon/edit/*',
|
||||
'addon/selection/*',
|
||||
'addon/dialog/*'
|
||||
]
|
||||
},
|
||||
'ace-builds': {
|
||||
files: [
|
||||
'src-min-noconflict/ace.js',
|
||||
|
||||
'src-min-noconflict/ext-language_tools.js',
|
||||
'src-min-noconflict/ext-searchbox.js',
|
||||
'src-min-noconflict/ext-settings_menu.js',
|
||||
|
||||
'src-min-noconflict/snippets/text.js',
|
||||
'src-min-noconflict/snippets/javascript.js',
|
||||
|
||||
'src-min-noconflict/theme-chrome.js',
|
||||
|
||||
'src-min-noconflict/mode-razor.js',
|
||||
'src-min-noconflict/mode-javascript.js',
|
||||
|
||||
'src-min-noconflict/worker-javascript.js',
|
||||
]
|
||||
},
|
||||
'clipboard': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['dist/clipboard.min.js']
|
||||
},
|
||||
'angular-moment': {
|
||||
keepExpandedHierarchy: false,
|
||||
files: ['angular-moment.min.js']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
options: {
|
||||
expand: true
|
||||
}
|
||||
},
|
||||
|
||||
"bower-install-simple": {
|
||||
options: {
|
||||
color: true
|
||||
},
|
||||
"dev": {}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-recess');
|
||||
grunt.loadNpmTasks('grunt-postcss');
|
||||
|
||||
grunt.loadNpmTasks('grunt-karma');
|
||||
|
||||
grunt.loadNpmTasks('grunt-open');
|
||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks("grunt-bower-install-simple");
|
||||
grunt.loadNpmTasks('grunt-bower');
|
||||
grunt.loadNpmTasks('grunt-ngdocs');
|
||||
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-hustler');
|
||||
};
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
|
||||
scope.openDocumentType = function (documentType) {
|
||||
var url = "/settings/documenttypes/edit/" + documentType.id;
|
||||
$location.path(url);
|
||||
$location.url(url);
|
||||
};
|
||||
|
||||
scope.updateTemplate = function (templateAlias) {
|
||||
|
||||
+5
-3
@@ -59,7 +59,6 @@
|
||||
</pre>
|
||||
|
||||
<h1>General Options</h1>
|
||||
Lorem ipsum dolor sit amet..
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -74,7 +73,7 @@ Lorem ipsum dolor sit amet..
|
||||
<td>Set the title of the overlay.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>model.subTitle</td>
|
||||
<td>model.subtitle</td>
|
||||
<td>String</td>
|
||||
<td>Set the subtitle of the overlay.</td>
|
||||
</tr>
|
||||
@@ -496,6 +495,7 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
var activeElementType = document.activeElement.tagName;
|
||||
var clickableElements = ["A", "BUTTON"];
|
||||
var submitOnEnter = document.activeElement.hasAttribute("overlay-submit-on-enter");
|
||||
var submitOnEnterValue = submitOnEnter ? document.activeElement.getAttribute("overlay-submit-on-enter") : "";
|
||||
|
||||
if(clickableElements.indexOf(activeElementType) === 0) {
|
||||
document.activeElement.click();
|
||||
@@ -503,7 +503,9 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
} else if(activeElementType === "TEXTAREA" && !submitOnEnter) {
|
||||
|
||||
|
||||
} else {
|
||||
} else if (submitOnEnter && submitOnEnterValue === "false") {
|
||||
// don't do anything
|
||||
}else {
|
||||
scope.$apply(function () {
|
||||
scope.submitForm(scope.model);
|
||||
});
|
||||
|
||||
+6
-6
@@ -10,12 +10,12 @@ function noDirtyCheck() {
|
||||
require: 'ngModel',
|
||||
link: function (scope, elm, attrs, ctrl) {
|
||||
|
||||
elm.focus(function () {
|
||||
scope.$watch(function() {
|
||||
ctrl.$pristine = false;
|
||||
});
|
||||
});
|
||||
|
||||
var alwaysFalse = {
|
||||
get: function () { return false; },
|
||||
set: function () { }
|
||||
};
|
||||
Object.defineProperty(ctrl, '$pristine', alwaysFalse);
|
||||
Object.defineProperty(ctrl, '$dirty', alwaysFalse);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -288,9 +288,12 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
throw "args.tree cannot be null";
|
||||
}
|
||||
|
||||
if (mainTreeEventHandler) {
|
||||
//returns a promise
|
||||
return mainTreeEventHandler.syncTree(args);
|
||||
if (mainTreeEventHandler) {
|
||||
|
||||
if (mainTreeEventHandler.syncTree) {
|
||||
//returns a promise,
|
||||
return mainTreeEventHandler.syncTree(args);
|
||||
}
|
||||
}
|
||||
|
||||
//couldn't sync
|
||||
|
||||
@@ -168,6 +168,9 @@
|
||||
//used for property editors
|
||||
@import "property-editors.less";
|
||||
|
||||
//used for prevalue editors
|
||||
@import "components/prevalues/multivalues.less";
|
||||
|
||||
|
||||
@import "typeahead.less";
|
||||
@import "hacks.less";
|
||||
@@ -175,4 +178,4 @@
|
||||
@import "healthcheck.less";
|
||||
|
||||
// cleanup properties.less when it is done
|
||||
@import "properties.less";
|
||||
@import "properties.less";
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
.umb-prevalues-multivalues {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__left {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__right {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add input {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add input {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__add button {
|
||||
margin: 0 6px 0 0;
|
||||
float: right
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem {
|
||||
display: flex;
|
||||
padding: 6px;
|
||||
margin: 10px 0px !important;
|
||||
background: #F3F3F5;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__listitem input {
|
||||
width: 295px;
|
||||
}
|
||||
@@ -280,7 +280,6 @@
|
||||
.umb-grid .umb-control {
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@@ -40,6 +40,16 @@
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.umb-contentpicker__min-max-help {
|
||||
font-size: 13px;
|
||||
margin-top: 5px;
|
||||
color: @gray-4;
|
||||
}
|
||||
|
||||
.show-validation .umb-contentpicker__min-max-help {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.umb-contentpicker small {
|
||||
|
||||
&:not(:last-child) {
|
||||
@@ -109,22 +119,22 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
/* pre-value editor */
|
||||
/*.control-group.color-picker-preval:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 100%;
|
||||
}*/
|
||||
|
||||
/*.control-group.color-picker-preval div.thumbnail {
|
||||
display: inline-block;
|
||||
/*.control-group.color-picker-preval:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}*/
|
||||
.control-group.color-picker-preval div.color-picker-prediv {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}*/
|
||||
|
||||
/*.control-group.color-picker-preval div.thumbnail {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}*/
|
||||
.control-group.color-picker-preval div.color-picker-prediv {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval pre {
|
||||
display: inline;
|
||||
margin-right: 20px;
|
||||
@@ -136,18 +146,18 @@ ul.color-picker li a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval btn {
|
||||
.control-group.color-picker-preval btn {
|
||||
//vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval input[type="text"] {
|
||||
min-width: 40%;
|
||||
width: 40%;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
.control-group.color-picker-preval input[type="text"] {
|
||||
min-width: 40%;
|
||||
width: 40%;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval label {
|
||||
border: solid @white 1px;
|
||||
padding: 6px;
|
||||
@@ -203,10 +213,22 @@ ul.color-picker li a {
|
||||
|
||||
|
||||
|
||||
.umb-thumbnails{
|
||||
position: relative;
|
||||
.umb-thumbnails {
|
||||
position: relative;
|
||||
display: flex;
|
||||
-ms-flex-direction: row;
|
||||
-webkit-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.umb-thumbnails > li.icon {
|
||||
width: 14%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.umb-thumbnails i{margin: auto;}
|
||||
.umb-thumbnails a{
|
||||
|
||||
@@ -100,6 +100,27 @@
|
||||
.color-green, .color-green i{color: @green-d1 !important;}
|
||||
.color-yellow, .color-yellow i{color: @yellow-d1 !important;}
|
||||
|
||||
/* Colors based on http://zavoloklom.github.io/material-design-color-palette/colors.html */
|
||||
.color-black, .color-black i { color: #000 !important; }
|
||||
.color-blue-grey, .color-blue-grey i { color: #607d8b !important; }
|
||||
.color-grey, .color-grey i { color: #9e9e9e !important; }
|
||||
.color-brown, .color-brown i { color: #795548 !important; }
|
||||
.color-blue, .color-blue i { color: #2196f3 !important; }
|
||||
.color-light-blue, .color-light-blue i {color: #03a9f4 !important; }
|
||||
.color-cyan, .color-cyan i { color: #00bcd4 !important; }
|
||||
.color-green, .color-green i { color: #4caf50 !important; }
|
||||
.color-light-green, .color-light-green i {color: #8bc34a !important; }
|
||||
.color-lime, .color-lime i { color: #cddc39 !important; }
|
||||
.color-yellow, .color-yellow i { color: #ffeb3b !important; }
|
||||
.color-amber, .color-amber i { color: #ffc107 !important; }
|
||||
.color-orange, .color-orange i { color: #ff9800 !important; }
|
||||
.color-deep-orange, .color-deep-orange i { color: #ff5722 !important; }
|
||||
.color-red, .color-red i { color: #f44336 !important; }
|
||||
.color-pink, .color-pink i { color: #e91e63 !important; }
|
||||
.color-purple,.color-purple i { color: #9c27b0 !important; }
|
||||
.color-deep-purple, .color-deep-purple i { color: #673ab7 !important; }
|
||||
.color-indigo, .color-indigo i { color: #3f51b5 !important; }
|
||||
|
||||
|
||||
// Scaffolding
|
||||
// -------------------------
|
||||
|
||||
@@ -7,14 +7,13 @@ angular.module("umbraco")
|
||||
$scope.icons = icons;
|
||||
});
|
||||
|
||||
$scope.submitClass = function (icon) {
|
||||
$scope.submitClass = function(icon){
|
||||
if($scope.color) {
|
||||
$scope.submit(icon + " " + $scope.color);
|
||||
}
|
||||
else {
|
||||
$scope.submit(icon);
|
||||
else {
|
||||
$scope.submit(icon);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
@@ -16,24 +16,25 @@
|
||||
|
||||
<div class="umb-control-group">
|
||||
<select ng-model="color" class="input-block-level">
|
||||
<option value="">
|
||||
<localize key="colors_black">Black</localize>
|
||||
</option>
|
||||
<option value="color-green">
|
||||
<localize key="colors_green">Green</localize>
|
||||
</option>
|
||||
<option value="color-yellow">
|
||||
<localize key="colors_yellow">Yellow</localize>
|
||||
</option>
|
||||
<option value="color-orange">
|
||||
<localize key="colors_orange">Orange</localize>
|
||||
</option>
|
||||
<option value="color-blue">
|
||||
<localize key="colors_blue">Blue</localize>
|
||||
</option>
|
||||
<option value="color-red">
|
||||
<localize key="colors_red">Red</localize>
|
||||
</option>
|
||||
<option value=""><localize key="colors_black">Black</localize></option>
|
||||
<option value="color-blue-grey"><localize key="colors_bluegrey">Blue Grey</localize></option>
|
||||
<option value="color-grey"><localize key="colors_grey">Grey</localize></option>
|
||||
<option value="color-brown"><localize key="colors_brown">Brown</localize></option>
|
||||
<option value="color-blue"><localize key="colors_blue">Blue</localize></option>
|
||||
<option value="color-light-blue"><localize key="colors_lightblue">Light Blue</localize></option>
|
||||
<option value="color-cyan"><localize key="colors_cyan">Cyan</localize></option>
|
||||
<option value="color-green"><localize key="colors_green">Green</localize></option>
|
||||
<option value="color-light-green"><localize key="colors_lightgreen">Light Green</localize></option>
|
||||
<option value="color-yellow"><localize key="colors_yellow">Yellow</localize></option>
|
||||
<option value="color-lime"><localize key="colors_lime">Lime</localize></option>
|
||||
<option value="color-amber"><localize key="colors_amber">Amber</localize></option>
|
||||
<option value="color-orange"><localize key="colors_orange">Orange</localize></option>
|
||||
<option value="color-deep-orange"><localize key="colors_deeporange">Deep Orange</localize></option>
|
||||
<option value="color-red"><localize key="colors_red">Red</localize></option>
|
||||
<option value="color-pink"><localize key="colors_pink">Pink</localize></option>
|
||||
<option value="color-purple"><localize key="colors_purple">Purple</localize></option>
|
||||
<option value="color-deep-purple"><localize key="colors_deeppurple">Deep Purple</localize></option>
|
||||
<option value="color-indigo"><localize key="colors_indigo">Indigo</localize></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -47,7 +47,17 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="umb-table-cell" ng-repeat="column in itemProperties">
|
||||
<span title="{{column.header}}: {{item[column.alias]}}">{{item[column.alias]}}</span>
|
||||
<span title="{{column.header}}: {{item[column.alias]}}">
|
||||
|
||||
<div ng-if="!column.isSensitive">
|
||||
{{item[column.alias]}}
|
||||
</div>
|
||||
|
||||
<em ng-show="column.isSensitive" class="muted">
|
||||
<localize key="content_isSensitiveValue_short"></localize>
|
||||
</em>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
|
||||
|
||||
$scope.newItem = "";
|
||||
$scope.hasError = false;
|
||||
$scope.focusOnNew = false;
|
||||
|
||||
if (!angular.isArray($scope.model.value)) {
|
||||
|
||||
@@ -43,6 +44,7 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
|
||||
$scope.model.value.push({ value: $scope.newItem });
|
||||
$scope.newItem = "";
|
||||
$scope.hasError = false;
|
||||
$scope.focusOnNew = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -73,6 +75,12 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.MultiValuesControl
|
||||
}
|
||||
};
|
||||
|
||||
$scope.createNew = function (event) {
|
||||
if (event.keyCode == 13) {
|
||||
$scope.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
function getElementIndexByPrevalueText(value) {
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
if ($scope.model.value[i].value === value) {
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
<div class="umb-editor" ng-controller="Umbraco.PrevalueEditors.MultiValuesController">
|
||||
<div class="control-group">
|
||||
<input name="newItem" type="text" ng-model="newItem" val-highlight="{{hasError}}" />
|
||||
<button class="btn" ng-click="add($event)">Add</button>
|
||||
<div class="umb-editor umb-prevalues-multivalues" ng-controller="Umbraco.PrevalueEditors.MultiValuesController">
|
||||
<div class="control-group umb-prevalues-multivalues__add">
|
||||
<div class="umb-prevalues-multivalues__left">
|
||||
<input overlay-submit-on-enter="false" name="newItem" focus-when="{{focusOnNew}}" ng-keydown="createNew($event)" type="text" ng-model="newItem" val-highlight="{{hasError}}" />
|
||||
</div>
|
||||
<div class="umb-prevalues-multivalues__right">
|
||||
<button class="btn btn-info" ng-click="add($event)">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div ui-sortable="sortableOptions">
|
||||
<div class="control-group" ng-repeat="item in model.value">
|
||||
<div class="control-group umb-prevalues-multivalues__listitem" ng-repeat="item in model.value">
|
||||
<i class="icon icon-navigation handle"></i>
|
||||
<input type="text" ng-model="item.value" val-server="item_{{$index}}" required />
|
||||
<button class="btn btn-danger" ng-click="remove(item, $event)">Remove</button>
|
||||
<div class="umb-prevalues-multivalues__left">
|
||||
<input type="text" ng-model="item.value" val-server="item_{{$index}}" required />
|
||||
</div>
|
||||
<div class="umb-prevalues-multivalues__right">
|
||||
<a class="umb-node-preview__action" ng-click="remove(item, $event)">Remove</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ function ColorPickerController($scope) {
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = $scope.model.value.hasOwnProperty("value")
|
||||
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
|
||||
+2
@@ -66,6 +66,8 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
showOpenButton: false,
|
||||
showEditButton: false,
|
||||
showPathOnHover: false,
|
||||
maxNumber: 1,
|
||||
minNumber : 0,
|
||||
startNode: {
|
||||
query: "",
|
||||
type: "content",
|
||||
|
||||
+34
-1
@@ -20,7 +20,7 @@
|
||||
</umb-node-preview>
|
||||
</div>
|
||||
|
||||
<a ng-show="model.config.multiPicker === true || renderModel.length === 0"
|
||||
<a ng-show="model.config.multiPicker === true && renderModel.length < model.config.maxNumber || renderModel.length === 0 || !model.config.maxNumber"
|
||||
class="umb-node-preview-add"
|
||||
href=""
|
||||
ng-click="openContentPicker()"
|
||||
@@ -28,6 +28,39 @@
|
||||
<localize key="general_add">Add</localize>
|
||||
</a>
|
||||
|
||||
<div class="umb-contentpicker__min-max-help" ng-if="model.config.multiPicker === true">
|
||||
|
||||
<!-- Both min and max items -->
|
||||
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber !== model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add between {{model.config.minNumber}} and {{model.config.maxNumber}} items</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Equal min and max -->
|
||||
<span ng-if="model.config.minNumber && model.config.maxNumber && model.config.minNumber === model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add {{model.config.minNumber - renderModel.length}} item(s)</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected"> items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Only max -->
|
||||
<span ng-if="!model.config.minNumber && model.config.maxNumber">
|
||||
<span ng-if="renderModel.length < model.config.maxNumber">Add up to {{model.config.maxNumber}} items</span>
|
||||
<span ng-if="renderModel.length > model.config.maxNumber">
|
||||
<localize key="validation_maxCount">You can only have</localize> {{model.config.maxNumber}} <localize key="validation_itemsSelected">items selected</localize>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- Only min -->
|
||||
<span ng-if="model.config.minNumber && !model.config.maxNumber && renderModel.length < model.config.minNumber">
|
||||
Add at least {{model.config.minNumber}} item(s)
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<!--These are here because we need ng-form fields to validate against-->
|
||||
<input type="hidden" name="minCount" ng-model="renderModel" />
|
||||
<input type="hidden" name="maxCount" ng-model="renderModel" />
|
||||
|
||||
+3
@@ -130,6 +130,9 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag
|
||||
// in the description of this controller, it states that this value isn't actually used for persistence,
|
||||
// but we need to set it so that the editor and the server can detect that it's been changed, and it is used for validation.
|
||||
$scope.model.value = { selectedFiles: newVal.trimEnd(",") };
|
||||
|
||||
//need to explicity setDirty here as file upload field can't track dirty & we can't use the fileCount (hidden field/model)
|
||||
$scope.propertyForm.$setDirty();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory"/>
|
||||
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory" no-dirty-check />
|
||||
|
||||
</div>
|
||||
|
||||
+22
-2
@@ -30,15 +30,14 @@
|
||||
vm.dragLeave = dragLeave;
|
||||
vm.onFilesQueue = onFilesQueue;
|
||||
vm.onUploadComplete = onUploadComplete;
|
||||
markAsSensitive();
|
||||
|
||||
function activate() {
|
||||
|
||||
if ($scope.entityType === 'media') {
|
||||
mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function (types) {
|
||||
vm.acceptedMediatypes = types;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function selectAll($event) {
|
||||
@@ -87,6 +86,27 @@
|
||||
$scope.getContent($scope.contentId);
|
||||
}
|
||||
|
||||
function markAsSensitive() {
|
||||
angular.forEach($scope.options.includeProperties, function (option) {
|
||||
option.isSensitive = false;
|
||||
|
||||
angular.forEach($scope.items,
|
||||
function (item) {
|
||||
|
||||
angular.forEach(item.properties,
|
||||
function (property) {
|
||||
|
||||
if (option.alias === property.alias) {
|
||||
option.isSensitive = property.isSensitive;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
activate();
|
||||
|
||||
}
|
||||
|
||||
+7
-1
@@ -46,6 +46,7 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
// init the md editor after this digest because the DOM needs to be ready first
|
||||
// so run the init on a timeout
|
||||
$timeout(function () {
|
||||
$scope.markdownEditorInitComplete = false;
|
||||
var converter2 = new Markdown.Converter();
|
||||
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
|
||||
editor2.run();
|
||||
@@ -59,7 +60,12 @@ function MarkdownEditorController($scope, $element, assetsService, dialogService
|
||||
editor2.hooks.set("onPreviewRefresh", function () {
|
||||
// We must manually update the model as there is no way to hook into the markdown editor events without exstensive edits to the library.
|
||||
if ($scope.model.value !== $("textarea", $element).val()) {
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
if ($scope.markdownEditorInitComplete) {
|
||||
//only set dirty after init load to avoid "unsaved" dialogue when we don't want it
|
||||
angularHelper.getCurrentForm($scope).$setDirty();
|
||||
} else {
|
||||
$scope.markdownEditorInitComplete = true;
|
||||
}
|
||||
$scope.model.value = $("textarea", $element).val();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -359,7 +359,8 @@ angular.module("umbraco")
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server;
|
||||
tinyMceEditor.setContent(newVal, { format: 'raw' });
|
||||
//uses an empty string in the editor when the value is null
|
||||
tinyMceEditor.setContent(newVal || "", { format: 'raw' });
|
||||
//we need to manually fire this event since it is only ever fired based on loading from the DOM, this
|
||||
// is required for our plugins listening to this event to execute
|
||||
tinyMceEditor.fire('LoadContent', null);
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
$scope.model.config.ticksPositions = _.map($scope.model.config.ticksPositions.split(','), function (item) {
|
||||
return parseInt(item.trim());
|
||||
});
|
||||
console.log($scope.model.config.ticksPositions);
|
||||
}
|
||||
|
||||
if (!$scope.model.config.ticksLabels) {
|
||||
@@ -215,4 +214,4 @@
|
||||
assetsService.loadCss("lib/slider/bootstrap-slider.css");
|
||||
assetsService.loadCss("lib/slider/bootstrap-slider-custom.css");
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.SliderController", sliderController);
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.SliderController", sliderController);
|
||||
|
||||
@@ -1023,9 +1023,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7920</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7940</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7920</IISUrl>
|
||||
<IISUrl>http://localhost:7940</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
url += "&mode=crop";
|
||||
}
|
||||
}
|
||||
|
||||
var altText = Model.value.altText ?? Model.value.caption ?? string.Empty;
|
||||
|
||||
<img src="@url" alt="@Model.value.caption">
|
||||
<img src="@url" alt="@altText">
|
||||
|
||||
if (Model.value.caption != null)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="XsltTasks" />
|
||||
<delete assembly="umbraco" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<header>Macro</header>
|
||||
<usercontrol>/create/xslt.ascx</usercontrol>
|
||||
<tasks>
|
||||
<create assembly="umbraco" type="XsltTasks" />
|
||||
<delete assembly="umbraco" type="XsltTasks" />
|
||||
</tasks>
|
||||
</nodeType>
|
||||
|
||||
@@ -661,7 +661,7 @@
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Baggrundsfarve</key>
|
||||
<key alias="bold">Fed</key>
|
||||
<key alias="color">Tekst farve</key>
|
||||
<key alias="color">Tekstfarve</key>
|
||||
<key alias="font">Skrifttype</key>
|
||||
<key alias="text">Tekst</key>
|
||||
</area>
|
||||
@@ -1259,9 +1259,9 @@ Mange hilsner fra Umbraco robotten
|
||||
|
||||
|
||||
<key alias="styles">Typografi</key>
|
||||
<key alias="stylesDetails">Vælg, hvilke typografiværdier, en redaktør kan ændre</key>
|
||||
<key alias="stylesDetails">Vælg hvilke typografiværdier en redaktør kan ændre</key>
|
||||
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtaste json-konfiguration er gyldig</key>
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtastede json-konfiguration er gyldig</key>
|
||||
|
||||
<key alias="allowAllEditors">Tillad alle editorer</key>
|
||||
<key alias="allowAllRowConfigurations">Tillad alle rækkekonfigurationer</key>
|
||||
@@ -1272,7 +1272,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="areAdded">er tilføjet</key>
|
||||
|
||||
<key alias="maxItems">Maksimalt emner</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sat til 0 ubegrænset for</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sæt til 0 for ubegrænset</key>
|
||||
|
||||
</area>
|
||||
<area alias="contentTypeEditor">
|
||||
@@ -1282,7 +1282,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="addNewTab">Tilføj ny fane</key>
|
||||
<key alias="addAnotherTab">Tilføj endnu en fane</key>
|
||||
<key alias="inheritedFrom">Nedarvet fra</key>
|
||||
<key alias="addProperty">Tilføj property</key>
|
||||
<key alias="addProperty">Tilføj egenskab</key>
|
||||
<key alias="requiredLabel">Påkrævet label</key>
|
||||
|
||||
<key alias="enableListViewHeading">Aktiver listevisning</key>
|
||||
@@ -1473,7 +1473,6 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="noLogin">har endnu ikke logget ind</key>
|
||||
<key alias="oldPassword">Gammelt kodeord</key>
|
||||
<key alias="password">Adgangskode</key>
|
||||
<key alias="removePhoto">Fjern billede</key>
|
||||
<key alias="resetPassword">Nulstil kodeord</key>
|
||||
<key alias="passwordChanged">Dit kodeord er blevet ændret!</key>
|
||||
<key alias="passwordConfirm">Bekræft venligst dit nye kodeord</key>
|
||||
|
||||
@@ -229,6 +229,7 @@
|
||||
<key alias="removeTextBox">Remove this text box</key>
|
||||
<key alias="contentRoot">Content root</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Create a new Content Template from '%0%'</key>
|
||||
@@ -662,7 +663,20 @@
|
||||
<key alias="yellow">Yellow</key>
|
||||
<key alias="orange">Orange</key>
|
||||
<key alias="blue">Blue</key>
|
||||
<key alias="bluegrey">Blue Grey</key>
|
||||
<key alias="grey">Grey</key>
|
||||
<key alias="brown">Brown</key>
|
||||
<key alias="lightblue">Light Blue</key>
|
||||
<key alias="cyan">Cyan</key>
|
||||
<key alias="lightgreen">Light Green</key>
|
||||
<key alias="lime">Lime</key>
|
||||
<key alias="amber">Amber</key>
|
||||
<key alias="deeporange">Deep Orange</key>
|
||||
<key alias="red">Red</key>
|
||||
<key alias="pink">Pink</key>
|
||||
<key alias="purple">Purple</key>
|
||||
<key alias="deeppurple">Deep Purple</key>
|
||||
<key alias="indigo">Indigo</key>
|
||||
</area>
|
||||
|
||||
<area alias="shortcuts">
|
||||
|
||||
@@ -229,6 +229,7 @@
|
||||
<key alias="removeTextBox">Remove this text box</key>
|
||||
<key alias="contentRoot">Content root</key>
|
||||
<key alias="isSensitiveValue">This value is hidden. If you need access to view this value please contact your website administrator.</key>
|
||||
<key alias="isSensitiveValue_short">This value is hidden.</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Create a new Content Template from '%0%'</key>
|
||||
@@ -660,7 +661,20 @@
|
||||
<key alias="yellow">Yellow</key>
|
||||
<key alias="orange">Orange</key>
|
||||
<key alias="blue">Blue</key>
|
||||
<key alias="bluegrey">Blue Grey</key>
|
||||
<key alias="grey">Grey</key>
|
||||
<key alias="brown">Brown</key>
|
||||
<key alias="lightblue">Light Blue</key>
|
||||
<key alias="cyan">Cyan</key>
|
||||
<key alias="lightgreen">Light Green</key>
|
||||
<key alias="lime">Lime</key>
|
||||
<key alias="amber">Amber</key>
|
||||
<key alias="deeporange">Deep Orange</key>
|
||||
<key alias="red">Red</key>
|
||||
<key alias="pink">Pink</key>
|
||||
<key alias="purple">Purple</key>
|
||||
<key alias="deeppurple">Deep Purple</key>
|
||||
<key alias="indigo">Indigo</key>
|
||||
</area>
|
||||
<area alias="shortcuts">
|
||||
<key alias="addTab">Add tab</key>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<key alias="update">Bijwerken</key>
|
||||
</area>
|
||||
<area alias="assignDomain">
|
||||
<key alias="permissionDenied">Permission denied.</key>
|
||||
<key alias="permissionDenied">Toegang geweigerd.</key>
|
||||
<key alias="addNew">Nieuw domein toevoegen</key>
|
||||
<key alias="remove">verwijderen</key>
|
||||
<key alias="invalidNode">Ongeldige node.</key>
|
||||
@@ -1379,10 +1379,10 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
<key alias="httpsCheckEnableHttpsDescription">Zet in de appSettings van de web.config de umbracoSSL instelling op 'true'.</key>
|
||||
<key alias="httpsCheckEnableHttpsSuccess">De appSetting 'umbracoUseSSL' is nu ingesteld op 'true', cookies zullen als 'secure' worden aangemerkt.</key>
|
||||
|
||||
<key alias="rectifyButton">Fix</key>
|
||||
<key alias="cannotRectifyShouldNotEqual">Cannot fix a check with a value comparison type of 'ShouldNotEqual'.</key>
|
||||
<key alias="cannotRectifyShouldEqualWithValue">Cannot fix a check with a value comparison type of 'ShouldEqual' with a provided value.</key>
|
||||
<key alias="valueToRectifyNotProvided">Value to fix check not provided.</key>
|
||||
<key alias="rectifyButton">Herstellen</key>
|
||||
<key alias="cannotRectifyShouldNotEqual">Kan een controle met vergelijkingstype 'ShouldNotEqual' niet herstellen.</key>
|
||||
<key alias="cannotRectifyShouldEqualWithValue">Kan een controle met vergelijkingstype 'ShouldNotEqual' en gedefinieerde waarde niet herstellen.</key>
|
||||
<key alias="valueToRectifyNotProvided">Waarde om te herstellen niet gedefinieerd.</key>
|
||||
|
||||
<key alias="compilationDebugCheckSuccessMessage">Debug compiliate mode staat uit.</key>
|
||||
<key alias="compilationDebugCheckErrorMessage">Debug compiliate mode staat momenteel aan. Wij raden aan deze instelling uit te zetten voor livegang.</key>
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Examine.LuceneEngine.SearchCriteria;
|
||||
using Examine.SearchCriteria;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -33,10 +22,7 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Binders;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using umbraco;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Examine;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -96,16 +82,18 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (MembershipScenario == MembershipScenario.NativeUmbraco)
|
||||
{
|
||||
long totalRecords;
|
||||
var members = Services.MemberService
|
||||
.GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter).ToArray();
|
||||
.GetAll((pageNumber - 1), pageSize, out var totalRecords, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter).ToArray();
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return new PagedResult<MemberBasic>(0, 0, 0);
|
||||
}
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize);
|
||||
pagedResult.Items = members
|
||||
.Select(Mapper.Map<IMember, MemberBasic>);
|
||||
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = members
|
||||
.Select(x => AutoMapperExtensions.MapWithUmbracoContext<IMember, MemberBasic>(x, UmbracoContext))
|
||||
};
|
||||
return pagedResult;
|
||||
}
|
||||
else
|
||||
@@ -133,10 +121,13 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
return new PagedResult<MemberBasic>(0, 0, 0);
|
||||
}
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize);
|
||||
pagedResult.Items = members
|
||||
.Cast<MembershipUser>()
|
||||
.Select(Mapper.Map<MembershipUser, MemberBasic>);
|
||||
|
||||
var pagedResult = new PagedResult<MemberBasic>(totalRecords, pageNumber, pageSize)
|
||||
{
|
||||
Items = members
|
||||
.Cast<MembershipUser>()
|
||||
.Select(Mapper.Map<MembershipUser, MemberBasic>)
|
||||
};
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
@@ -437,7 +428,7 @@ namespace Umbraco.Web.Editors
|
||||
var sensitiveProperties = contentItem.PersistedContent.ContentType
|
||||
.PropertyTypes.Where(x => contentItem.PersistedContent.ContentType.IsSensitiveProperty(x.Alias))
|
||||
.ToList();
|
||||
|
||||
|
||||
foreach (var sensitiveProperty in sensitiveProperties)
|
||||
{
|
||||
//if found, change the value of the contentItem model to the persisted value so it remains unchanged
|
||||
@@ -665,7 +656,7 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.Email,
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
contentItem.IsApproved,
|
||||
contentItem.IsApproved,
|
||||
contentItem.PersistedContent.Key, //custom membership provider, we'll link that based on the IMember unique id (GUID)
|
||||
out status);
|
||||
|
||||
@@ -682,7 +673,7 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.Email,
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
"TEMP", //some membership provider's require something here even if q/a is disabled!
|
||||
contentItem.IsApproved,
|
||||
contentItem.IsApproved,
|
||||
newKey,
|
||||
out status);
|
||||
|
||||
@@ -828,17 +819,17 @@ namespace Umbraco.Web.Editors
|
||||
var member = ((MemberService)Services.MemberService).ExportMember(key);
|
||||
|
||||
var fileName = $"{member.Name}_{member.Email}.txt";
|
||||
|
||||
httpResponseMessage.Content = new ObjectContent<MemberExportModel>(member, new JsonMediaTypeFormatter {Indent = true});
|
||||
|
||||
httpResponseMessage.Content = new ObjectContent<MemberExportModel>(member, new JsonMediaTypeFormatter { Indent = true });
|
||||
httpResponseMessage.Content.Headers.Add("x-filename", fileName);
|
||||
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
|
||||
httpResponseMessage.StatusCode = HttpStatusCode.OK;
|
||||
|
||||
|
||||
return httpResponseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -70,14 +70,20 @@ namespace Umbraco.Web.Editors
|
||||
//Checking to see if the user has access to the required tour sections, else we remove the tour
|
||||
foreach (var backOfficeTourFile in result)
|
||||
{
|
||||
foreach (var tour in backOfficeTourFile.Tours)
|
||||
if (backOfficeTourFile.Tours != null)
|
||||
{
|
||||
foreach (var toursRequiredSection in tour.RequiredSections)
|
||||
foreach (var tour in backOfficeTourFile.Tours)
|
||||
{
|
||||
if (allowedSections.Contains(toursRequiredSection) == false)
|
||||
if (tour.RequiredSections != null)
|
||||
{
|
||||
toursToBeRemoved.Add(backOfficeTourFile);
|
||||
break;
|
||||
foreach (var toursRequiredSection in tour.RequiredSections)
|
||||
{
|
||||
if (allowedSections.Contains(toursRequiredSection) == false)
|
||||
{
|
||||
toursToBeRemoved.Add(backOfficeTourFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace Umbraco.Web.Models
|
||||
[DataContract(Name = "tour", Namespace = "")]
|
||||
public class BackOfficeTour
|
||||
{
|
||||
public BackOfficeTour()
|
||||
{
|
||||
RequiredSections = new List<string>();
|
||||
}
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
public string Name { get; set; }
|
||||
[DataMember(Name = "alias")]
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace Umbraco.Web.Models
|
||||
[DataContract(Name = "tourFile", Namespace = "")]
|
||||
public class BackOfficeTourFile
|
||||
{
|
||||
public BackOfficeTourFile()
|
||||
{
|
||||
Tours = new List<BackOfficeTour>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The file name for the tour
|
||||
/// </summary>
|
||||
@@ -27,4 +32,4 @@ namespace Umbraco.Web.Models
|
||||
[DataMember(Name = "tours")]
|
||||
public IEnumerable<BackOfficeTour> Tours { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "editor", IsRequired = false)]
|
||||
public string Editor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags the property to denote that it can contain sensitive data
|
||||
/// </summary>
|
||||
[DataMember(Name = "isSensitive", IsRequired = false)]
|
||||
public bool IsSensitive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used internally during model mapping
|
||||
@@ -38,4 +43,4 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
internal PropertyEditor PropertyEditor { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,17 +80,21 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//FROM IMember TO MemberBasic
|
||||
config.CreateMap<IMember, MemberBasic>()
|
||||
.ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
|
||||
.ForMember(display => display.Udi,
|
||||
expression =>
|
||||
expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key)))
|
||||
.ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver<IMember>()))
|
||||
.ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon))
|
||||
.ForMember(dto => dto.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(dto => dto.ContentTypeAlias,
|
||||
expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(dto => dto.Email, expression => expression.MapFrom(content => content.Email))
|
||||
.ForMember(dto => dto.Username, expression => expression.MapFrom(content => content.Username))
|
||||
.ForMember(dto => dto.Trashed, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Published, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Updater, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Alias, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore());
|
||||
.ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Properties, expression => expression.ResolveUsing(new MemberBasicPropertiesResolver()));
|
||||
|
||||
//FROM MembershipUser TO MemberBasic
|
||||
config.CreateMap<MembershipUser, MemberBasic>()
|
||||
@@ -395,6 +399,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//check permissions for viewing sensitive data
|
||||
if (isSensitiveProperty && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
//mark this property as sensitive
|
||||
prop.IsSensitive = true;
|
||||
//mark this property as readonly so that it does not post any data
|
||||
prop.Readonly = true;
|
||||
//replace this editor with a sensitivevalue
|
||||
@@ -477,8 +483,51 @@ namespace Umbraco.Web.Models.Mapping
|
||||
return AutoMapperExtensions.MapWithUmbracoContext<IMember, MemberDisplay>(member, context.GetUmbracoContext());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A resolver to map <see cref="IMember"/> properties to a collection of <see cref="ContentPropertyBasic"/>
|
||||
/// </summary>
|
||||
internal class MemberBasicPropertiesResolver : IValueResolver
|
||||
{
|
||||
public ResolutionResult Resolve(ResolutionResult source)
|
||||
{
|
||||
if (source.Value != null && (source.Value is IMember) == false)
|
||||
throw new AutoMapperMappingException(string.Format("Value supplied is of type {0} but expected {1}.\nChange the value resolver source type, or redirect the source value supplied to the value resolver using FromMember.", new object[]
|
||||
{
|
||||
source.Value.GetType(),
|
||||
typeof (IMember)
|
||||
}));
|
||||
return source.New(
|
||||
//perform the mapping with the current umbraco context
|
||||
ResolveCore(source.Context.GetUmbracoContext(), (IMember)source.Value), typeof(IEnumerable<ContentPropertyDisplay>));
|
||||
}
|
||||
|
||||
private IEnumerable<ContentPropertyBasic> ResolveCore(UmbracoContext umbracoContext, IMember content)
|
||||
{
|
||||
var result = Mapper.Map<IEnumerable<Property>, IEnumerable<ContentPropertyBasic>>(
|
||||
// Sort properties so items from different compositions appear in correct order (see U4-9298). Map sorted properties.
|
||||
content.Properties.OrderBy(prop => prop.PropertyType.SortOrder))
|
||||
.ToList();
|
||||
|
||||
var member = (IMember)content;
|
||||
var memberType = member.ContentType;
|
||||
|
||||
//now update the IsSensitive value
|
||||
foreach (var prop in result)
|
||||
{
|
||||
//check if this property is flagged as sensitive
|
||||
var isSensitiveProperty = memberType.IsSensitiveProperty(prop.Alias);
|
||||
//check permissions for viewing sensitive data
|
||||
if (isSensitiveProperty && umbracoContext.Security.CurrentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
//mark this property as sensitive
|
||||
prop.IsSensitive = true;
|
||||
//clear the value
|
||||
prop.Value = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
@@ -9,7 +7,6 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using umbraco;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
@@ -53,7 +50,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
//perform the mapping with the current umbraco context
|
||||
ResolveCore(source.Context.GetUmbracoContext(), (TSource)source.Value), typeof(List<Tab<ContentPropertyDisplay>>));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the container (listview) tab to the document
|
||||
/// </summary>
|
||||
@@ -275,7 +272,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//now add the user props
|
||||
contentProps.AddRange(currProps);
|
||||
|
||||
|
||||
//re-assign
|
||||
genericProps.Properties = contentProps;
|
||||
|
||||
@@ -308,6 +305,6 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
using (var wc = new HttpClient())
|
||||
{
|
||||
if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri))
|
||||
{
|
||||
wc.BaseAddress = baseUri;
|
||||
}
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
|
||||
//TODO: pass custom the authorization header, currently these aren't really secured!
|
||||
@@ -122,4 +126,4 @@ namespace Umbraco.Web.Scheduling
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Web.UI;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.BasePages;
|
||||
using Umbraco.Core.IO;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.UI;
|
||||
|
||||
namespace umbraco
|
||||
{
|
||||
@@ -15,31 +12,43 @@ namespace umbraco
|
||||
public override bool PerformSave()
|
||||
{
|
||||
Roles.CreateRole(Alias);
|
||||
_returnUrl = string.Format("members/EditMemberGroup.aspx?id={0}", System.Web.HttpContext.Current.Server.UrlEncode(Alias));
|
||||
_returnUrl = $"members/EditMemberGroup.aspx?id={System.Web.HttpContext.Current.Server.UrlEncode(Alias)}";
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool PerformDelete()
|
||||
{
|
||||
var roleDeleted = false;
|
||||
|
||||
// only built-in roles can be deleted
|
||||
if (Member.IsUsingUmbracoRoles())
|
||||
{
|
||||
MemberGroup.GetByName(Alias).delete();
|
||||
return true;
|
||||
roleDeleted = Roles.DeleteRole(Alias);
|
||||
}
|
||||
return false;
|
||||
|
||||
// Need to delete the member group from any content item that has it assigned in public access settings
|
||||
var publicAccessService = UmbracoContext.Current.Application.Services.PublicAccessService;
|
||||
var allPublicAccessRules = publicAccessService.GetAll();
|
||||
|
||||
// Find only rules which have the current role name (alias) assigned to them
|
||||
var rulesWithDeletedRoles = allPublicAccessRules.Where(x => x.Rules.Any(r => r.RuleValue == Alias));
|
||||
|
||||
var contentService = UmbracoContext.Current.Application.Services.ContentService;
|
||||
foreach (var publicAccessEntry in rulesWithDeletedRoles)
|
||||
{
|
||||
var contentItem = contentService.GetById(publicAccessEntry.ProtectedNodeId);
|
||||
var rulesToDelete = publicAccessEntry.Rules.ToList();
|
||||
foreach (var rule in rulesToDelete)
|
||||
publicAccessService.RemoveRule(contentItem, rule.RuleType, rule.RuleValue);
|
||||
}
|
||||
|
||||
return roleDeleted;
|
||||
}
|
||||
|
||||
private string _returnUrl = "";
|
||||
|
||||
public override string ReturnUrl
|
||||
{
|
||||
get { return _returnUrl; }
|
||||
}
|
||||
public override string ReturnUrl => _returnUrl;
|
||||
|
||||
public override string AssignedApp
|
||||
{
|
||||
get { return DefaultApps.member.ToString(); }
|
||||
}
|
||||
public override string AssignedApp => DefaultApps.member.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user