Merge branch temp8 into temp8-di2690
@@ -27,4 +27,10 @@ dotnet_naming_symbols.private_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
|
||||
|
||||
dotnet_naming_style.prefix_underscore.capitalization = camel_case
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
|
||||
# https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/ide/editorconfig-code-style-settings-reference.md
|
||||
[*.cs]
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
@@ -129,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||

|
||||
|
||||
@@ -156,4 +156,4 @@ 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))
|
||||
(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))
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: File a bug report, if you've discovered a problem in Umbraco.
|
||||
---
|
||||
|
||||
A brief description of the issue goes here.
|
||||
|
||||
<!--
|
||||
|
||||
If you haven't yet done so, please read the "contributing guidelines"
|
||||
thoroughly. Then, proceed by filling out the rest of the details in the issue
|
||||
template below. The more details you can give us, the easier it will be for us
|
||||
to determine the cause of a problem.
|
||||
|
||||
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
Reproduction
|
||||
------------
|
||||
|
||||
If you're filing a bug, please describe how to reproduce it. Include as much
|
||||
relevant information as possible, such as:
|
||||
|
||||
### Bug summary
|
||||
|
||||
<!--
|
||||
* Write a short summary of the bug
|
||||
* Try to pinpoint it as much as possible
|
||||
* Try to state the _actual problem_, and not just what you _think_ the
|
||||
solution might be.
|
||||
-->
|
||||
|
||||
### Specifics
|
||||
|
||||
<!--
|
||||
* Mention the URL where this bug occurs, if applicable
|
||||
* What version of Umbraco are you using (down to the very last digit!)
|
||||
* What browser and version you are using
|
||||
* Please mention if you've checked it in other browsers as well
|
||||
* Please include *full error messages* and *screenshots* if possible
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--
|
||||
* Clearly mention the steps to reproduce the bug
|
||||
-->
|
||||
|
||||
### Expected result
|
||||
|
||||
<!--
|
||||
* What did you _expect_ that would happen on your Umbraco site?
|
||||
* Describe the intended/desired outcome after you did the steps mentioned.
|
||||
-->
|
||||
|
||||
### Actual result
|
||||
|
||||
<!--
|
||||
* What is the actual result of the above steps?
|
||||
* Describe the behaviour of the bug
|
||||
* Please, please include **error messages** and screenshots. They might mean
|
||||
nothing to you, but they are _very_ helpful to us.
|
||||
-->
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: 📮 Feature Request
|
||||
about: Open a feature request, if you want to propose a new feature.
|
||||
---
|
||||
|
||||
A brief description of your feature request goes here.
|
||||
|
||||
|
||||
<!--
|
||||
If you want to discuss the feature you're imagining, please make sure to keep
|
||||
those discussions on the forum at https://our.umbraco.com/ (choose the
|
||||
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
|
||||
|
||||
Once you've come to a conclusion in the discussion, feel free to propose the
|
||||
new feature here.
|
||||
-->
|
||||
|
||||
How can you help?
|
||||
-------------------------------
|
||||
|
||||
<!--
|
||||
The resources (read: available time and effort) of Umbraco's core team are
|
||||
limited.
|
||||
|
||||
If we can not work on your suggestion, please don't take it personally. Most
|
||||
likely, it's either:
|
||||
|
||||
- We think your idea is valid, but we can't find the time to work on it.
|
||||
- Your idea might be better suited as a package, if it's not suitable for
|
||||
the majority of users.
|
||||
-->
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: ⁉️ Support Question
|
||||
about: Having trouble with Umbraco? -> https://our.umbraco.com
|
||||
---
|
||||
|
||||
This issue tracker is NOT meant for support questions. If you have a question,
|
||||
please join us on the forum at https://our.umbraco.com.
|
||||
|
||||
Thanks!
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: 📖 Documentation Issue
|
||||
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
|
||||
---
|
||||
|
||||
The Umbraco documentation has its own dedicated repository. Please open your
|
||||
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
|
||||
|
||||
Thanks!
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: 🔐 Security Issue
|
||||
about: Discovered a Security Issue in Umbraco?
|
||||
---
|
||||
|
||||
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
|
||||
|
||||
If you have found a security issue in Umbraco, please send the details to
|
||||
security@umbraco.com and don't disclose it publicly until we can provide a fix for
|
||||
it. If you wish, we'll credit you for finding verified issues, when we release
|
||||
the patched version.
|
||||
|
||||
❗ Please read more about how to report security issues on https://umbraco.com/security
|
||||
|
||||
A note on "Self XSS"
|
||||
--------------------
|
||||
|
||||
Umbraco is a CMS, that allows users to edit content on a website. As such,
|
||||
all _authenticated users_ can:
|
||||
|
||||
- Edit content, and (depending on the field types) insert HTML and CSS in that
|
||||
content, with a variety of allowed attributes.
|
||||
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
|
||||
javascript in so on.
|
||||
- Upload files to the site, which will become publicly available.
|
||||
|
||||
We see these functionalities as _features_, and not as security issues. Please
|
||||
report the mentioned items only if they can be performed by non-authorized
|
||||
users, or other exploitable vulnerabilities.
|
||||
|
||||
Thanks!
|
||||
@@ -0,0 +1,11 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
|
||||
- [ ] I have added steps to test this contribution in the description below
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -1,92 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.1.19,2.999999)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.2.19,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="LightInject" version="[5.1.2,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.CodeAnalysis.CSharp" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[1.0.8,1.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.999999)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
|
||||
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.3,3.999999)" />
|
||||
<dependency id="Semver" version="[2.0.4,2.999999)" />
|
||||
<dependency id="Serilog" version="[2.7.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Process" version="[2.0.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Thread" version="[3.0.0,3.999999)" />
|
||||
<dependency id="Serilog.Filters.Expressions" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Serilog.Formatting.Compact" version="[1.0.0,1.999999)" />
|
||||
<dependency id="Serilog.Settings.AppSettings" version="[2.1.2,2.999999)" />
|
||||
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
|
||||
<dependency id="System.Reflection.Primitives" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Runtime.Handles" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Security.Cryptography.X509Certificates" version="[4.3.2,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="LightInject" version="[5.1.2,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Web" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Core" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi.Client" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.Owin" version="[4.0.0,4.999999)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
|
||||
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
|
||||
<dependency id="Semver" version="[2.0.4,2.999999)" />
|
||||
<dependency id="Serilog" version="[2.7.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Process" version="[2.0.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Thread" version="[3.0.0,3.999999)" />
|
||||
<dependency id="Serilog.Filters.Expressions" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Serilog.Formatting.Compact" version="[1.0.0,1.999999)" />
|
||||
<dependency id="Serilog.Settings.AppSettings" version="[2.1.2,2.999999)" />
|
||||
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.4,3.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- libs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.UI.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web.UI\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Web</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the web assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.2.25,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- libs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -1,58 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.22]" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
|
||||
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Web" version="[$version$]" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.22]" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.3.25,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.9.0,2.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- files -->
|
||||
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
|
||||
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.htm" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.htm" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\package.manifest" target="Content\App_Plugins\ModelsBuilder\package.manifest" />
|
||||
<!-- these files are copied by install.ps1 -->
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
|
||||
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
|
||||
<!-- tools -->
|
||||
<!-- beware! install.ps1 not supported by PackageReference -->
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
<!-- config transforms -->
|
||||
<!-- beware! config transforms not supported by PackageReference -->
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
|
||||
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" /> <!-- FIXME Content\ !! and then... transform?! -->
|
||||
|
||||
<!-- UmbracoCms props and targets -->
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -47,9 +47,6 @@
|
||||
<CustomFilesToInclude Include=".\umbraco\**\*">
|
||||
<Dir>umbraco</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco_client\**\*">
|
||||
<Dir>umbraco_client</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\Global.asax">
|
||||
<Dir>.</Dir>
|
||||
</CustomFilesToInclude>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
- Umbraco
|
||||
|
||||
@@ -1,39 +1,30 @@
|
||||
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.com/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
Depending on the version you are upgrading from, you may need to make some changes to your web.config
|
||||
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
|
||||
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
We've done our best to transform your configuration files but in case something is not quite right: remember we
|
||||
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
|
||||
|
||||
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
|
||||
a package might have added. Only the existing files were overwritten. If you customized anything then make
|
||||
We've overwritten all the files in the Umbraco folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
|
||||
a package might have added. Only the existing files were overwritten. If you customized anything then make
|
||||
sure to do a compare and merge with the NuGetBackup folder.
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
- Umbraco
|
||||
|
||||
@@ -150,10 +150,6 @@
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
|
||||
@@ -44,14 +44,6 @@ if ($project) {
|
||||
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
|
||||
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientFolder
|
||||
$umbracoClientFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco_Client"
|
||||
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
|
||||
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
|
||||
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
|
||||
|
||||
$copyWebconfig = $true
|
||||
$destinationWebConfig = Join-Path $projectPath "Web.config"
|
||||
|
||||
@@ -85,15 +77,7 @@ if ($project) {
|
||||
$splashesDestination = Join-Path $projectPath "Config\splashes\"
|
||||
New-Item $splashesDestination -Type directory
|
||||
Copy-Item $splashesSource $splashesDestination -Force
|
||||
|
||||
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
|
||||
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
|
||||
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
|
||||
|
||||
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
|
||||
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
|
||||
Copy-Item $sqlCex86source $sqlCex86Destination -Force
|
||||
|
||||
|
||||
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
@@ -159,4 +143,4 @@ if ($project) {
|
||||
{
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\ReadmeUpgrade.txt')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
$global:node_nodepath = $this.ClearEnvVar("NODEPATH")
|
||||
$global:node_npmcache = $this.ClearEnvVar("NPM_CONFIG_CACHE")
|
||||
$global:node_npmprefix = $this.ClearEnvVar("NPM_CONFIG_PREFIX")
|
||||
|
||||
# https://github.com/gruntjs/grunt-contrib-connect/issues/235
|
||||
$this.SetEnvVar("NODE_NO_HTTP2", "1")
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("RestoreNode",
|
||||
@@ -78,6 +81,8 @@
|
||||
$this.SetEnvVar("NODEPATH", $node_nodepath)
|
||||
$this.SetEnvVar("NPM_CONFIG_CACHE", $node_npmcache)
|
||||
$this.SetEnvVar("NPM_CONFIG_PREFIX", $node_npmprefix)
|
||||
|
||||
$ignore = $this.ClearEnvVar("NODE_NO_HTTP2")
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("CompileBelle",
|
||||
@@ -124,7 +129,7 @@
|
||||
|
||||
Write-Output "### install gulp-cli" >> $log 2>&1
|
||||
&npm install -g gulp-cli --quiet >> $log 2>&1
|
||||
if (-not $?) { throw "Failed to install gulp-cli" } # that one is expected to work
|
||||
$error.Clear() # that one fails 'cos some files not being removed - ignore
|
||||
|
||||
Write-Output "### gulp build for version $($this.Version.Release)" >> $log 2>&1
|
||||
&gulp build --buildversion=$this.Version.Release >> $log 2>&1
|
||||
@@ -399,9 +404,15 @@
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Web.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Web." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version $this.Version.Semver.ToString() `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cms.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms." }
|
||||
|
||||
@@ -417,7 +428,7 @@
|
||||
$ubuild.DefineMethod("VerifyNuGet",
|
||||
{
|
||||
$this.VerifyNuGetConsistency(
|
||||
("UmbracoCms", "UmbracoCms.Core"),
|
||||
("UmbracoCms", "UmbracoCms.Core", "UmbracoCms.Web"),
|
||||
("Umbraco.Core", "Umbraco.Web", "Umbraco.Web.UI", "Umbraco.Examine"))
|
||||
if ($this.OnError()) { return }
|
||||
})
|
||||
@@ -427,7 +438,7 @@
|
||||
Write-Host "Prepare Azure Gallery"
|
||||
$this.CopyFile("$($this.SolutionRoot)\build\Azure\azuregalleryrelease.ps1", $this.BuildOutput)
|
||||
})
|
||||
|
||||
|
||||
$ubuild.DefineMethod("Build",
|
||||
{
|
||||
$error.Clear()
|
||||
@@ -457,6 +468,7 @@
|
||||
if ($this.OnError()) { return }
|
||||
$this.PrepareAzureGallery()
|
||||
if ($this.OnError()) { return }
|
||||
Write-Host "Done"
|
||||
})
|
||||
|
||||
# ################################################################
|
||||
@@ -472,5 +484,4 @@
|
||||
$ubuild.Build()
|
||||
if ($ubuild.OnError()) { return }
|
||||
}
|
||||
Write-Host "Done"
|
||||
if ($get) { return $ubuild }
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have written a descriptive pull-request title
|
||||
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
@@ -19,4 +19,4 @@ using System.Resources;
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.49")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.50")]
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -11,7 +10,7 @@ using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
public sealed class AuditEventsComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
{
|
||||
@@ -53,18 +52,6 @@ namespace Umbraco.Core.Auditing
|
||||
_userService = userService;
|
||||
_entityService = entityService;
|
||||
|
||||
//BackOfficeUserManager.AccountLocked += ;
|
||||
//BackOfficeUserManager.AccountUnlocked += ;
|
||||
BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
|
||||
BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
|
||||
BackOfficeUserManager.LoginFailed += OnLoginFailed;
|
||||
//BackOfficeUserManager.LoginRequiresVerification += ;
|
||||
BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
|
||||
BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
|
||||
BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
|
||||
BackOfficeUserManager.PasswordReset += OnPasswordReset;
|
||||
//BackOfficeUserManager.ResetAccessFailedCount += ;
|
||||
|
||||
UserService.SavedUserGroup += OnSavedUserGroupWithUsers;
|
||||
|
||||
UserService.SavedUser += OnSavedUser;
|
||||
@@ -255,64 +242,6 @@ namespace Umbraco.Core.Auditing
|
||||
"umbraco/user/delete", "delete user");
|
||||
}
|
||||
|
||||
private void OnLoginSuccess(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs)
|
||||
{
|
||||
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
|
||||
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/login", "login success");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogoutSuccess(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs)
|
||||
{
|
||||
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
|
||||
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/logout", "logout success");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordReset(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/reset", "password reset");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordChanged(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/change", "password change");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoginFailed(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, 0, identityArgs.IpAddress, "umbraco/user/sign-in/failed", "login failed", affectedDetails: "");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForgotPasswordChange(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/change", "password forgot/change");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForgotPasswordRequest(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/request", "password forgot/request");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteAudit(int performingId, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
|
||||
{
|
||||
var performingUser = _userService.GetUserById(performingId);
|
||||
@@ -1,11 +1,9 @@
|
||||
using System.IO;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
|
||||
namespace Umbraco.Core.Strategies
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public class ManifestWatcherComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Strategies
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
//TODO: This should just exist in the content service/repo!
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Components;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Strategies
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public sealed class RelateOnTrashComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
@@ -1,9 +1,24 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public static class ContentSectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file extension corresponds to an image.
|
||||
/// </summary>
|
||||
/// <param name="extension">The file extension.</param>
|
||||
/// <param name="contentConfig"></param>
|
||||
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
|
||||
public static bool IsImageFile(this IContentSection contentConfig, string extension)
|
||||
{
|
||||
if (contentConfig == null) throw new ArgumentNullException(nameof(contentConfig));
|
||||
if (extension == null) return false;
|
||||
extension = extension.TrimStart('.');
|
||||
return contentConfig.ImageFileTypes.InvariantContains(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if file extension is allowed for upload based on (optional) white list and black list
|
||||
/// held in settings.
|
||||
@@ -15,5 +30,17 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
(contentSection.AllowedUploadFiles.Any() == false &&
|
||||
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the auto-fill configuration for a specified property alias.
|
||||
/// </summary>
|
||||
/// <param name="contentSection"></param>
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <returns>The auto-fill configuration for the specified property alias, or null.</returns>
|
||||
public static IImagingAutoFillUploadField GetConfig(this IContentSection contentSection, string propertyTypeAlias)
|
||||
{
|
||||
var autoFillConfigs = contentSection.ImageAutoFillProperties;
|
||||
return autoFillConfigs?.FirstOrDefault(x => x.Alias == propertyTypeAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
bool DisableAlternativeTemplates { get; }
|
||||
|
||||
bool ValidateAlternativeTemplates { get; }
|
||||
|
||||
bool DisableFindContentByIdPath { get; }
|
||||
|
||||
bool DisableRedirectUrlTracking { get; }
|
||||
@@ -16,5 +18,4 @@
|
||||
|
||||
string UmbracoApplicationUrl { get; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,44 +5,27 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
internal class WebRoutingElement : ConfigurationElement, IWebRoutingSection
|
||||
{
|
||||
[ConfigurationProperty("trySkipIisCustomErrors", DefaultValue = "false")]
|
||||
public bool TrySkipIisCustomErrors
|
||||
{
|
||||
get { return (bool) base["trySkipIisCustomErrors"]; }
|
||||
}
|
||||
public bool TrySkipIisCustomErrors => (bool) base["trySkipIisCustomErrors"];
|
||||
|
||||
[ConfigurationProperty("internalRedirectPreservesTemplate", DefaultValue = "false")]
|
||||
public bool InternalRedirectPreservesTemplate
|
||||
{
|
||||
get { return (bool) base["internalRedirectPreservesTemplate"]; }
|
||||
}
|
||||
public bool InternalRedirectPreservesTemplate => (bool) base["internalRedirectPreservesTemplate"];
|
||||
|
||||
[ConfigurationProperty("disableAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool DisableAlternativeTemplates
|
||||
{
|
||||
get { return (bool) base["disableAlternativeTemplates"]; }
|
||||
}
|
||||
public bool DisableAlternativeTemplates => (bool) base["disableAlternativeTemplates"];
|
||||
|
||||
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool ValidateAlternativeTemplates => (bool) base["validateAlternativeTemplates"];
|
||||
|
||||
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
|
||||
public bool DisableFindContentByIdPath
|
||||
{
|
||||
get { return (bool) base["disableFindContentByIdPath"]; }
|
||||
}
|
||||
public bool DisableFindContentByIdPath => (bool) base["disableFindContentByIdPath"];
|
||||
|
||||
[ConfigurationProperty("disableRedirectUrlTracking", DefaultValue = "false")]
|
||||
public bool DisableRedirectUrlTracking
|
||||
{
|
||||
get { return (bool) base["disableRedirectUrlTracking"]; }
|
||||
}
|
||||
public bool DisableRedirectUrlTracking => (bool) base["disableRedirectUrlTracking"];
|
||||
|
||||
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
|
||||
public string UrlProviderMode
|
||||
{
|
||||
get { return (string) base["urlProviderMode"]; }
|
||||
}
|
||||
public string UrlProviderMode => (string) base["urlProviderMode"];
|
||||
|
||||
[ConfigurationProperty("umbracoApplicationUrl", DefaultValue = null)]
|
||||
public string UmbracoApplicationUrl
|
||||
{
|
||||
get { return (string)base["umbracoApplicationUrl"]; }
|
||||
}
|
||||
public string UmbracoApplicationUrl => (string)base["umbracoApplicationUrl"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <summary>
|
||||
/// Gets the version comment of the executing code (eg "beta").
|
||||
/// </summary>
|
||||
public static string CurrentComment => "alpha.49";
|
||||
public static string CurrentComment => "alpha.50";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly version of Umbraco.Code.dll.
|
||||
|
||||
@@ -7,12 +7,13 @@ using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class ContentExtensions
|
||||
{
|
||||
@@ -241,30 +242,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
#region SetValue for setting file contents
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
|
||||
{
|
||||
// ensure we get the filename without the path in IE in intranet mode
|
||||
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
|
||||
var filename = value.FileName;
|
||||
var pos = filename.LastIndexOf(@"\", StringComparison.InvariantCulture);
|
||||
if (pos > 0)
|
||||
filename = filename.Substring(pos + 1);
|
||||
|
||||
// strip any directory info
|
||||
pos = filename.LastIndexOf(IOHelper.DirSepChar);
|
||||
if (pos > 0)
|
||||
filename = filename.Substring(pos + 1);
|
||||
|
||||
// get a safe & clean filename
|
||||
filename = IOHelper.SafeFileName(filename);
|
||||
if (string.IsNullOrWhiteSpace(filename)) return;
|
||||
filename = filename.ToLower(); // fixme - er... why?
|
||||
|
||||
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream, culture, segment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
@@ -281,7 +258,31 @@ namespace Umbraco.Core.Models
|
||||
if (string.IsNullOrWhiteSpace(filename)) return;
|
||||
filename = filename.ToLower(); // fixme - er... why?
|
||||
|
||||
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
|
||||
SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
|
||||
}
|
||||
|
||||
private static void SetUploadFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? MediaFileSystem.GetRelativePath(svalue) : null;
|
||||
var filepath = MediaFileSystem.StoreFile(content, property.PropertyType, filename, filestream, oldpath);
|
||||
property.SetValue(MediaFileSystem.GetUrl(filepath), culture, segment);
|
||||
}
|
||||
|
||||
// gets or creates a property for a content item.
|
||||
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
|
||||
{
|
||||
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (property != null) return property;
|
||||
|
||||
var propertyType = content.GetContentType().CompositionPropertyTypes
|
||||
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (propertyType == null)
|
||||
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
|
||||
|
||||
property = new Property(propertyType);
|
||||
content.Properties.Add(property);
|
||||
return property;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -8,7 +7,6 @@ using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Media.Exif;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
@@ -26,8 +24,6 @@ namespace Umbraco.Core.IO
|
||||
Logger = logger;
|
||||
MediaPathScheme = mediaPathScheme;
|
||||
MediaPathScheme.Initialize(this);
|
||||
|
||||
UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig);
|
||||
}
|
||||
|
||||
private IMediaPathScheme MediaPathScheme { get; }
|
||||
@@ -35,9 +31,7 @@ namespace Umbraco.Core.IO
|
||||
private IContentSection ContentConfig { get; }
|
||||
|
||||
private ILogger Logger { get; }
|
||||
|
||||
internal UploadAutoFillProperties UploadAutoFillProperties { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all files passed in.
|
||||
/// </summary>
|
||||
@@ -204,113 +198,9 @@ namespace Umbraco.Core.IO
|
||||
return filepath;
|
||||
}
|
||||
|
||||
// gets or creates a property for a content item.
|
||||
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
|
||||
{
|
||||
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (property != null) return property;
|
||||
|
||||
var propertyType = content.GetContentType().CompositionPropertyTypes
|
||||
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (propertyType == null)
|
||||
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
|
||||
|
||||
property = new Property(propertyType);
|
||||
content.Properties.Add(property);
|
||||
return property;
|
||||
}
|
||||
|
||||
// fixme - what's below belongs to the upload property editor, not the media filesystem!
|
||||
|
||||
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
|
||||
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
|
||||
property.SetValue(GetUrl(filepath), culture, segment);
|
||||
SetUploadFile(content, property, filepath, filestream, culture, segment);
|
||||
}
|
||||
|
||||
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
// fixme delete?
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
|
||||
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
|
||||
DeleteFile(oldpath);
|
||||
property.SetValue(GetUrl(filepath), culture, segment);
|
||||
using (var filestream = OpenFile(filepath))
|
||||
{
|
||||
SetUploadFile(content, property, filepath, filestream, culture, segment);
|
||||
}
|
||||
}
|
||||
|
||||
// sets a file for the FileUpload property editor
|
||||
// ie generates thumbnails and populates autofill properties
|
||||
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file extension corresponds to an image.
|
||||
/// </summary>
|
||||
/// <param name="extension">The file extension.</param>
|
||||
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
|
||||
public bool IsImageFile(string extension)
|
||||
{
|
||||
if (extension == null) return false;
|
||||
extension = extension.TrimStart('.');
|
||||
return ContentConfig.ImageFileTypes.InvariantContains(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dimensions of an image.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream containing the image bytes.</param>
|
||||
/// <returns>The dimension of the image.</returns>
|
||||
/// <remarks>First try with EXIF as it is faster and does not load the entire image
|
||||
/// in memory. Fallback to GDI which means loading the image in memory and thus
|
||||
/// use potentially large amounts of memory.</remarks>
|
||||
public Size GetDimensions(Stream stream)
|
||||
{
|
||||
//Try to load with exif
|
||||
try
|
||||
{
|
||||
var jpgInfo = ImageFile.FromStream(stream);
|
||||
|
||||
if (jpgInfo.Format != ImageFileFormat.Unknown
|
||||
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
|
||||
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
|
||||
{
|
||||
var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
|
||||
var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
|
||||
if (height > 0 && width > 0)
|
||||
{
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//We will just swallow, just means we can't read exif data, we don't want to log an error either
|
||||
}
|
||||
|
||||
//we have no choice but to try to read in via GDI
|
||||
using (var image = Image.FromStream(stream))
|
||||
{
|
||||
|
||||
var fileWidth = image.Width;
|
||||
var fileHeight = image.Height;
|
||||
return new Size(fileWidth, fileHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string Umbraco => IOHelper.ReturnPath("umbracoPath", "~/umbraco");
|
||||
|
||||
[Obsolete("This will be removed, there is no more umbraco_client folder")]
|
||||
public static string UmbracoClient => IOHelper.ReturnPath("umbracoClientPath", "~/umbraco_client");
|
||||
|
||||
public static string UserControls => IOHelper.ReturnPath("umbracoUsercontrolsPath", "~/usercontrols");
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public static class ImageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the MIME type of an image.
|
||||
/// </summary>
|
||||
/// <param name="image">The image.</param>
|
||||
/// <returns>The MIME type of the image.</returns>
|
||||
public static string GetMimeType(this Image image)
|
||||
{
|
||||
var format = image.RawFormat;
|
||||
var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid);
|
||||
return codec.MimeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,26 +280,6 @@ namespace Umbraco.Core.Models
|
||||
Properties.Add(property);
|
||||
}
|
||||
|
||||
// HttpPostedFileBase is the base class that can be mocked
|
||||
// HttpPostedFile is what we get in ASP.NET
|
||||
// HttpPostedFileWrapper wraps sealed HttpPostedFile as HttpPostedFileBase
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
public virtual void SetValue(string propertyTypeAlias, HttpPostedFile value, string culture = null, string segment = null)
|
||||
{
|
||||
ContentExtensions.SetValue(this, propertyTypeAlias, new HttpPostedFileWrapper(value), culture, segment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
public virtual void SetValue(string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
|
||||
{
|
||||
ContentExtensions.SetValue(this, propertyTypeAlias, value, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Copy
|
||||
|
||||
@@ -98,6 +98,30 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateId">The template id to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
|
||||
public bool IsAllowedTemplate(int templateId)
|
||||
{
|
||||
return AllowedTemplates == null
|
||||
? false
|
||||
: AllowedTemplates.Any(t => t.Id == templateId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateAlias">The template alias to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
|
||||
public bool IsAllowedTemplate(string templateAlias)
|
||||
{
|
||||
return AllowedTemplates == null
|
||||
? false
|
||||
: AllowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default template for the ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -172,10 +172,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <returns>A value indicating whether the culture can be published.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Fails if values cannot be published, e.g. if some values are not valid.</para>
|
||||
/// <para>Fails if properties don't pass variant validtion rules.</para>
|
||||
/// <para>Publishing must be finalized via the content service SavePublishing method.</para>
|
||||
/// </remarks>
|
||||
// fixme - should return an attempt with error results
|
||||
bool PublishCulture(string culture = "*");
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Models
|
||||
// fixme validate published cultures?
|
||||
|
||||
/// <summary>
|
||||
/// Validates the content item's properties.
|
||||
/// Validates the content item's properties pass variant rules
|
||||
/// </summary>
|
||||
/// <para>If the content type is variant, then culture can be either '*' or an actual culture, but neither 'null' nor
|
||||
/// 'empty'. If the content type is invariant, then culture can be either '*' or null or empty.</para>
|
||||
|
||||
@@ -17,6 +17,20 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
IEnumerable<ITemplate> AllowedTemplates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateId">The template id to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
|
||||
bool IsAllowedTemplate(int templateId);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateAlias">The template alias to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
|
||||
bool IsAllowedTemplate(string templateAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default template for the ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -93,14 +93,6 @@ namespace Umbraco.Core.Models.Identity
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
}
|
||||
|
||||
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager<BackOfficeIdentityUser> manager)
|
||||
{
|
||||
// NOTE the authenticationType must match the umbraco one
|
||||
// defined in CookieAuthenticationOptions.AuthenticationType
|
||||
var userIdentity = await manager.CreateIdentityAsync(this, Constants.Security.BackOfficeAuthenticationType);
|
||||
return userIdentity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if an Id has been set on this object this will be false if the object is new and not peristed to the database
|
||||
/// </summary>
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null)
|
||||
if (LastLoginDate == default && IsApproved == false && InvitedDate != null)
|
||||
return UserState.Invited;
|
||||
|
||||
if (IsLockedOut)
|
||||
@@ -268,6 +268,10 @@ namespace Umbraco.Core.Models.Membership
|
||||
if (IsApproved == false)
|
||||
return UserState.Disabled;
|
||||
|
||||
// User is not disabled or locked and has never logged in before
|
||||
if (LastLoginDate == default && IsApproved && IsLockedOut == false)
|
||||
return UserState.Inactive;
|
||||
|
||||
return UserState.Active;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
Active = 0,
|
||||
Disabled = 1,
|
||||
LockedOut = 2,
|
||||
Invited = 3
|
||||
Invited = 3,
|
||||
Inactive = 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
|
||||
@@ -10,9 +10,6 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Returns the machine name that is safe to use in file paths.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// see: https://github.com/Shandem/ClientDependency/issues/4
|
||||
/// </remarks>
|
||||
public static string FileSafeMachineName
|
||||
{
|
||||
get { return MachineName.ReplaceNonAlphanumericChars('-'); }
|
||||
|
||||
@@ -150,6 +150,8 @@ UNION
|
||||
SELECT '4CountOfLockedOut' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userNoConsole = 1
|
||||
UNION
|
||||
SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL
|
||||
UNION
|
||||
SELECT '6CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL
|
||||
ORDER BY colName";
|
||||
|
||||
var result = Database.Fetch<dynamic>(sql);
|
||||
@@ -160,7 +162,8 @@ ORDER BY colName";
|
||||
{UserState.Active, (int) result[1].num},
|
||||
{UserState.Disabled, (int) result[2].num},
|
||||
{UserState.LockedOut, (int) result[3].num},
|
||||
{UserState.Invited, (int) result[4].num}
|
||||
{UserState.Invited, (int) result[4].num},
|
||||
{UserState.Inactive, (int) result[5].num}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -766,6 +769,12 @@ ORDER BY colName";
|
||||
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL)");
|
||||
appended = true;
|
||||
}
|
||||
if (userState.Contains(UserState.Inactive))
|
||||
{
|
||||
if (appended) sb.Append(" OR ");
|
||||
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL)");
|
||||
appended = true;
|
||||
}
|
||||
if (userState.Contains(UserState.Disabled))
|
||||
{
|
||||
if (appended) sb.Append(" OR ");
|
||||
|
||||
@@ -143,19 +143,19 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(IDatabase db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TableName = t.Name,ColumnName = c.Name,dc.Name,dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id");
|
||||
var items = db.Fetch<dynamic>("SELECT TableName = t.Name, ColumnName = c.Name, dc.Name, dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id INNER JOIN sys.schemas as s on t.[schema_id] = s.[schema_id] WHERE s.name = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetTablesInSchema(IDatabase db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
|
||||
}
|
||||
|
||||
public override IEnumerable<ColumnInfo> GetColumnsInSchema(IDatabase db)
|
||||
{
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS");
|
||||
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return
|
||||
items.Select(
|
||||
item =>
|
||||
@@ -168,7 +168,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE");
|
||||
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
{
|
||||
var items =
|
||||
db.Fetch<dynamic>(
|
||||
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE");
|
||||
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
|
||||
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
|
||||
}
|
||||
|
||||
@@ -191,7 +191,8 @@ CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [U
|
||||
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
|
||||
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
|
||||
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
|
||||
WHERE I.is_primary_key = 0
|
||||
inner join sys.schemas as S on T.[schema_id] = S.[schema_id]
|
||||
WHERE S.name = (SELECT SCHEMA_NAME()) AND I.is_primary_key = 0
|
||||
order by T.name, I.name");
|
||||
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
|
||||
item.UNIQUE == 1)).ToList();
|
||||
@@ -201,7 +202,7 @@ order by T.name, I.name");
|
||||
public override bool DoesTableExist(IDatabase db, string tableName)
|
||||
{
|
||||
var result =
|
||||
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
|
||||
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = (SELECT SCHEMA_NAME())",
|
||||
new { TableName = tableName });
|
||||
|
||||
return result > 0;
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool HasFocalPoint()
|
||||
=> FocalPoint != null && FocalPoint.Left != 0.5m && FocalPoint.Top != 0.5m;
|
||||
=> FocalPoint != null && (FocalPoint.Left != 0.5m || FocalPoint.Top != 0.5m);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the value has a specified crop.
|
||||
|
||||
@@ -720,7 +720,7 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
else
|
||||
{
|
||||
//if the salt bytes is too long for the required key length for the algorithm, extend it
|
||||
//if the salt bytes is too short for the required key length for the algorithm, extend it
|
||||
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
|
||||
var dstOffset = 0;
|
||||
while (dstOffset < numArray2.Length)
|
||||
|
||||
@@ -645,7 +645,7 @@ namespace Umbraco.Core.Services.Implement
|
||||
{
|
||||
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
|
||||
{
|
||||
return _userRepository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username);
|
||||
return _userRepository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ namespace Umbraco.Core.Services
|
||||
/// Represents the result of a service operation.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResultType">The type of the result type.</typeparam>
|
||||
/// <remarks>Type <typeparamref name="TResultType"/> must be an enumeration, and its
|
||||
/// underlying type must be byte. Values indicating success should be in the 0-127
|
||||
/// range, while values indicating failure should be in the 128-255 range. See
|
||||
/// <see cref="OperationResultType"/> for a base implementation.</remarks>
|
||||
public class OperationResult<TResultType>
|
||||
where TResultType : struct
|
||||
{
|
||||
@@ -56,6 +60,10 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
/// <typeparam name="TResultType">The type of the result type.</typeparam>
|
||||
/// <typeparam name="TEntity">The type of the entity.</typeparam>
|
||||
/// <remarks>Type <typeparamref name="TResultType"/> must be an enumeration, and its
|
||||
/// underlying type must be byte. Values indicating success should be in the 0-127
|
||||
/// range, while values indicating failure should be in the 128-255 range. See
|
||||
/// <see cref="OperationResultType"/> for a base implementation.</remarks>
|
||||
public class OperationResult<TResultType, TEntity> : OperationResult<TResultType>
|
||||
where TResultType : struct
|
||||
{
|
||||
@@ -111,7 +119,8 @@ namespace Umbraco.Core.Services
|
||||
return new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages);
|
||||
}
|
||||
|
||||
// fixme wtf?
|
||||
// fixme - this exists to support services that still return Attempt<OperationResult>
|
||||
// these services should directly return an OperationResult, and then this static class should be deleted
|
||||
internal static class Attempt
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
@@ -58,21 +56,22 @@
|
||||
<ItemGroup>
|
||||
<!-- note: NuGet deals with transitive references now -->
|
||||
<PackageReference Include="AutoMapper" Version="7.0.1" />
|
||||
<PackageReference Include="ClientDependency" Version="1.9.6" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.7.2" />
|
||||
<PackageReference Include="ImageProcessor" Version="2.6.1.19" />
|
||||
<PackageReference Include="LightInject" Version="5.1.2" />
|
||||
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
|
||||
<PackageReference Include="LightInject.Web" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.6" />
|
||||
<PackageReference Include="Microsoft.Owin.Security.Cookies" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.Owin.Security.OAuth" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.Xdt" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Core">
|
||||
<Version>2.2.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client">
|
||||
<Version>5.2.6</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Owin">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MiniProfiler" Version="3.2.0.157" />
|
||||
<PackageReference Include="MySql.Data" Version="6.10.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NPoco" Version="3.9.3" />
|
||||
<PackageReference Include="NPoco" Version="3.9.4" />
|
||||
<PackageReference Include="Semver" Version="2.0.4" />
|
||||
<PackageReference Include="Serilog">
|
||||
<Version>2.7.1</Version>
|
||||
@@ -110,8 +109,7 @@
|
||||
<Compile Include="Attempt.cs" />
|
||||
<Compile Include="AttemptOfTResult.cs" />
|
||||
<Compile Include="AttemptOfTResultTStatus.cs" />
|
||||
<Compile Include="Auditing\AuditEventsComponent.cs" />
|
||||
<Compile Include="Auditing\IdentityAuditEventArgs.cs" />
|
||||
<Compile Include="Components\AuditEventsComponent.cs" />
|
||||
<Compile Include="BindingRedirects.cs" />
|
||||
<Compile Include="ByteArrayExtensions.cs" />
|
||||
<Compile Include="Cache\CacheHelper.cs" />
|
||||
@@ -200,7 +198,6 @@
|
||||
<Compile Include="Composing\WeightAttribute.cs" />
|
||||
<Compile Include="Composing\WeightedCollectionBuilderBase.cs" />
|
||||
<Compile Include="Configuration\CaseInsensitiveEnumConfigConverter.cs" />
|
||||
<Compile Include="Configuration\ClientDependencyConfiguration.cs" />
|
||||
<Compile Include="Configuration\CommaDelimitedConfigurationElement.cs" />
|
||||
<Compile Include="Configuration\CoreDebug.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
|
||||
@@ -576,7 +573,6 @@
|
||||
<Compile Include="ListExtensions.cs" />
|
||||
<Compile Include="Logging\DebugDiagnosticsLogger.cs" />
|
||||
<Compile Include="Logging\ILogger.cs" />
|
||||
<Compile Include="Logging\ImageProcessorLogger.cs" />
|
||||
<Compile Include="Logging\IProfiler.cs" />
|
||||
<Compile Include="Logging\Serilog\SerilogLogger.cs" />
|
||||
<Compile Include="Logging\LoggerExtensions.cs" />
|
||||
@@ -591,49 +587,17 @@
|
||||
<Compile Include="Logging\WebProfilerComponent.cs" />
|
||||
<Compile Include="Logging\WebProfilerProvider.cs" />
|
||||
<Compile Include="Macros\MacroErrorBehaviour.cs" />
|
||||
<Compile Include="Macros\MacroTagParser.cs" />
|
||||
<Compile Include="MainDom.cs" />
|
||||
<Compile Include="Manifest\ManifestParser.cs" />
|
||||
<Compile Include="Manifest\ValueValidatorConverter.cs" />
|
||||
<Compile Include="Manifest\ManifestWatcher.cs" />
|
||||
<Compile Include="Manifest\PackageManifest.cs" />
|
||||
<Compile Include="Manifest\DataEditorConverter.cs" />
|
||||
<Compile Include="Media\Exif\BitConverterEx.cs" />
|
||||
<Compile Include="Media\Exif\ExifBitConverter.cs" />
|
||||
<Compile Include="Media\Exif\ExifEnums.cs" />
|
||||
<Compile Include="Media\Exif\ExifExceptions.cs" />
|
||||
<Compile Include="Media\Exif\ExifExtendedProperty.cs" />
|
||||
<Compile Include="Media\Exif\ExifFileTypeDescriptor.cs" />
|
||||
<Compile Include="Media\Exif\ExifInterOperability.cs" />
|
||||
<Compile Include="Media\Exif\ExifProperty.cs" />
|
||||
<Compile Include="Media\Exif\ExifPropertyCollection.cs" />
|
||||
<Compile Include="Media\Exif\ExifPropertyFactory.cs" />
|
||||
<Compile Include="Media\Exif\ExifTag.cs" />
|
||||
<Compile Include="Media\Exif\ExifTagFactory.cs" />
|
||||
<Compile Include="Media\Exif\IFD.cs" />
|
||||
<Compile Include="Media\Exif\ImageFile.cs" />
|
||||
<Compile Include="Media\Exif\ImageFileDirectory.cs" />
|
||||
<Compile Include="Media\Exif\ImageFileDirectoryEntry.cs" />
|
||||
<Compile Include="Media\Exif\ImageFileFormat.cs" />
|
||||
<Compile Include="Media\Exif\JFIFEnums.cs" />
|
||||
<Compile Include="Media\Exif\JFIFExtendedProperty.cs" />
|
||||
<Compile Include="Media\Exif\JFIFThumbnail.cs" />
|
||||
<Compile Include="Media\Exif\JPEGExceptions.cs" />
|
||||
<Compile Include="Media\Exif\JPEGFile.cs" />
|
||||
<Compile Include="Media\Exif\JPEGMarker.cs" />
|
||||
<Compile Include="Media\Exif\JPEGSection.cs" />
|
||||
<Compile Include="Media\Exif\MathEx.cs" />
|
||||
<Compile Include="Media\Exif\TIFFFile.cs" />
|
||||
<Compile Include="Media\Exif\TIFFHeader.cs" />
|
||||
<Compile Include="Media\Exif\TIFFStrip.cs" />
|
||||
<Compile Include="Media\Exif\Utility.cs" />
|
||||
<Compile Include="Media\IEmbedProvider.cs" />
|
||||
<Compile Include="Media\IEmbedSettingProvider.cs" />
|
||||
<Compile Include="Media\ImageExtensions.cs" />
|
||||
<Compile Include="Media\ProviderSetting.cs" />
|
||||
<Compile Include="Media\Result.cs" />
|
||||
<Compile Include="Media\Status.cs" />
|
||||
<Compile Include="Media\UploadAutoFillProperties.cs" />
|
||||
<Compile Include="Migrations\IPostMigration.cs" />
|
||||
<Compile Include="Migrations\MigrationBuilder.cs" />
|
||||
<Compile Include="Migrations\MigrationPlan.cs" />
|
||||
@@ -650,7 +614,7 @@
|
||||
<Compile Include="Models\AuditType.cs" />
|
||||
<Compile Include="Models\Content.cs" />
|
||||
<Compile Include="Models\ContentBase.cs" />
|
||||
<Compile Include="Models\ContentExtensions.cs" />
|
||||
<Compile Include="ContentExtensions.cs" />
|
||||
<Compile Include="Models\ContentStatus.cs" />
|
||||
<Compile Include="Models\ContentType.cs" />
|
||||
<Compile Include="Models\ContentTypeAvailableCompositionsResult.cs" />
|
||||
@@ -1315,19 +1279,10 @@
|
||||
<Compile Include="Scoping\ScopeContextualBase.cs" />
|
||||
<Compile Include="Scoping\ScopeProvider.cs" />
|
||||
<Compile Include="Scoping\ScopeReference.cs" />
|
||||
<Compile Include="Security\ActiveDirectoryBackOfficeUserPasswordChecker.cs" />
|
||||
<Compile Include="Security\AuthenticationExtensions.cs" />
|
||||
<Compile Include="Security\BackOfficeClaimsIdentityFactory.cs" />
|
||||
<Compile Include="Security\BackOfficeCookieAuthenticationProvider.cs" />
|
||||
<Compile Include="Security\BackOfficeSignInManager.cs" />
|
||||
<Compile Include="Security\BackOfficeUserManager.cs" />
|
||||
<Compile Include="Security\BackOfficeUserManagerMarker.cs" />
|
||||
<Compile Include="Security\BackOfficeUserPasswordCheckerResult.cs" />
|
||||
<Compile Include="Security\BackOfficeUserStore.cs" />
|
||||
<Compile Include="Security\BackOfficeUserValidator.cs" />
|
||||
<Compile Include="Security\EmailService.cs" />
|
||||
<Compile Include="Security\IBackOfficeUserManagerMarker.cs" />
|
||||
<Compile Include="Security\IBackOfficeUserPasswordChecker.cs" />
|
||||
<Compile Include="Security\IMembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\IUmbracoMemberTypeMembershipProvider.cs" />
|
||||
<Compile Include="Security\IUserAwarePasswordHasher.cs" />
|
||||
@@ -1338,8 +1293,6 @@
|
||||
<Compile Include="Security\MembershipProviderExtensions.cs" />
|
||||
<Compile Include="Security\MembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\MembershipProviderPasswordValidator.cs" />
|
||||
<Compile Include="Security\OwinExtensions.cs" />
|
||||
<Compile Include="Security\SessionIdValidator.cs" />
|
||||
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
|
||||
<Compile Include="Security\UmbracoEmailMessage.cs" />
|
||||
<Compile Include="Security\UmbracoMembershipProviderBase.cs" />
|
||||
@@ -1456,9 +1409,9 @@
|
||||
<Compile Include="Services\UnpublishResultType.cs" />
|
||||
<Compile Include="Services\UserServiceExtensions.cs" />
|
||||
<Compile Include="Settable.cs" />
|
||||
<Compile Include="Strategies\ManifestWatcherComponent.cs" />
|
||||
<Compile Include="Strategies\RelateOnCopyComponent.cs" />
|
||||
<Compile Include="Strategies\RelateOnTrashComponent.cs" />
|
||||
<Compile Include="Components\ManifestWatcherComponent.cs" />
|
||||
<Compile Include="Components\RelateOnCopyComponent.cs" />
|
||||
<Compile Include="Components\RelateOnTrashComponent.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
<Compile Include="Strings\CleanStringType.cs" />
|
||||
<Compile Include="Strings\ContentBaseExtensions.cs" />
|
||||
@@ -1540,6 +1493,8 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="FileResources\Files.resx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Folder Include="Auditing\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -50,7 +50,7 @@
|
||||
<!-- note: NuGet deals with transitive references now -->
|
||||
<PackageReference Include="Examine" Version="1.0.0-beta025" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NPoco" Version="3.9.3" />
|
||||
<PackageReference Include="NPoco" Version="3.9.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config\ConfigIndexCriteria.cs" />
|
||||
|
||||
@@ -62,18 +62,16 @@
|
||||
<PackageReference Include="BenchmarkDotNet.Toolchains.Roslyn" Version="0.10.13" />
|
||||
<PackageReference Include="Castle.Core" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.9.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="2.8.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.11" />
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="2.0.4" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||
<PackageReference Include="Moq" Version="4.8.2" />
|
||||
<PackageReference Include="NPoco" Version="3.9.3" />
|
||||
<PackageReference Include="NPoco" Version="3.9.4" />
|
||||
<PackageReference Include="Umbraco.SqlServerCE" Version="4.0.0.1" />
|
||||
<PackageReference Include="System.AppContext" Version="4.3.0" />
|
||||
<PackageReference Include="System.Collections" Version="4.3.0" />
|
||||
<PackageReference Include="System.Collections.Concurrent" Version="4.3.0" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
|
||||
<PackageReference Include="System.Console" Version="4.3.0" />
|
||||
<PackageReference Include="System.Diagnostics.Debug" Version="4.3.0" />
|
||||
<PackageReference Include="System.Diagnostics.FileVersionInfo" Version="4.3.0" />
|
||||
@@ -87,7 +85,6 @@
|
||||
<PackageReference Include="System.Linq" Version="4.3.0" />
|
||||
<PackageReference Include="System.Linq.Expressions" Version="4.3.0" />
|
||||
<PackageReference Include="System.Reflection" Version="4.3.0" />
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="1.5.0" />
|
||||
<PackageReference Include="System.Reflection.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="System.Resources.ResourceManager" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime" Version="4.3.0" />
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.TraceEvent" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
@@ -55,7 +55,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ComponentModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
@@ -167,7 +167,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.3.0" newVersion="1.4.3.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
@@ -267,7 +267,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
|
||||
|
||||
@@ -23,6 +23,12 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
|
||||
Assert.IsTrue(SettingsSection.WebRouting.DisableAlternativeTemplates == false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ValidateAlternativeTemplates()
|
||||
{
|
||||
Assert.IsTrue(SettingsSection.WebRouting.ValidateAlternativeTemplates == false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisableFindContentByIdPath()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Macros;
|
||||
using Umbraco.Web.Macros;
|
||||
|
||||
namespace Umbraco.Tests.Macros
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
using Umbraco.Tests.Testing;
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Web;
|
||||
using Moq;
|
||||
using Umbraco.Core;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web;
|
||||
@@ -74,7 +75,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
var mediaFileSystem = new MediaFileSystem(Mock.Of<IFileSystem>(), Mock.Of<IContentSection>(), Mock.Of<IMediaPathScheme>(), Mock.Of<ILogger>());
|
||||
|
||||
var dataTypeService = new TestObjects.TestDataTypeService(
|
||||
new DataType(new ImageCropperPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, Mock.Of<IContentSection>())) { Id = 1 });
|
||||
new DataType(new ImageCropperPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, Mock.Of<IContentSection>(), Mock.Of<IDataTypeService>())) { Id = 1 });
|
||||
|
||||
var factory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty<IPropertyValueConverter>()), dataTypeService);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Security.Identity;
|
||||
|
||||
|
||||
namespace Umbraco.Tests.Security
|
||||
{
|
||||
|
||||
@@ -89,7 +89,11 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
var httpContext = Mock.Of<HttpContextBase>(
|
||||
http => http.User == owinContext.Authentication.User
|
||||
//ensure the request exists with a cookies collection
|
||||
&& http.Request == Mock.Of<HttpRequestBase>(r => r.Cookies == new HttpCookieCollection())
|
||||
&& http.Request == Mock.Of<HttpRequestBase>(r => r.Cookies == new HttpCookieCollection()
|
||||
&& r.RequestContext == new System.Web.Routing.RequestContext
|
||||
{
|
||||
RouteData = new System.Web.Routing.RouteData()
|
||||
})
|
||||
//ensure the request exists with an items collection
|
||||
&& http.Items == httpContextItems);
|
||||
//chuck it into the props since this is what MS does when hosted and it's needed there
|
||||
|
||||
@@ -58,14 +58,14 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
|
||||
var response = await server.HttpClient.SendAsync(request);
|
||||
Console.WriteLine(response);
|
||||
|
||||
var json = "";
|
||||
if (response.IsSuccessStatusCode == false)
|
||||
{
|
||||
WriteResponseError(response);
|
||||
}
|
||||
else
|
||||
|
||||
var json = (await ((StreamContent)response.Content).ReadAsStringAsync()).TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
|
||||
if (!json.IsNullOrWhiteSpace())
|
||||
{
|
||||
json = (await ((StreamContent) response.Content).ReadAsStringAsync()).TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
|
||||
var deserialized = JsonConvert.DeserializeObject(json);
|
||||
Console.Write(JsonConvert.SerializeObject(deserialized, Formatting.Indented));
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
|
||||
<PackageReference Include="Lucene.Net" Version="3.0.3" />
|
||||
<PackageReference Include="Lucene.Net.Contrib" Version="3.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.6" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi" Version="5.2.6" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.6" />
|
||||
@@ -96,7 +96,7 @@
|
||||
<PackageReference Include="Microsoft.Web.Infrastructure" Version="1.0.0.0" />
|
||||
<PackageReference Include="MiniProfiler" Version="3.2.0.157" />
|
||||
<PackageReference Include="Moq" Version="4.8.2" />
|
||||
<PackageReference Include="NPoco" Version="3.9.3" />
|
||||
<PackageReference Include="NPoco" Version="3.9.4" />
|
||||
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
|
||||
@@ -24,6 +24,12 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web._Legacy.Actions;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
using System;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.Trees;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
@@ -40,6 +46,8 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
userServiceMock.Setup(service => service.GetUserById(It.IsAny<int>()))
|
||||
.Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List<IReadOnlyUserGroup>(), new int[0], new int[0]) : null);
|
||||
userServiceMock.Setup(x => x.GetProfileById(It.IsAny<int>()))
|
||||
.Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List<IReadOnlyUserGroup>(), new int[0], new int[0]) : null);
|
||||
userServiceMock.Setup(service => service.GetPermissionsForPath(It.IsAny<IUser>(), It.IsAny<string>()))
|
||||
.Returns(new EntityPermissionSet(123, new EntityPermissionCollection(new[]
|
||||
{
|
||||
@@ -54,23 +62,34 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
|
||||
var entityService = new Mock<IEntityService>();
|
||||
entityService.Setup(x => x.GetAllPaths(UmbracoObjectTypes.Document, It.IsAny<int[]>()))
|
||||
.Returns((UmbracoObjectTypes objType, int[] ids) => ids.Select(x => new TreeEntityPath {Path = $"-1,{x}", Id = x}).ToList());
|
||||
.Returns((UmbracoObjectTypes objType, int[] ids) => ids.Select(x => new TreeEntityPath { Path = $"-1,{x}", Id = x }).ToList());
|
||||
|
||||
var dataTypeService = new Mock<IDataTypeService>();
|
||||
dataTypeService.Setup(service => service.GetDataType(It.IsAny<int>()))
|
||||
.Returns(MockedDataType());
|
||||
.Returns(Mock.Of<IDataType>(type => type.Id == 9876 && type.Name == "text"));
|
||||
dataTypeService.Setup(service => service.GetDataType(-87)) //the RTE
|
||||
.Returns(Mock.Of<IDataType>(type => type.Id == -87 && type.Name == "Rich text" && type.Configuration == new RichTextConfiguration()));
|
||||
|
||||
var langService = new Mock<ILocalizationService>();
|
||||
langService.Setup(x => x.GetAllLanguages()).Returns(new[] {
|
||||
Mock.Of<ILanguage>(x => x.IsoCode == "en-US"),
|
||||
Mock.Of<ILanguage>(x => x.IsoCode == "es-ES"),
|
||||
Mock.Of<ILanguage>(x => x.IsoCode == "fr-FR")
|
||||
});
|
||||
|
||||
var textService = new Mock<ILocalizedTextService>();
|
||||
textService.Setup(x => x.Localize(It.IsAny<string>(), It.IsAny<CultureInfo>(), It.IsAny<IDictionary<string, string>>())).Returns("");
|
||||
|
||||
Container.RegisterSingleton(f => Mock.Of<IContentService>());
|
||||
Container.RegisterSingleton(f => userServiceMock.Object);
|
||||
Container.RegisterSingleton(f => entityService.Object);
|
||||
Container.RegisterSingleton(f => dataTypeService.Object);
|
||||
Container.RegisterSingleton(f => langService.Object);
|
||||
Container.RegisterSingleton(f => textService.Object);
|
||||
Container.RegisterSingleton(f => Mock.Of<ICultureDictionaryFactory>());
|
||||
Container.RegisterSingleton(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) }));
|
||||
}
|
||||
|
||||
private IDataType MockedDataType()
|
||||
{
|
||||
return Mock.Of<IDataType>(type => type.Id == 9876 && type.Name == "text");
|
||||
}
|
||||
|
||||
private MultipartFormDataContent GetMultiPartRequestContent(string json)
|
||||
{
|
||||
var multiPartBoundary = "----WebKitFormBoundary123456789";
|
||||
@@ -89,14 +108,34 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
};
|
||||
}
|
||||
|
||||
private const string PublishJson1 = @"{
|
||||
private IContent GetMockedContent()
|
||||
{
|
||||
var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
|
||||
content.Id = 123;
|
||||
content.Path = "-1,123";
|
||||
//ensure things have ids
|
||||
var ids = 888;
|
||||
foreach (var g in content.PropertyGroups)
|
||||
{
|
||||
g.Id = ids;
|
||||
ids++;
|
||||
}
|
||||
foreach (var p in content.PropertyTypes)
|
||||
{
|
||||
p.Id = ids;
|
||||
ids++;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private const string PublishJsonInvariant = @"{
|
||||
""id"": 123,
|
||||
""contentTypeAlias"": ""page"",
|
||||
""parentId"": -1,
|
||||
""action"": ""save"",
|
||||
""variants"": [
|
||||
{
|
||||
""name"": null,
|
||||
""name"": ""asdf"",
|
||||
""properties"": [
|
||||
{
|
||||
""id"": 1,
|
||||
@@ -104,10 +143,34 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
""value"": ""asdf""
|
||||
}
|
||||
],
|
||||
""culture"": ""en-US""
|
||||
""culture"": null,
|
||||
""save"": true,
|
||||
""publish"": true
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
private const string PublishJsonVariant = @"{
|
||||
""id"": 123,
|
||||
""contentTypeAlias"": ""page"",
|
||||
""parentId"": -1,
|
||||
""action"": ""save"",
|
||||
""variants"": [
|
||||
{
|
||||
""name"": ""asdf"",
|
||||
""properties"": [
|
||||
{
|
||||
""id"": 1,
|
||||
""alias"": ""title"",
|
||||
""value"": ""asdf""
|
||||
}
|
||||
],
|
||||
""culture"": ""en-US"",
|
||||
""save"": true,
|
||||
""publish"": true
|
||||
},
|
||||
{
|
||||
""name"": null,
|
||||
""name"": ""asdf"",
|
||||
""properties"": [
|
||||
{
|
||||
""id"": 1,
|
||||
@@ -115,7 +178,9 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
""value"": ""asdf""
|
||||
}
|
||||
],
|
||||
""culture"": ""fr-FR""
|
||||
""culture"": ""fr-FR"",
|
||||
""save"": true,
|
||||
""publish"": true
|
||||
},
|
||||
{
|
||||
""name"": ""asdf"",
|
||||
@@ -142,12 +207,8 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
{
|
||||
//var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
|
||||
//content.Id = 999999999; //this will not be found
|
||||
//content.Path = "-1,999999999";
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null); //do not find it
|
||||
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
@@ -157,7 +218,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(PublishJson1),
|
||||
content: GetMultiPartRequestContent(PublishJsonInvariant),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
assertOkResponse: false);
|
||||
|
||||
@@ -174,7 +235,7 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
{
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => GetMockedContent());
|
||||
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
@@ -182,9 +243,9 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
return usersController;
|
||||
}
|
||||
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJson1);
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
|
||||
//remove all save flaggs
|
||||
((JArray)json["variants"])[2]["save"] = false;
|
||||
((JArray)json["variants"])[0]["save"] = false;
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
@@ -200,20 +261,52 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
/// Returns 404 if any of the posted properties dont actually exist
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Test, Ignore("Not implemented yet")]
|
||||
[Test]
|
||||
public async Task PostSave_Validate_Properties_Exist()
|
||||
{
|
||||
//TODO: Make this work! to finish it, we need to include a property in the POST data that doesn't exist on the content type
|
||||
// or change the content type below to not include one of the posted ones
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
{
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => GetMockedContent());
|
||||
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
|
||||
Container.InjectProperties(usersController);
|
||||
return usersController;
|
||||
}
|
||||
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
|
||||
//add a non-existent property to a variant being saved
|
||||
var variantProps = (JArray)json["variants"].ElementAt(0)["properties"];
|
||||
variantProps.Add(JObject.FromObject(new
|
||||
{
|
||||
id = 2,
|
||||
alias = "doesntExist",
|
||||
value = "hello"
|
||||
}));
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
assertOkResponse: false);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.NotFound, response.Item1.StatusCode);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PostSave_Simple_Invariant()
|
||||
{
|
||||
var content = GetMockedContent();
|
||||
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
{
|
||||
var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
|
||||
content.Id = 123;
|
||||
content.Path = "-1,123";
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => content);
|
||||
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
|
||||
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
|
||||
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
@@ -223,14 +316,92 @@ namespace Umbraco.Tests.Web.Controllers
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(PublishJson1),
|
||||
content: GetMultiPartRequestContent(PublishJsonInvariant),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
assertOkResponse: false);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.NotFound, response.Item1.StatusCode);
|
||||
|
||||
//var obj = JsonConvert.DeserializeObject<PagedResult<UserDisplay>>(response.Item2);
|
||||
//Assert.AreEqual(0, obj.TotalItems);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.Item1.StatusCode);
|
||||
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(response.Item2);
|
||||
Assert.AreEqual(1, display.Variants.Count());
|
||||
Assert.AreEqual(content.PropertyGroups.Count(), display.Variants.ElementAt(0).Tabs.Count());
|
||||
Assert.AreEqual(content.PropertyTypes.Count(), display.Variants.ElementAt(0).Tabs.ElementAt(0).Properties.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PostSave_Validate_Empty_Name()
|
||||
{
|
||||
var content = GetMockedContent();
|
||||
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
{
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => content);
|
||||
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
|
||||
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
|
||||
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
|
||||
Container.InjectProperties(usersController);
|
||||
return usersController;
|
||||
}
|
||||
|
||||
//clear out the name
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
|
||||
json["variants"].ElementAt(0)["name"] = null;
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
assertOkResponse: false);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.BadRequest, response.Item1.StatusCode);
|
||||
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(response.Item2);
|
||||
Assert.AreEqual(1, display.Errors.Count());
|
||||
Assert.IsTrue(display.Errors.ContainsKey("Variants[0].Name"));
|
||||
//ModelState":{"Variants[0].Name":["Required"]}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PostSave_Validate_Variants_Empty_Name()
|
||||
{
|
||||
var content = GetMockedContent();
|
||||
|
||||
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
|
||||
{
|
||||
|
||||
var contentServiceMock = Mock.Get(Current.Services.ContentService);
|
||||
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => content);
|
||||
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
|
||||
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
|
||||
|
||||
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
|
||||
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
|
||||
var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
|
||||
Container.InjectProperties(usersController);
|
||||
return usersController;
|
||||
}
|
||||
|
||||
//clear out one of the names
|
||||
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonVariant);
|
||||
json["variants"].ElementAt(0)["name"] = null;
|
||||
|
||||
var runner = new TestRunner(Factory);
|
||||
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
|
||||
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
|
||||
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
|
||||
assertOkResponse: false);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.BadRequest, response.Item1.StatusCode);
|
||||
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(response.Item2);
|
||||
Assert.AreEqual(2, display.Errors.Count());
|
||||
Assert.IsTrue(display.Errors.ContainsKey("Variants[0].Name"));
|
||||
Assert.IsTrue(display.Errors.ContainsKey("_content_variant_en-US_"));
|
||||
}
|
||||
|
||||
//TODO: There are SOOOOO many more tests we should write - a lot of them to do with validation
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
[Test]
|
||||
public void ReplaceLineBreaksWithHtmlBreak()
|
||||
{
|
||||
var output = _htmlStringUtilities.ReplaceLineBreaksForHtml("<div><h1>hello world</h1><p>hello world\r\nhello world\rhello world\nhello world</p></div>");
|
||||
var output = _htmlStringUtilities.ReplaceLineBreaksForHtml("<div><h1>hello world</h1><p>hello world\r\nhello world\rhello world\nhello world</p></div>").ToString();
|
||||
var expected = "<div><h1>hello world</h1><p>hello world<br />hello world<br />hello world<br />hello world</p></div>";
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
@@ -58,4 +58,4 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
src/common/services/util.service.js
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<staticContent>
|
||||
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
|
||||
</staticContent>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@@ -455,13 +455,28 @@ In the following example you see how to run some custom logic before a step goes
|
||||
function waitForPendingRerequests() {
|
||||
var deferred = $q.defer();
|
||||
var timer = window.setInterval(function(){
|
||||
|
||||
var requestsReady = false;
|
||||
var animationsDone = false;
|
||||
|
||||
// check for pending requests both in angular and on the document
|
||||
if($http.pendingRequests.length === 0 && document.readyState === "complete") {
|
||||
requestsReady = true;
|
||||
}
|
||||
|
||||
// check for animations. ng-enter and ng-leave are default angular animations.
|
||||
// Also check for infinite editors animating
|
||||
if(document.querySelectorAll(".ng-enter, .ng-leave, .umb-editor--animating").length === 0) {
|
||||
animationsDone = true;
|
||||
}
|
||||
|
||||
if(requestsReady && animationsDone) {
|
||||
$timeout(function(){
|
||||
deferred.resolve();
|
||||
clearInterval(timer);
|
||||
});
|
||||
}
|
||||
|
||||
}, 50);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,6 @@
|
||||
$scope.page.hideChangeVariant = infiniteMode ? true : false;
|
||||
$scope.allowOpen = true;
|
||||
|
||||
// add all editors to an editors array to support split view
|
||||
$scope.editors = [];
|
||||
$scope.initVariant = initVariant;
|
||||
$scope.splitViewChanged = splitViewChanged;
|
||||
|
||||
function init(content) {
|
||||
|
||||
if (infiniteMode) {
|
||||
@@ -55,17 +50,10 @@
|
||||
// set first app to active
|
||||
// We need to track active
|
||||
$scope.content.apps[0].active = true;
|
||||
|
||||
setActiveCulture();
|
||||
|
||||
|
||||
resetVariantFlags();
|
||||
}
|
||||
|
||||
/** This is called when the split view changes based on the umb-variant-content */
|
||||
function splitViewChanged() {
|
||||
//send an event downwards
|
||||
$scope.$broadcast("editors.content.splitViewChanged", { editors: $scope.editors });
|
||||
}
|
||||
|
||||
/**
|
||||
* This will reset isDirty flags if save is true.
|
||||
@@ -91,123 +79,12 @@
|
||||
$scope.content.variants[0].publish = false;
|
||||
}
|
||||
}
|
||||
|
||||
function countDirtyVariants() {
|
||||
var count = 0;
|
||||
for (var i = 0; i < $scope.content.variants.length; i++) {
|
||||
var v = $scope.content.variants[i];
|
||||
if (v.isDirty) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if the save/publish dialog should be shown when pressing the button */
|
||||
function showSaveOrPublishDialog() {
|
||||
return $scope.content.variants.length > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The content item(s) are loaded into an array and this will set the active content item based on the current culture (query string).
|
||||
* If the content item is invariant, then only one item exists in the array.
|
||||
*/
|
||||
function setActiveCulture() {
|
||||
// set the active variant
|
||||
var activeVariant = null;
|
||||
_.each($scope.content.variants, function (v) {
|
||||
if (v.language && v.language.culture === $scope.culture) {
|
||||
v.active = true;
|
||||
activeVariant = v;
|
||||
}
|
||||
else {
|
||||
v.active = false;
|
||||
}
|
||||
});
|
||||
if (!activeVariant) {
|
||||
// set the first variant to active
|
||||
$scope.content.variants[0].active = true;
|
||||
activeVariant = $scope.content.variants[0];
|
||||
}
|
||||
|
||||
initVariant(activeVariant);
|
||||
|
||||
//If there are no editors yet then create one with the current content.
|
||||
//if there's already a main editor then update it with the current content.
|
||||
if ($scope.editors.length === 0) {
|
||||
var editor = {
|
||||
content: activeVariant
|
||||
};
|
||||
$scope.editors.push(editor);
|
||||
}
|
||||
else {
|
||||
//this will mean there is only one
|
||||
$scope.editors[0].content = activeVariant;
|
||||
|
||||
if ($scope.editors.length > 1) {
|
||||
//now re-sync any other editor content (i.e. if split view is open)
|
||||
for (var s = 1; s < $scope.editors.length; s++) {
|
||||
//get the variant from the scope model
|
||||
var variant = _.find($scope.content.variants, function (v) {
|
||||
return v.language.culture === $scope.editors[s].content.language.culture;
|
||||
});
|
||||
$scope.editors[s].content = initVariant(variant);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function initVariant(variant) {
|
||||
//The model that is assigned to the editor contains the current content variant along
|
||||
//with a copy of the contentApps. This is required because each editor renders it's own
|
||||
//header and content apps section and the content apps contains the view for editing content itself
|
||||
//and we need to assign a view model to the subView so that it is scoped to the current
|
||||
//editor so that split views work.
|
||||
|
||||
//copy the apps from the main model if not assigned yet to the variant
|
||||
if (!variant.apps) {
|
||||
variant.apps = angular.copy($scope.content.apps);
|
||||
}
|
||||
|
||||
//if this is a variant has a culture/language than we need to assign the language drop down info
|
||||
if (variant.language) {
|
||||
//if the variant list that defines the header drop down isn't assigned to the variant then assign it now
|
||||
if (!variant.variants) {
|
||||
variant.variants = _.map($scope.content.variants,
|
||||
function (v) {
|
||||
return _.pick(v, "active", "language", "state");
|
||||
});
|
||||
}
|
||||
else {
|
||||
//merge the scope variants on top of the header variants collection (handy when needing to refresh)
|
||||
angular.extend(variant.variants,
|
||||
_.map($scope.content.variants,
|
||||
function (v) {
|
||||
return _.pick(v, "active", "language", "state");
|
||||
}));
|
||||
}
|
||||
|
||||
//ensure the current culture is set as the active one
|
||||
for (var i = 0; i < variant.variants.length; i++) {
|
||||
if (variant.variants[i].language.culture === variant.language.culture) {
|
||||
variant.variants[i].active = true;
|
||||
}
|
||||
else {
|
||||
variant.variants[i].active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//then assign the variant to a view model to the content app
|
||||
var contentApp = _.find(variant.apps, function (a) {
|
||||
return a.alias === "content";
|
||||
});
|
||||
contentApp.viewModel = variant;
|
||||
|
||||
return variant;
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
//bindEvents can be called more than once and we don't want to have multiple bound events
|
||||
for (var e in evts) {
|
||||
@@ -249,9 +126,7 @@
|
||||
|
||||
init($scope.content);
|
||||
|
||||
if (!infiniteMode) {
|
||||
syncTreeNode($scope.content, true);
|
||||
}
|
||||
syncTreeNode($scope.content, $scope.content.path, true);
|
||||
|
||||
resetLastListPageNumber($scope.content);
|
||||
|
||||
@@ -300,10 +175,12 @@
|
||||
}
|
||||
|
||||
/** Syncs the content item to it's tree node - this occurs on first load and after saving */
|
||||
function syncTreeNode(content, initialLoad) {
|
||||
|
||||
var path = content.path;
|
||||
function syncTreeNode(content, path, initialLoad) {
|
||||
|
||||
if (infiniteMode || !path) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$scope.content.isChildOfListView) {
|
||||
navigationService.syncTree({ tree: $scope.treeAlias, path: path.split(","), forceReload: initialLoad !== true }).then(function (syncArgs) {
|
||||
$scope.page.menu.currentNode = syncArgs.node;
|
||||
@@ -341,9 +218,7 @@
|
||||
//success
|
||||
init($scope.content);
|
||||
|
||||
if (!infiniteMode) {
|
||||
syncTreeNode($scope.content);
|
||||
}
|
||||
syncTreeNode($scope.content, data.path);
|
||||
|
||||
$scope.page.buttonGroupState = "success";
|
||||
|
||||
@@ -353,8 +228,7 @@
|
||||
},
|
||||
function (err) {
|
||||
|
||||
setActiveCulture();
|
||||
syncTreeNode($scope.content);
|
||||
syncTreeNode($scope.content, $scope.content.path);
|
||||
|
||||
//error
|
||||
if (err) {
|
||||
@@ -367,6 +241,19 @@
|
||||
});
|
||||
}
|
||||
|
||||
function clearNotifications(content) {
|
||||
if (content.notifications) {
|
||||
content.notifications = [];
|
||||
}
|
||||
if (content.variants) {
|
||||
for (var i = 0; i < content.variants.length; i++) {
|
||||
if (content.variants[i].notifications) {
|
||||
content.variants[i].notifications = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetLastListPageNumber(content) {
|
||||
// We're using rootScope to store the page number for list views, so if returning to the list
|
||||
// we can restore the page. If we've moved on to edit a piece of content that's not the list or it's children
|
||||
@@ -376,6 +263,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to clear the dirty state for successfully saved variants when not all variant saving was successful
|
||||
* @param {any} variants
|
||||
*/
|
||||
function clearDirtyState(variants) {
|
||||
for (var i = 0; i < variants.length; i++) {
|
||||
var v = variants[i];
|
||||
if (v.notifications) {
|
||||
var isSuccess = _.find(v.notifications, function (n) {
|
||||
return n.type === 3; //this is a success notification
|
||||
});
|
||||
if (isSuccess) {
|
||||
v.isDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope.page.isNew) {
|
||||
|
||||
$scope.page.loading = true;
|
||||
@@ -438,9 +343,7 @@
|
||||
|
||||
init($scope.content);
|
||||
|
||||
if (!infiniteMode) {
|
||||
syncTreeNode($scope.content);
|
||||
}
|
||||
syncTreeNode($scope.content, data.path);
|
||||
|
||||
$scope.page.buttonGroupState = "success";
|
||||
|
||||
@@ -458,35 +361,40 @@
|
||||
};
|
||||
|
||||
$scope.saveAndPublish = function () {
|
||||
|
||||
clearNotifications($scope.content);
|
||||
// TODO: Add "..." to publish button label if there are more than one variant to publish - currently it just adds the elipses if there's more than 1 variant
|
||||
if (showSaveOrPublishDialog()) {
|
||||
//before we launch the dialog we want to execute all client side validations first
|
||||
if (formHelper.submitForm({ scope: $scope, action: "publish" })) {
|
||||
|
||||
var dialog = {
|
||||
parentScope: $scope,
|
||||
view: "views/content/overlays/publish.html",
|
||||
variants: $scope.content.variants, //set a model property for the dialog
|
||||
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
|
||||
submitButtonLabel: "Publish",
|
||||
submit: function (model) {
|
||||
model.submitButtonState = "busy";
|
||||
|
||||
clearNotifications($scope.content);
|
||||
//we need to return this promise so that the dialog can handle the result and wire up the validation response
|
||||
return performSave({
|
||||
saveMethod: contentResource.publish,
|
||||
action: "publish",
|
||||
showNotifications: false
|
||||
}).then(function (data) {
|
||||
//show all notifications manually here since we disabled showing them automatically in the save method
|
||||
formHelper.showNotifications(data);
|
||||
clearNotifications($scope.content);
|
||||
overlayService.close();
|
||||
return $q.when(data);
|
||||
},
|
||||
function (err) {
|
||||
clearDirtyState($scope.content.variants);
|
||||
model.submitButtonState = "error";
|
||||
//re-map the dialog model since we've re-bound the properties
|
||||
dialog.variants = $scope.content.variants;
|
||||
|
||||
return $q.reject(err);
|
||||
//don't reject, we've handled the error
|
||||
return $q.when(err);
|
||||
});
|
||||
},
|
||||
close: function (oldModel) {
|
||||
@@ -505,35 +413,40 @@
|
||||
};
|
||||
|
||||
$scope.save = function () {
|
||||
|
||||
clearNotifications($scope.content);
|
||||
// TODO: Add "..." to save button label if there are more than one variant to publish - currently it just adds the elipses if there's more than 1 variant
|
||||
if (showSaveOrPublishDialog()) {
|
||||
//before we launch the dialog we want to execute all client side validations first
|
||||
if (formHelper.submitForm({ scope: $scope, action: "save" })) {
|
||||
|
||||
var dialog = {
|
||||
parentScope: $scope,
|
||||
view: "views/content/overlays/save.html",
|
||||
variants: $scope.content.variants, //set a model property for the dialog
|
||||
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
|
||||
submitButtonLabel: "Save",
|
||||
submit: function (model) {
|
||||
model.submitButtonState = "busy";
|
||||
|
||||
clearNotifications($scope.content);
|
||||
//we need to return this promise so that the dialog can handle the result and wire up the validation response
|
||||
return performSave({
|
||||
saveMethod: $scope.saveMethod(),
|
||||
action: "save",
|
||||
showNotifications: false
|
||||
}).then(function (data) {
|
||||
//show all notifications manually here since we disabled showing them automatically in the save method
|
||||
formHelper.showNotifications(data);
|
||||
clearNotifications($scope.content);
|
||||
overlayService.close();
|
||||
return $q.when(data);
|
||||
},
|
||||
function (err) {
|
||||
clearDirtyState($scope.content.variants);
|
||||
model.submitButtonState = "error";
|
||||
//re-map the dialog model since we've re-bound the properties
|
||||
dialog.variants = $scope.content.variants;
|
||||
|
||||
return $q.reject(err);
|
||||
//don't reject, we've handled the error
|
||||
return $q.when(err);
|
||||
});
|
||||
},
|
||||
close: function (oldModel) {
|
||||
@@ -576,10 +489,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
$scope.backToListView = function () {
|
||||
$location.path($scope.page.listViewPath);
|
||||
};
|
||||
|
||||
$scope.restore = function (content) {
|
||||
|
||||
$scope.page.buttonRestore = "busy";
|
||||
@@ -685,12 +594,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('culture', function (newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
setActiveCulture();
|
||||
}
|
||||
});
|
||||
|
||||
//ensure to unregister from all events!
|
||||
$scope.$on('$destroy', function () {
|
||||
for (var e in evts) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
scope.disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates;
|
||||
scope.allowChangeDocumentType = false;
|
||||
scope.allowChangeTemplate = false;
|
||||
|
||||
|
||||
function onInit() {
|
||||
|
||||
userService.getCurrentUser().then(function(user){
|
||||
@@ -71,10 +71,11 @@
|
||||
|
||||
// make sure dates are formatted to the user's locale
|
||||
formatDatesToLocal();
|
||||
|
||||
// Declare a fallback URL for the <umb-node-preview/> directive
|
||||
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
|
||||
|
||||
// Declare a fallback URL for the <umb-node-preview/> directive
|
||||
if (scope.documentType !== null) {
|
||||
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
|
||||
}
|
||||
}
|
||||
|
||||
scope.auditTrailPageChange = function (pageNumber) {
|
||||
@@ -142,7 +143,7 @@
|
||||
item.timestampFormatted = dateHelper.getLocalDate(item.timestamp, currentUser.locale, 'LLL');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
scope.auditTrail = data.items;
|
||||
scope.auditTrailOptions.pageNumber = data.pageNumber;
|
||||
scope.auditTrailOptions.pageSize = data.pageSize;
|
||||
@@ -150,7 +151,7 @@
|
||||
scope.auditTrailOptions.totalPages = data.totalPages;
|
||||
|
||||
setAuditTrailLogTypeColor(scope.auditTrail);
|
||||
|
||||
|
||||
scope.loadingAuditTrail = false;
|
||||
});
|
||||
|
||||
@@ -158,6 +159,7 @@
|
||||
|
||||
function setAuditTrailLogTypeColor(auditTrail) {
|
||||
angular.forEach(auditTrail, function (item) {
|
||||
|
||||
switch (item.logType) {
|
||||
case "Publish":
|
||||
item.logTypeColor = "success";
|
||||
@@ -286,7 +288,7 @@
|
||||
eventsService.emit("editors.content.changeUnpublishDate", args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function ucfirst(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
@@ -295,13 +297,13 @@
|
||||
// get current backoffice user and format dates
|
||||
userService.getCurrentUser().then(function (currentUser) {
|
||||
scope.node.createDateFormatted = dateHelper.getLocalDate(scope.node.createDate, currentUser.locale, 'LLL');
|
||||
|
||||
|
||||
scope.node.releaseDateYear = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'YYYY')) : null;
|
||||
scope.node.releaseDateMonth = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'MMMM')) : null;
|
||||
scope.node.releaseDateDayNumber = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'DD')) : null;
|
||||
scope.node.releaseDateDay = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'dddd')) : null;
|
||||
scope.node.releaseDateTime = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'HH:mm')) : null;
|
||||
|
||||
|
||||
scope.node.removeDateYear = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'YYYY')) : null;
|
||||
scope.node.removeDateMonth = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'MMMM')) : null;
|
||||
scope.node.removeDateDayNumber = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'DD')) : null;
|
||||
@@ -326,8 +328,8 @@
|
||||
scope.$watch('node.updateDate', function(newValue, oldValue){
|
||||
|
||||
if(!newValue) { return; }
|
||||
if(newValue === oldValue) { return; }
|
||||
|
||||
if(newValue === oldValue) { return; }
|
||||
|
||||
if(isInfoTab) {
|
||||
loadAuditTrail();
|
||||
formatDatesToLocal();
|
||||
|
||||
@@ -2,133 +2,79 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* A directive to encapsulate each variant editor which includes the name header and all content apps for a given variant
|
||||
* @param {any} $timeout
|
||||
* @param {any} $location
|
||||
* A component to encapsulate each variant editor which includes the name header and all content apps for a given variant
|
||||
*/
|
||||
function variantContentDirective($timeout, $location) {
|
||||
var umbVariantContent = {
|
||||
templateUrl: 'views/components/content/umb-variant-content.html',
|
||||
bindings: {
|
||||
content: "<",
|
||||
page: "<",
|
||||
editor: "<",
|
||||
editorIndex: "<",
|
||||
editorCount: "<",
|
||||
onCloseSplitView: "&",
|
||||
onSelectVariant: "&",
|
||||
onOpenSplitView: "&"
|
||||
},
|
||||
controllerAs: 'vm',
|
||||
controller: umbVariantContentController
|
||||
};
|
||||
|
||||
function umbVariantContentController($scope, $element, $location) {
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/content/umb-variant-content.html',
|
||||
link: function (scope) {
|
||||
var unsubscribe = [];
|
||||
|
||||
/**
|
||||
* Adds a new editor to the editors array to show content in a split view
|
||||
* @param {any} selectedVariant
|
||||
*/
|
||||
scope.openInSplitView = function (selectedVariant) {
|
||||
var vm = this;
|
||||
|
||||
var selectedCulture = selectedVariant.language.culture;
|
||||
vm.$postLink = postLink;
|
||||
vm.$onDestroy = onDestroy;
|
||||
|
||||
//only the content app can be selected since no other apps are shown, and because we copy all of these apps
|
||||
//to the "editors" we need to update this across all editors
|
||||
for (var e = 0; e < scope.editors.length; e++) {
|
||||
var editor = scope.editors[e];
|
||||
for (var i = 0; i < editor.content.apps.length; i++) {
|
||||
var app = editor.content.apps[i];
|
||||
if (app.alias === "content") {
|
||||
app.active = true;
|
||||
}
|
||||
else {
|
||||
app.active = false;
|
||||
}
|
||||
}
|
||||
vm.selectVariant = selectVariant;
|
||||
vm.openSplitView = openSplitView;
|
||||
vm.backToListView = backToListView;
|
||||
|
||||
/** Called when the component has linked all elements, this is when the form controller is available */
|
||||
function postLink() {
|
||||
//set the content to dirty if the header changes
|
||||
unsubscribe.push($scope.$watch("contentHeaderForm.$dirty",
|
||||
function(newValue, oldValue) {
|
||||
if (newValue === true) {
|
||||
vm.editor.content.isDirty = true;
|
||||
}
|
||||
|
||||
//Find the whole variant model based on the culture that was chosen
|
||||
var variant = _.find(scope.content.variants, function (v) {
|
||||
return v.language.culture === selectedCulture;
|
||||
});
|
||||
|
||||
var editor = {
|
||||
content: scope.initVariant({ variant: variant})
|
||||
};
|
||||
scope.editors.push(editor);
|
||||
|
||||
//TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular
|
||||
editor.collapsed = true;
|
||||
editor.loading = true;
|
||||
$timeout(function () {
|
||||
editor.collapsed = false;
|
||||
editor.loading = false;
|
||||
scope.onSplitViewChanged();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the currently selected variant
|
||||
* @param {any} variantDropDownItem
|
||||
*/
|
||||
scope.selectVariant = function (variantDropDownItem) {
|
||||
|
||||
var editorIndex = _.findIndex(scope.editors, function (e) {
|
||||
return e === scope.editor;
|
||||
});
|
||||
|
||||
//if the editor index is zero, then update the query string to track the lang selection, otherwise if it's part
|
||||
//of a 2nd split view editor then update the model directly.
|
||||
if (editorIndex === 0) {
|
||||
//if we've made it this far, then update the query string
|
||||
$location.search("cculture", variantDropDownItem.language.culture);
|
||||
}
|
||||
else {
|
||||
//set all variant drop down items as inactive for this editor and then set the selected on as active
|
||||
for (var i = 0; i < scope.editor.content.variants.length; i++) {
|
||||
scope.editor.content.variants[i].active = false;
|
||||
}
|
||||
variantDropDownItem.active = true;
|
||||
|
||||
//get the variant content model and initialize the editor with that
|
||||
var variant = _.find(scope.content.variants, function (v) {
|
||||
return v.language.culture === variantDropDownItem.language.culture;
|
||||
});
|
||||
scope.editor.content = scope.initVariant({ variant: variant });
|
||||
}
|
||||
};
|
||||
|
||||
/** Closes the split view */
|
||||
scope.closeSplitView = function () {
|
||||
//TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular
|
||||
scope.editor.loading = true;
|
||||
scope.editor.collapsed = true;
|
||||
$timeout(function () {
|
||||
var index = _.findIndex(scope.editors, function(e) {
|
||||
return e === scope.editor;
|
||||
});
|
||||
scope.editors.splice(index, 1);
|
||||
scope.onSplitViewChanged();
|
||||
}, 400);
|
||||
};
|
||||
|
||||
//set the content to dirty if the header changes
|
||||
scope.$watch("contentHeaderForm.$dirty",
|
||||
function (newValue, oldValue) {
|
||||
if (newValue === true) {
|
||||
scope.editor.content.isDirty = true;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
scope: {
|
||||
//TODO: This should be turned into a proper component
|
||||
|
||||
page: "=",
|
||||
content: "=",
|
||||
editor: "=",
|
||||
editors: "=",
|
||||
//TODO: I don't like having this callback defined and would like to make this directive a bit less
|
||||
// coupled but right now don't have time
|
||||
initVariant: "&",
|
||||
onSplitViewChanged: "&"
|
||||
}));
|
||||
}
|
||||
|
||||
function onDestroy() {
|
||||
for (var i = 0; i < unsubscribe.length; i++) {
|
||||
unsubscribe[i]();
|
||||
}
|
||||
}
|
||||
|
||||
function backToListView() {
|
||||
$location.path(vm.page.listViewPath);
|
||||
};
|
||||
|
||||
return directive;
|
||||
/**
|
||||
* Used to proxy a callback
|
||||
* @param {any} variant
|
||||
*/
|
||||
function selectVariant(variant) {
|
||||
if (vm.onSelectVariant) {
|
||||
vm.onSelectVariant({ "variant": variant });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to proxy a callback
|
||||
* @param {any} variant
|
||||
*/
|
||||
function openSplitView(variant) {
|
||||
if (vm.onOpenSplitView) {
|
||||
vm.onOpenSplitView({ "variant": variant });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbVariantContent', variantContentDirective);
|
||||
angular.module('umbraco.directives').component('umbVariantContent', umbVariantContent);
|
||||
|
||||
})();
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* A component for split view content editing
|
||||
*/
|
||||
var umbVariantContentEditors = {
|
||||
templateUrl: 'views/components/content/umb-variant-content-editors.html',
|
||||
bindings: {
|
||||
page: "<",
|
||||
content: "<", //TODO: Not sure if this should be = since we are changing the 'active' property of a variant
|
||||
culture: "<"
|
||||
},
|
||||
controllerAs: 'vm',
|
||||
controller: umbVariantContentEditorsController
|
||||
};
|
||||
|
||||
function umbVariantContentEditorsController($scope, $element, $location, $timeout) {
|
||||
|
||||
var prevContentDateUpdated = null;
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.$onInit = onInit;
|
||||
vm.$onChanges = onChanges;
|
||||
vm.$doCheck = doCheck;
|
||||
vm.$postLink = postLink;
|
||||
|
||||
vm.openSplitView = openSplitView;
|
||||
vm.closeSplitView = closeSplitView;
|
||||
vm.selectVariant = selectVariant;
|
||||
|
||||
//Used to track how many content views there are (for split view there will be 2, it could support more in theory)
|
||||
vm.editors = [];
|
||||
|
||||
/** Called when the component initializes */
|
||||
function onInit() {
|
||||
prevContentDateUpdated = angular.copy(vm.content.updateDate);
|
||||
setActiveCulture();
|
||||
}
|
||||
|
||||
/** Called when the component has linked all elements, this is when the form controller is available */
|
||||
function postLink() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch for model changes
|
||||
* @param {any} changes
|
||||
*/
|
||||
function onChanges(changes) {
|
||||
|
||||
if (changes.culture && !changes.culture.isFirstChange() && changes.culture.currentValue !== changes.culture.previousValue) {
|
||||
setActiveCulture();
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows us to deep watch whatever we want - executes on every digest cycle */
|
||||
function doCheck() {
|
||||
if (!angular.equals(vm.content.updateDate, prevContentDateUpdated)) {
|
||||
setActiveCulture();
|
||||
prevContentDateUpdated = angular.copy(vm.content.updateDate);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is called when the split view changes based on the umb-variant-content */
|
||||
function splitViewChanged() {
|
||||
//send an event downwards
|
||||
$scope.$broadcast("editors.content.splitViewChanged", { editors: vm.editors });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active variant based on the current culture (query string)
|
||||
*/
|
||||
function setActiveCulture() {
|
||||
// set the active variant
|
||||
var activeVariant = null;
|
||||
_.each(vm.content.variants, function (v) {
|
||||
if (v.language && v.language.culture === vm.culture) {
|
||||
v.active = true;
|
||||
activeVariant = v;
|
||||
}
|
||||
else {
|
||||
v.active = false;
|
||||
}
|
||||
});
|
||||
if (!activeVariant) {
|
||||
// Set the first variant to active if we can't find it.
|
||||
// If the content item is invariant, then only one item exists in the array.
|
||||
vm.content.variants[0].active = true;
|
||||
activeVariant = vm.content.variants[0];
|
||||
}
|
||||
|
||||
insertVariantEditor(0, initVariant(activeVariant));
|
||||
|
||||
if (vm.editors.length > 1) {
|
||||
//now re-sync any other editor content (i.e. if split view is open)
|
||||
for (var s = 1; s < vm.editors.length; s++) {
|
||||
//get the variant from the scope model
|
||||
var variant = _.find(vm.content.variants, function (v) {
|
||||
return v.language.culture === vm.editors[s].content.language.culture;
|
||||
});
|
||||
vm.editors[s].content = initVariant(variant);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the editors collection for a given index for the specified variant
|
||||
* @param {any} index
|
||||
* @param {any} variant
|
||||
*/
|
||||
function insertVariantEditor(index, variant) {
|
||||
|
||||
var variantCulture = variant.language ? variant.language.culture : "invariant";
|
||||
|
||||
//check if the culture at the index is the same, if it's null an editor will be added
|
||||
var currentCulture = vm.editors.length === 0 || vm.editors.length <= index ? null : vm.editors[index].culture;
|
||||
|
||||
if (currentCulture !== variantCulture) {
|
||||
//Not the current culture which means we need to modify the array.
|
||||
//NOTE: It is not good enough to just replace the `content` object at a given index in the array
|
||||
// since that would mean that directives are not re-initialized.
|
||||
vm.editors.splice(index, 1, {
|
||||
content: variant,
|
||||
//used for "track-by" ng-repeat
|
||||
culture: variantCulture
|
||||
});
|
||||
}
|
||||
else {
|
||||
//replace the editor for the same culture
|
||||
vm.editors[index].content = variant;
|
||||
}
|
||||
}
|
||||
|
||||
function initVariant(variant) {
|
||||
//The model that is assigned to the editor contains the current content variant along
|
||||
//with a copy of the contentApps. This is required because each editor renders it's own
|
||||
//header and content apps section and the content apps contains the view for editing content itself
|
||||
//and we need to assign a view model to the subView so that it is scoped to the current
|
||||
//editor so that split views work.
|
||||
|
||||
//copy the apps from the main model if not assigned yet to the variant
|
||||
if (!variant.apps) {
|
||||
variant.apps = angular.copy(vm.content.apps);
|
||||
}
|
||||
|
||||
//if this is a variant has a culture/language than we need to assign the language drop down info
|
||||
if (variant.language) {
|
||||
//if the variant list that defines the header drop down isn't assigned to the variant then assign it now
|
||||
if (!variant.variants) {
|
||||
variant.variants = _.map(vm.content.variants,
|
||||
function (v) {
|
||||
return _.pick(v, "active", "language", "state");
|
||||
});
|
||||
}
|
||||
else {
|
||||
//merge the scope variants on top of the header variants collection (handy when needing to refresh)
|
||||
angular.extend(variant.variants,
|
||||
_.map(vm.content.variants,
|
||||
function (v) {
|
||||
return _.pick(v, "active", "language", "state");
|
||||
}));
|
||||
}
|
||||
|
||||
//ensure the current culture is set as the active one
|
||||
for (var i = 0; i < variant.variants.length; i++) {
|
||||
if (variant.variants[i].language.culture === variant.language.culture) {
|
||||
variant.variants[i].active = true;
|
||||
}
|
||||
else {
|
||||
variant.variants[i].active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//then assign the variant to a view model to the content app
|
||||
var contentApp = _.find(variant.apps, function (a) {
|
||||
return a.alias === "content";
|
||||
});
|
||||
contentApp.viewModel = variant;
|
||||
|
||||
return variant;
|
||||
}
|
||||
/**
|
||||
* Adds a new editor to the editors array to show content in a split view
|
||||
* @param {any} selectedVariant
|
||||
*/
|
||||
function openSplitView(selectedVariant) {
|
||||
|
||||
var selectedCulture = selectedVariant.language.culture;
|
||||
|
||||
//only the content app can be selected since no other apps are shown, and because we copy all of these apps
|
||||
//to the "editors" we need to update this across all editors
|
||||
for (var e = 0; e < vm.editors.length; e++) {
|
||||
var editor = vm.editors[e];
|
||||
for (var i = 0; i < editor.content.apps.length; i++) {
|
||||
var app = editor.content.apps[i];
|
||||
if (app.alias === "content") {
|
||||
app.active = true;
|
||||
}
|
||||
else {
|
||||
app.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Find the whole variant model based on the culture that was chosen
|
||||
var variant = _.find(vm.content.variants, function (v) {
|
||||
return v.language.culture === selectedCulture;
|
||||
});
|
||||
|
||||
insertVariantEditor(vm.editors.length, initVariant(variant));
|
||||
|
||||
//TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular
|
||||
editor.collapsed = true;
|
||||
editor.loading = true;
|
||||
$timeout(function () {
|
||||
editor.collapsed = false;
|
||||
editor.loading = false;
|
||||
splitViewChanged();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/** Closes the split view */
|
||||
function closeSplitView(editorIndex) {
|
||||
//TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular
|
||||
var editor = vm.editors[editorIndex];
|
||||
editor.loading = true;
|
||||
editor.collapsed = true;
|
||||
$timeout(function () {
|
||||
vm.editors.splice(editorIndex, 1);
|
||||
splitViewChanged();
|
||||
}, 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the currently selected variant
|
||||
* @param {any} variant This is the model of the variant/language drop down item in the editor header
|
||||
* @param {any} editorIndex The index of the editor being changed
|
||||
*/
|
||||
function selectVariant(variant, editorIndex) {
|
||||
|
||||
var variantCulture = variant.language ? variant.language.culture : "invariant";
|
||||
|
||||
//if the editor index is zero, then update the query string to track the lang selection, otherwise if it's part
|
||||
//of a 2nd split view editor then update the model directly.
|
||||
if (editorIndex === 0) {
|
||||
//If we've made it this far, then update the query string.
|
||||
//The editor will respond to this query string changing.
|
||||
$location.search("cculture", variant.language.culture);
|
||||
}
|
||||
else {
|
||||
|
||||
//Update the 'active' variant for this editor
|
||||
var editor = vm.editors[editorIndex];
|
||||
//set all variant drop down items as inactive for this editor and then set the selected one as active
|
||||
for (var i = 0; i < editor.content.variants.length; i++) {
|
||||
editor.content.variants[i].active = false;
|
||||
}
|
||||
variant.active = true;
|
||||
|
||||
//get the variant content model and initialize the editor with that
|
||||
var contentVariant = _.find(vm.content.variants,
|
||||
function (v) {
|
||||
return v.language.culture === variant.language.culture;
|
||||
});
|
||||
editor.content = initVariant(contentVariant);
|
||||
|
||||
//update the editors collection
|
||||
insertVariantEditor(editorIndex, contentVariant);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').component('umbVariantContentEditors', umbVariantContentEditors);
|
||||
|
||||
})();
|
||||
@@ -209,6 +209,13 @@ Use this directive to construct a header inside the main editor window.
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
|
||||
if (!scope.serverValidationNameField) {
|
||||
scope.serverValidationNameField = "Name";
|
||||
}
|
||||
if (!scope.serverValidationAliasField) {
|
||||
scope.serverValidationAliasField = "Alias";
|
||||
}
|
||||
|
||||
scope.vm = {};
|
||||
scope.vm.dropdownOpen = false;
|
||||
scope.vm.currentVariant = "";
|
||||
@@ -324,7 +331,9 @@ Use this directive to construct a header inside the main editor window.
|
||||
splitViewOpen: "=?",
|
||||
onOpenInSplitView: "&?",
|
||||
onCloseSplitView: "&?",
|
||||
onSelectVariant: "&?"
|
||||
onSelectVariant: "&?",
|
||||
serverValidationNameField: "@?",
|
||||
serverValidationAliasField: "@?"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
|
||||
// get document type details
|
||||
scope.mediaType = scope.node.contentType;
|
||||
// get node url
|
||||
scope.nodeUrl = scope.node.mediaLink;
|
||||
|
||||
// set the media link initially
|
||||
setMediaLink();
|
||||
|
||||
// make sure dates are formatted to the user's locale
|
||||
formatDatesToLocal();
|
||||
}
|
||||
@@ -36,6 +38,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
function setMediaLink(){
|
||||
scope.nodeUrl = scope.node.mediaLink;
|
||||
}
|
||||
|
||||
scope.openMediaType = function (mediaType) {
|
||||
var editor = {
|
||||
id: mediaType.id,
|
||||
@@ -48,11 +54,16 @@
|
||||
};
|
||||
editorService.mediaTypeEditor(editor);
|
||||
};
|
||||
|
||||
|
||||
// watch for content updates - reload content when node is saved, published etc.
|
||||
scope.$watch('node.updateDate', function(newValue, oldValue){
|
||||
if(!newValue) { return; }
|
||||
if(newValue === oldValue) { return; }
|
||||
|
||||
// Update the media link
|
||||
setMediaLink();
|
||||
|
||||
// Update the create and update dates
|
||||
formatDatesToLocal();
|
||||
});
|
||||
|
||||
@@ -64,7 +75,6 @@
|
||||
});
|
||||
|
||||
onInit();
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
|
||||
@@ -412,7 +412,7 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function OverlayDirective($timeout, formHelper, overlayHelper, localizationService, $q) {
|
||||
function OverlayDirective($timeout, formHelper, overlayHelper, localizationService, $q, $templateCache, $http, $compile) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
@@ -424,7 +424,8 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
var numberOfOverlays = 0;
|
||||
var isRegistered = false;
|
||||
|
||||
var modelCopy = {};
|
||||
var modelCopy = {};
|
||||
var unsubscribe = [];
|
||||
|
||||
function activate() {
|
||||
|
||||
@@ -459,6 +460,21 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
scope.view = "views/common/overlays/" + viewAlias + "/" + viewAlias + ".html";
|
||||
}
|
||||
|
||||
//if a custom parent scope is defined then we need to manually compile the view
|
||||
if (scope.parentScope) {
|
||||
var element = el.find(".scoped-view");
|
||||
$http.get(scope.view, { cache: $templateCache })
|
||||
.then(function (response) {
|
||||
var templateScope = scope.parentScope.$new();
|
||||
unsubscribe.push(function() {
|
||||
templateScope.$destroy();
|
||||
});
|
||||
templateScope.model = scope.model;
|
||||
element.html(response.data);
|
||||
element.show();
|
||||
$compile(element.contents())(templateScope);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -553,7 +569,7 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
var newObject = {};
|
||||
|
||||
for (var key in object) {
|
||||
if (key !== "event") {
|
||||
if (key !== "event" && key !== "parentScope") {
|
||||
newObject[key] = angular.copy(object[key]);
|
||||
}
|
||||
}
|
||||
@@ -652,14 +668,14 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
$q.when(scope.model.submit(model, modelCopy, scope.directive.enableConfirmButton)).then(
|
||||
function() {
|
||||
formHelper.resetForm({ scope: scope });
|
||||
}, angular.noop);
|
||||
});
|
||||
} else {
|
||||
unregisterOverlay();
|
||||
//wrap in a when since we don't know if this is a promise or not
|
||||
$q.when(scope.model.submit(model, modelCopy, scope.directive.enableConfirmButton)).then(
|
||||
function() {
|
||||
formHelper.resetForm({ scope: scope });
|
||||
}, angular.noop);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -684,8 +700,11 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
|
||||
};
|
||||
|
||||
scope.$on('$destroy', function(){
|
||||
unregisterOverlay();
|
||||
unsubscribe.push(unregisterOverlay);
|
||||
scope.$on('$destroy', function () {
|
||||
for (var i = 0; i < unsubscribe.length; i++) {
|
||||
unsubscribe[i]();
|
||||
}
|
||||
});
|
||||
|
||||
activate();
|
||||
@@ -701,7 +720,8 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
ngShow: "=",
|
||||
model: "=",
|
||||
view: "=",
|
||||
position: "@"
|
||||
position: "@",
|
||||
parentScope: "=?"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -58,9 +58,13 @@
|
||||
|
||||
entityResource.getPagedChildren(miniListView.node.id, scope.entityType, miniListView.pagination)
|
||||
.then(function (data) {
|
||||
|
||||
// update children
|
||||
miniListView.children = data.items;
|
||||
_.each(miniListView.children, function(c) {
|
||||
// child allowed by default
|
||||
c.allowed = true;
|
||||
|
||||
// convert legacy icon for node
|
||||
if(c.icon) {
|
||||
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
|
||||
@@ -72,6 +76,17 @@
|
||||
c.published = c.metaData.IsPublished;
|
||||
}
|
||||
}
|
||||
|
||||
// filter items if there is a filter and it's not advanced
|
||||
// ** ignores advanced filter at the moment
|
||||
if (scope.entityTypeFilter && !scope.entityTypeFilter.filterAdvanced) {
|
||||
var a = scope.entityTypeFilter.filter.toLowerCase().replace(/\s/g, '').split(',');
|
||||
var found = a.indexOf(c.metaData.ContentTypeAlias.toLowerCase()) >= 0;
|
||||
|
||||
if (!scope.entityTypeFilter.filterExclude && !found || scope.entityTypeFilter.filterExclude && found) {
|
||||
c.allowed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
// update pagination
|
||||
miniListView.pagination.totalItems = data.totalItems;
|
||||
@@ -87,7 +102,7 @@
|
||||
};
|
||||
|
||||
scope.selectNode = function(node) {
|
||||
if(scope.onSelect) {
|
||||
if (scope.onSelect && node.allowed) {
|
||||
scope.onSelect({'node': node});
|
||||
}
|
||||
};
|
||||
@@ -184,7 +199,8 @@
|
||||
entityType: "@",
|
||||
startNodeId: "=",
|
||||
onSelect: "&",
|
||||
onClose: "&"
|
||||
onClose: "&",
|
||||
entityTypeFilter: "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -50,6 +50,11 @@ Use this directive make an element sticky and follow the page when scrolling.
|
||||
|
||||
function activate() {
|
||||
|
||||
if (bar.parents(".umb-property").length > 1) {
|
||||
bar.addClass("nested");
|
||||
return;
|
||||
}
|
||||
|
||||
if (attr.scrollableContainer) {
|
||||
scrollableContainer = $(attr.scrollableContainer);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbIsolateForm', function () {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: ['form', '^form'],
|
||||
link: function (scope, element, attrs, forms) {
|
||||
forms[1].$removeControl(forms[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -3,16 +3,20 @@
|
||||
|
||||
function showValidationOnSubmit(serverValidationManager) {
|
||||
return {
|
||||
require: "ngMessages",
|
||||
require: ["ngMessages", "^^?valFormManager"],
|
||||
restrict: "A",
|
||||
|
||||
scope: {
|
||||
form: "=?"
|
||||
},
|
||||
link: function (scope, element, attr, ctrl) {
|
||||
|
||||
//We can either get the form submitted status by the parent directive valFormManager (if we add a property to it)
|
||||
//or we can just check upwards in the DOM for the css class (easier for now).
|
||||
var formMgr = ctrl.length > 1 ? ctrl[1] : null;
|
||||
|
||||
//We can either get the form submitted status by the parent directive valFormManager
|
||||
//or we can check upwards in the DOM for the css class... lets try both :)
|
||||
//The initial hidden state can't always be hidden because when we switch variants in the content editor we cannot
|
||||
//reset the status.
|
||||
var submitted = element.closest(".show-validation").length > 0;
|
||||
var submitted = element.closest(".show-validation").length > 0 || (formMgr && formMgr.showValidation);
|
||||
if (!submitted) {
|
||||
element.hide();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
|
||||
var SAVED_EVENT_NAME = "formSubmitted";
|
||||
|
||||
return {
|
||||
require: "form",
|
||||
require: ["form", "^^?valFormManager"],
|
||||
restrict: "A",
|
||||
controller: function($scope) {
|
||||
//This exposes an API for direct use with this directive
|
||||
@@ -35,6 +35,8 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
|
||||
}));
|
||||
};
|
||||
|
||||
this.showValidation = $scope.showValidation === true;
|
||||
|
||||
//Ensure to remove the event handlers when this instance is destroyted
|
||||
$scope.$on('$destroy', function () {
|
||||
for (var u in unsubscribe) {
|
||||
@@ -42,7 +44,10 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
|
||||
}
|
||||
});
|
||||
},
|
||||
link: function (scope, element, attr, formCtrl) {
|
||||
link: function (scope, element, attr, ctrls) {
|
||||
|
||||
var formCtrl = ctrls[0];
|
||||
var parentFormMgr = ctrls.length > 0 ? ctrls[1] : null;
|
||||
|
||||
var labels = {};
|
||||
|
||||
@@ -96,8 +101,9 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
|
||||
var isSavingNewItem = false;
|
||||
|
||||
//we should show validation if there are any msgs in the server validation collection
|
||||
if (serverValidationManager.items.length > 0) {
|
||||
if (serverValidationManager.items.length > 0 || (parentFormMgr && parentFormMgr.showValidation)) {
|
||||
element.addClass(SHOW_VALIDATION_CLASS_NAME);
|
||||
scope.showValidation = true;
|
||||
}
|
||||
|
||||
var unsubscribe = [];
|
||||
@@ -105,7 +111,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
|
||||
//listen for the forms saving event
|
||||
unsubscribe.push(scope.$on(SAVING_EVENT_NAME, function(ev, args) {
|
||||
element.addClass(SHOW_VALIDATION_CLASS_NAME);
|
||||
|
||||
scope.showValidation = true;
|
||||
//set the flag so we can check to see if we should display the error.
|
||||
isSavingNewItem = $routeParams.create;
|
||||
}));
|
||||
@@ -114,7 +120,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
|
||||
unsubscribe.push(scope.$on(SAVED_EVENT_NAME, function(ev, args) {
|
||||
//remove validation class
|
||||
element.removeClass(SHOW_VALIDATION_CLASS_NAME);
|
||||
|
||||
scope.showValidation = false;
|
||||
//clear form state as at this point we retrieve new data from the server
|
||||
//and all validation will have cleared at this point
|
||||
formCtrl.$setPristine();
|
||||
|
||||
@@ -26,12 +26,14 @@
|
||||
function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
/** internal method process the saving of data and post processing the result */
|
||||
function saveContentItem(content, action, files, restApiUrl) {
|
||||
function saveContentItem(content, action, files, restApiUrl, showNotifications) {
|
||||
|
||||
return umbRequestHelper.postSaveContent({
|
||||
restApiUrl: restApiUrl,
|
||||
content: content,
|
||||
action: action,
|
||||
files: files,
|
||||
showNotifications: showNotifications,
|
||||
dataFormatter: function (c, a) {
|
||||
return umbDataFormatter.formatContentPostData(c, a);
|
||||
}
|
||||
@@ -632,22 +634,23 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
* @param {Object} content The content item object with changes applied
|
||||
* @param {Bool} isNew set to true to create a new item or to update an existing
|
||||
* @param {Array} files collection of files for the document
|
||||
* @param {Array} files collection of files for the document
|
||||
* @param {Bool} showNotifications an option to disable/show notifications (default is true)
|
||||
* @returns {Promise} resourcePromise object containing the saved content item.
|
||||
*
|
||||
*/
|
||||
save: function (content, isNew, files) {
|
||||
save: function (content, isNew, files, showNotifications) {
|
||||
var endpoint = umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"PostSave");
|
||||
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint);
|
||||
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint, showNotifications);
|
||||
},
|
||||
|
||||
saveBlueprint: function (content, isNew, files) {
|
||||
saveBlueprint: function (content, isNew, files, showNotifications) {
|
||||
var endpoint = umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"PostSaveBlueprint");
|
||||
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint);
|
||||
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint, showNotifications);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -674,15 +677,16 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
* @param {Object} content The content item object with changes applied
|
||||
* @param {Bool} isNew set to true to create a new item or to update an existing
|
||||
* @param {Array} files collection of files for the document
|
||||
* @param {Array} files collection of files for the document
|
||||
* @param {Bool} showNotifications an option to disable/show notifications (default is true)
|
||||
* @returns {Promise} resourcePromise object containing the saved content item.
|
||||
*
|
||||
*/
|
||||
publish: function (content, isNew, files) {
|
||||
publish: function (content, isNew, files, showNotifications) {
|
||||
var endpoint = umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"PostSave");
|
||||
return saveContentItem(content, "publish" + (isNew ? "New" : ""), files, endpoint);
|
||||
return saveContentItem(content, "publish" + (isNew ? "New" : ""), files, endpoint, showNotifications);
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -298,10 +298,10 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter, loca
|
||||
|
||||
},
|
||||
|
||||
createCollection: function (parentId, collectionName, collectionItemName, collectionIcon, collectionItemIcon) {
|
||||
createCollection: function (parentId, collectionName, collectionCreateTemplate, collectionItemName, collectionItemCreateTemplate, collectionIcon, collectionItemIcon) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionItemName: collectionItemName, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon })),
|
||||
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionCreateTemplate: collectionCreateTemplate, collectionItemName: collectionItemName, collectionItemCreateTemplate: collectionItemCreateTemplate, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
|
||||
'Failed to create collection under ' + parentId);
|
||||
|
||||
},
|
||||
|
||||
@@ -66,7 +66,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
|
||||
args.scope.busy = true;
|
||||
|
||||
return args.saveMethod(args.content, $routeParams.create, fileManager.getFiles())
|
||||
return args.saveMethod(args.content, $routeParams.create, fileManager.getFiles(), args.showNotifications)
|
||||
.then(function (data) {
|
||||
|
||||
formHelper.resetForm({ scope: args.scope });
|
||||
@@ -262,7 +262,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
// if save button is alread the default don't change it just update the label
|
||||
if (buttons.defaultButton && buttons.defaultButton.letter === "A") {
|
||||
buttons.defaultButton.labelKey = "buttons_saveAndSchedule";
|
||||
return;
|
||||
return buttons;
|
||||
}
|
||||
|
||||
if (buttons.defaultButton && buttons.subButtons && buttons.subButtons.length > 0) {
|
||||
@@ -439,8 +439,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
var shouldIgnore = function (propName) {
|
||||
return _.some([
|
||||
"variants",
|
||||
"notifications",
|
||||
"ModelState",
|
||||
|
||||
"tabs",
|
||||
"properties",
|
||||
"apps",
|
||||
@@ -599,8 +598,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
|
||||
//add model state errors to notifications
|
||||
if (args.showNotifications) {
|
||||
for (var e in modelState) {
|
||||
notificationsService.error("Validation", modelState[e][0]);
|
||||
for (var e in args.err.data.ModelState) {
|
||||
notificationsService.error("Validation", args.err.data.ModelState[e][0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -761,13 +761,13 @@ function tinyMceService($log, imageHelper, $http, $timeout, macroResource, macro
|
||||
* @param {string} input the string to parse
|
||||
*/
|
||||
getAnchorNames: function (input) {
|
||||
var anchors = [];
|
||||
if (!input) {
|
||||
return anchors;
|
||||
}
|
||||
|
||||
var anchors = [];
|
||||
if (!input) {
|
||||
return anchors;
|
||||
}
|
||||
|
||||
var anchorPattern = /<a id=\\"(.*?)\\">/gi;
|
||||
var matches = input.match(anchorPattern);
|
||||
var matches = input.match(anchorPattern);
|
||||
|
||||
|
||||
if (matches) {
|
||||
@@ -776,7 +776,9 @@ function tinyMceService($log, imageHelper, $http, $timeout, macroResource, macro
|
||||
});
|
||||
}
|
||||
|
||||
return anchors;
|
||||
return anchors.filter(function(val, i, self) {
|
||||
return self.indexOf(val) === i;
|
||||
});
|
||||
},
|
||||
|
||||
insertLinkInEditor: function (editor, target, anchorElm) {
|
||||
|
||||
@@ -136,8 +136,8 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
|
||||
//create the callbacs based on whats been passed in.
|
||||
var callbacks = {
|
||||
success: ((!opts || !opts.success) ? defaultSuccess : opts.success),
|
||||
error: ((!opts || !opts.error) ? defaultError : opts.error)
|
||||
success: (!opts || !opts.success) ? defaultSuccess : opts.success,
|
||||
error: (!opts || !opts.error ? defaultError : opts.error)
|
||||
};
|
||||
|
||||
return httpPromise.then(function (response) {
|
||||
@@ -156,7 +156,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
//this is a JS/angular error that we should deal with
|
||||
return $q.reject({
|
||||
errorMsg: response.message
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//invoke the callback
|
||||
@@ -188,12 +188,22 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
errorMsg: result.errorMsg,
|
||||
data: result.data,
|
||||
status: result.status
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/** Used for saving content/media/members specifically */
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.contentResource#postSaveContent
|
||||
* @methodOf umbraco.resources.contentResource
|
||||
*
|
||||
* @description
|
||||
* Used for saving content/media/members specifically
|
||||
*
|
||||
* @param {Object} args arguments object
|
||||
* @returns {Promise} http promise object.
|
||||
*/
|
||||
postSaveContent: function (args) {
|
||||
|
||||
if (!args.restApiUrl) {
|
||||
@@ -211,6 +221,9 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
if (!args.dataFormatter) {
|
||||
throw "args.dataFormatter is a required argument";
|
||||
}
|
||||
if (args.showNotifications === null || args.showNotifications === undefined) {
|
||||
args.showNotifications = true;
|
||||
}
|
||||
|
||||
//save the active tab id so we can set it when the data is returned.
|
||||
var activeTab = _.find(args.content.tabs, function (item) {
|
||||
@@ -246,7 +259,9 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
response.data.tabs[activeTabIndex].active = true;
|
||||
}
|
||||
|
||||
formHelper.showNotifications(response.data);
|
||||
if (args.showNotifications) {
|
||||
formHelper.showNotifications(response.data);
|
||||
}
|
||||
|
||||
//TODO: Do we need to pass the result through umbDataFormatter.formatContentGetData? Right now things work so not sure but we should check
|
||||
|
||||
@@ -278,7 +293,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
else if (args.showNotifications) {
|
||||
formHelper.showNotifications(response.data);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
{ "value": 0, "name": "Active", "key": "Active", "color": "success" },
|
||||
{ "value": 1, "name": "Disabled", "key": "Disabled", "color": "danger" },
|
||||
{ "value": 2, "name": "Locked out", "key": "LockedOut", "color": "danger" },
|
||||
{ "value": 3, "name": "Invited", "key": "Invited", "color": "warning" }
|
||||
{ "value": 3, "name": "Invited", "key": "Invited", "color": "warning" },
|
||||
{ "value": 4, "name": "Inactive", "key": "Inactive", "color": "warning" }
|
||||
];
|
||||
|
||||
angular.forEach(userStates, function (userState) {
|
||||
|
||||
@@ -13,23 +13,31 @@
|
||||
list-style: none;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
margin-right: 10px;
|
||||
margin-right: -10px;
|
||||
}
|
||||
|
||||
.umb-app-header__action a {
|
||||
color: @white;
|
||||
opacity: 0.6;
|
||||
font-size: 22px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: @appHeaderHeight;
|
||||
}
|
||||
|
||||
.umb-app-header__action a:hover,
|
||||
.umb-app-header__action a:focus {
|
||||
opacity: 1;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.umb-app-header__action-icon {
|
||||
opacity: 0.6;
|
||||
color: @white;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.umb-app-header__action a:hover .umb-app-header__action-icon,
|
||||
.umb-app-header__action a:focus .umb-app-header__action-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||