Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0230a1586 | |||
| 57426ae895 | |||
| 6bafd3a254 | |||
| 564074a2bd | |||
| 617bdb2bd1 | |||
| 2c91f9bf14 | |||
| f146262031 | |||
| ddae0d01e3 | |||
| b9ee85dabc | |||
| 29fa6061a9 | |||
| 8ee61312b6 | |||
| cfd4b8c7bf | |||
| 7ce3b6046c | |||
| 43d98c9682 | |||
| 62e4825a5e | |||
| 81d35c6079 | |||
| 7e15077f96 | |||
| 6543e3c058 | |||
| 7c73c379cf | |||
| 4bc9d96bce | |||
| 45fd54d046 | |||
| 4f062306a6 | |||
| 0beda4b790 | |||
| 213ea6470f | |||
| e783308cf0 | |||
| 01f49bb07e | |||
| a3d08c19c5 | |||
| da0a1c808a | |||
| 08965982fd | |||
| b37197f66a |
+10
-1
@@ -114,6 +114,15 @@ Some parts of our source code is over 10 years old now. And when we say "old", w
|
||||
There's two big areas that you should know about:
|
||||
|
||||
1. The Umbraco backoffice is a extensible AngularJS app and requires you to run a `gulp dev` command while you're working with it, so changes are copied over to the appropriate directories and you can refresh your browser to view the results of your changes.
|
||||
You may need to run the following commands to set up gulp properly:
|
||||
```
|
||||
npm cache clean
|
||||
npm install -g bower
|
||||
npm install -g gulp
|
||||
npm install -g gulp-cli
|
||||
npm install
|
||||
gulp build
|
||||
```
|
||||
2. "The rest" is a C# based codebase, with some traces of our WebForms past but mostly ASP.NET MVC based these days. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
|
||||
|
||||
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
|
||||
@@ -171,4 +180,4 @@ Did something not work as expected? Try leaving a note in the ["Contributing to
|
||||
|
||||
## Credits
|
||||
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
|
||||
@@ -8,6 +8,7 @@ function Get-UmbracoBuildEnv
|
||||
# store tools in the module's directory
|
||||
# and cache them for two days
|
||||
$path = "$PSScriptRoot\temp"
|
||||
$src = "$PSScriptRoot\..\..\..\src"
|
||||
$cache = 2
|
||||
|
||||
if (-not (test-path $path))
|
||||
@@ -37,7 +38,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $sevenZip))
|
||||
{
|
||||
Write-Host "Download 7-Zip..."
|
||||
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install 7-Zip.CommandLine -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
|
||||
$file = ls -path "$dir" -name 7za.exe -recurse
|
||||
$file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
|
||||
@@ -54,7 +55,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $vswhere))
|
||||
{
|
||||
Write-Host "Download VsWhere..."
|
||||
&$nuget install vswhere -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install vswhere -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\vswhere.*" | sort -property Name -descending | select -first 1
|
||||
$file = ls -path "$dir" -name vswhere.exe -recurse
|
||||
mv "$dir\$file" $vswhere
|
||||
@@ -70,7 +71,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $semver))
|
||||
{
|
||||
Write-Host "Download Semver..."
|
||||
&$nuget install semver -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install semver -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\semver.*" | sort -property Name -descending | select -first 1
|
||||
$file = "$dir\lib\net452\Semver.dll"
|
||||
if (-not (test-path $file))
|
||||
|
||||
@@ -445,7 +445,7 @@ function Restore-NuGet
|
||||
Write-Host ">> Restore NuGet"
|
||||
Write-Host "Logging to $tmp\nuget.restore.log"
|
||||
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" > "$tmp\nuget.restore.log"
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" -configfile "$src\NuGet.config" > "$tmp\nuget.restore.log"
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.9.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.9.1")]
|
||||
[assembly: AssemblyFileVersion("7.9.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.9.2")]
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.9.1");
|
||||
private static readonly Version Version = new Version("7.9.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -26,6 +27,7 @@ namespace Umbraco.Core.IO
|
||||
private ShadowWrapper _xsltFileSystem;
|
||||
private ShadowWrapper _masterPagesFileSystem;
|
||||
private ShadowWrapper _mvcViewsFileSystem;
|
||||
private ShadowWrapper _javaScriptLibraryFileSystem;
|
||||
|
||||
#region Singleton & Constructor
|
||||
|
||||
@@ -113,6 +115,7 @@ namespace Umbraco.Core.IO
|
||||
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
|
||||
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
|
||||
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
|
||||
var javaScriptLibraryFileSystem = new PhysicalFileSystem(Path.Combine(SystemDirectories.Umbraco, "lib"));
|
||||
|
||||
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
|
||||
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", ScopeProvider);
|
||||
@@ -123,6 +126,7 @@ namespace Umbraco.Core.IO
|
||||
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", ScopeProvider);
|
||||
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", ScopeProvider);
|
||||
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", ScopeProvider);
|
||||
_javaScriptLibraryFileSystem = new ShadowWrapper(javaScriptLibraryFileSystem, "Lib", ScopeProvider);
|
||||
|
||||
// filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again
|
||||
MediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
|
||||
@@ -143,6 +147,7 @@ namespace Umbraco.Core.IO
|
||||
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
|
||||
public IFileSystem2 MasterPagesFileSystem { get { return _mvcViewsFileSystem; } }
|
||||
public IFileSystem2 MvcViewsFileSystem { get { return _mvcViewsFileSystem; } }
|
||||
internal IFileSystem2 JavaScriptLibraryFileSystem { get { return _javaScriptLibraryFileSystem; } }
|
||||
public MediaFileSystem MediaFileSystem { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -637,4 +637,4 @@ namespace Umbraco.Core.Services
|
||||
public static event TypedEventHandler<IDataTypeService, MoveEventArgs<IDataTypeDefinition>> Moved;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp50</s:String></wpf:ResourceDictionary>
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -142,10 +143,18 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
internal static bool IsClientSideRequest(this Uri url)
|
||||
{
|
||||
var ext = Path.GetExtension(url.LocalPath);
|
||||
if (ext.IsNullOrWhiteSpace()) return false;
|
||||
var toInclude = new[] { ".aspx", ".ashx", ".asmx", ".axd", ".svc" };
|
||||
return toInclude.Any(ext.InvariantEquals) == false;
|
||||
try
|
||||
{
|
||||
var ext = Path.GetExtension(url.LocalPath);
|
||||
if (ext.IsNullOrWhiteSpace()) return false;
|
||||
var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"};
|
||||
return toInclude.Any(ext.InvariantEquals) == false;
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
LogHelper.Error(typeof(UriExtensions), "Failed to determine if request was client side", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -311,4 +320,4 @@ namespace Umbraco.Core
|
||||
return new Uri(uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,53 +93,59 @@ namespace Umbraco.Tests.Routing
|
||||
var result = uri.IsClientSideRequest();
|
||||
Assert.AreEqual(assert, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Client_Side_Request_InvalidPath_ReturnFalse()
|
||||
{
|
||||
//This url is invalid. Default to false when the extension cannot be determined
|
||||
var uri = new Uri("http://test.com/installing-modules+foobar+\"yipee\"");
|
||||
var result = uri.IsClientSideRequest();
|
||||
Assert.AreEqual(false, result);
|
||||
}
|
||||
|
||||
//NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
|
||||
// we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
|
||||
// to ensure that each one is individually tested.
|
||||
|
||||
//[TestCase("/", 1046)]
|
||||
//[TestCase("/home.aspx", 1046)]
|
||||
//[TestCase("/home/sub1.aspx", 1173)]
|
||||
//[TestCase("/home.aspx?altTemplate=blah", 1046)]
|
||||
//public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
|
||||
//{
|
||||
// var httpContextFactory = new FakeHttpContextFactory(url);
|
||||
// var httpContext = httpContextFactory.HttpContext;
|
||||
// var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
|
||||
// var contentStore = new ContentStore(umbracoContext);
|
||||
// var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
// umbracoContext.RoutingContext = new RoutingContext(
|
||||
// new IPublishedContentLookup[] {new LookupByNiceUrl()},
|
||||
// new DefaultLastChanceLookup(),
|
||||
// contentStore,
|
||||
// niceUrls);
|
||||
|
||||
// StateHelper.HttpContext = httpContext;
|
||||
|
||||
//NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
|
||||
// we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
|
||||
// to ensure that each one is individually tested.
|
||||
// //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
|
||||
// //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
|
||||
// Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
|
||||
|
||||
//[TestCase("/", 1046)]
|
||||
//[TestCase("/home.aspx", 1046)]
|
||||
//[TestCase("/home/sub1.aspx", 1173)]
|
||||
//[TestCase("/home.aspx?altTemplate=blah", 1046)]
|
||||
//public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
|
||||
//{
|
||||
// var httpContextFactory = new FakeHttpContextFactory(url);
|
||||
// var httpContext = httpContextFactory.HttpContext;
|
||||
// var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
|
||||
// var contentStore = new ContentStore(umbracoContext);
|
||||
// var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
|
||||
// umbracoContext.RoutingContext = new RoutingContext(
|
||||
// new IPublishedContentLookup[] {new LookupByNiceUrl()},
|
||||
// new DefaultLastChanceLookup(),
|
||||
// contentStore,
|
||||
// niceUrls);
|
||||
// //need to create a template with id 1045
|
||||
// var template = Template.MakeNew("test", new User(0));
|
||||
|
||||
// StateHelper.HttpContext = httpContext;
|
||||
// SetupUmbracoContextForTest(umbracoContext, template);
|
||||
|
||||
// //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
|
||||
// //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
|
||||
// Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
|
||||
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
|
||||
|
||||
// //need to create a template with id 1045
|
||||
// var template = Template.MakeNew("test", new User(0));
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest);
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
|
||||
// Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
|
||||
|
||||
// SetupUmbracoContextForTest(umbracoContext, template);
|
||||
//}
|
||||
|
||||
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
|
||||
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest);
|
||||
// Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
|
||||
// Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
|
||||
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
|
||||
// Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,12 @@
|
||||
"codemirror"
|
||||
],
|
||||
"sources": {
|
||||
"moment": "bower_components/moment/min/moment-with-locales.js",
|
||||
"moment": [
|
||||
"bower_components/moment/min/moment.min.js",
|
||||
"bower_components/moment/min/moment-with-locales.js",
|
||||
"bower_components/moment/min/moment-with-locales.min.js",
|
||||
"bower_components/moment/locale/*.js"
|
||||
],
|
||||
"underscore": [
|
||||
"bower_components/underscore/underscore-min.js",
|
||||
"bower_components/underscore/underscore-min.map"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 180 KiB |
+1
-1
@@ -50,7 +50,7 @@
|
||||
|
||||
scope.openDocumentType = function (documentType) {
|
||||
var url = "/settings/documenttypes/edit/" + documentType.id;
|
||||
$location.path(url);
|
||||
$location.url(url);
|
||||
};
|
||||
|
||||
scope.updateTemplate = function (templateAlias) {
|
||||
|
||||
+589
-669
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -10,12 +10,12 @@ function noDirtyCheck() {
|
||||
require: 'ngModel',
|
||||
link: function (scope, elm, attrs, ctrl) {
|
||||
|
||||
elm.focus(function () {
|
||||
scope.$watch(function() {
|
||||
ctrl.$pristine = false;
|
||||
});
|
||||
});
|
||||
|
||||
var alwaysFalse = {
|
||||
get: function () { return false; },
|
||||
set: function () { }
|
||||
};
|
||||
Object.defineProperty(ctrl, '$pristine', alwaysFalse);
|
||||
Object.defineProperty(ctrl, '$dirty', alwaysFalse);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -357,37 +357,16 @@ function dataTypeResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
"PostCreateContainer",
|
||||
{ parentId: parentId, name: name })),
|
||||
'Failed to create a folder under parent id ' + parentId);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
renameContainer: function (id, name) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post
|
||||
(umbRequestHelper.getApiUrl(
|
||||
$http.post
|
||||
(umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"PostRenameContainer",
|
||||
{ id: id, name: name })),
|
||||
"Failed to rename the folder with id " + id);
|
||||
},
|
||||
|
||||
getContainer: function (name) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"GetContainer",
|
||||
{ name: name })),
|
||||
'No container found with name: ' + name);
|
||||
|
||||
},
|
||||
|
||||
containerExist: function (name) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"dataTypeApiBaseUrl",
|
||||
"ContainerExist",
|
||||
{ name: name })));
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function javascriptLibraryService($q, $http, umbRequestHelper) {
|
||||
|
||||
var existingLocales = [];
|
||||
|
||||
function getSupportedLocalesForMoment() {
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (existingLocales.length === 0) {
|
||||
umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"backOfficeAssetsApiBaseUrl",
|
||||
"GetSupportedMomentLocales")),
|
||||
'Failed to get cultures').then(function(locales) {
|
||||
existingLocales = locales;
|
||||
deferred.resolve(existingLocales);
|
||||
});
|
||||
} else {
|
||||
deferred.resolve(existingLocales);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
var service = {
|
||||
getSupportedLocalesForMoment: getSupportedLocalesForMoment
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('javascriptLibraryService', javascriptLibraryService);
|
||||
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,285 +1,324 @@
|
||||
angular.module('umbraco.services')
|
||||
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) {
|
||||
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, assetsService, dialogService, $timeout, angularHelper, $http, javascriptLibraryService) {
|
||||
|
||||
var currentUser = null;
|
||||
var lastUserId = null;
|
||||
var loginDialog = null;
|
||||
var currentUser = null;
|
||||
var lastUserId = null;
|
||||
var loginDialog = null;
|
||||
|
||||
//this tracks the last date/time that the user's remainingAuthSeconds was updated from the server
|
||||
// this is used so that we know when to go and get the user's remaining seconds directly.
|
||||
var lastServerTimeoutSet = null;
|
||||
//this tracks the last date/time that the user's remainingAuthSeconds was updated from the server
|
||||
// this is used so that we know when to go and get the user's remaining seconds directly.
|
||||
var lastServerTimeoutSet = null;
|
||||
|
||||
function openLoginDialog(isTimedOut) {
|
||||
if (!loginDialog) {
|
||||
loginDialog = dialogService.open({
|
||||
function openLoginDialog(isTimedOut) {
|
||||
if (!loginDialog) {
|
||||
loginDialog = dialogService.open({
|
||||
|
||||
//very special flag which means that global events cannot close this dialog
|
||||
manualClose: true,
|
||||
//very special flag which means that global events cannot close this dialog
|
||||
manualClose: true,
|
||||
|
||||
template: 'views/common/dialogs/login.html',
|
||||
modalClass: "login-overlay",
|
||||
animation: "slide",
|
||||
show: true,
|
||||
callback: onLoginDialogClose,
|
||||
dialogData: {
|
||||
isTimedOut: isTimedOut
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onLoginDialogClose(success) {
|
||||
loginDialog = null;
|
||||
|
||||
if (success) {
|
||||
securityRetryQueue.retryAll(currentUser.name);
|
||||
}
|
||||
else {
|
||||
securityRetryQueue.cancelAll();
|
||||
$location.path('/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This methods will set the current user when it is resolved and
|
||||
will then start the counter to count in-memory how many seconds they have
|
||||
remaining on the auth session
|
||||
*/
|
||||
function setCurrentUser(usr) {
|
||||
if (!usr.remainingAuthSeconds) {
|
||||
throw "The user object is invalid, the remainingAuthSeconds is required.";
|
||||
}
|
||||
currentUser = usr;
|
||||
lastServerTimeoutSet = new Date();
|
||||
//start the timer
|
||||
countdownUserTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
Method to count down the current user's timeout seconds,
|
||||
this will continually count down their current remaining seconds every 5 seconds until
|
||||
there are no more seconds remaining.
|
||||
*/
|
||||
function countdownUserTimeout() {
|
||||
|
||||
$timeout(function () {
|
||||
|
||||
if (currentUser) {
|
||||
//countdown by 5 seconds since that is how long our timer is for.
|
||||
currentUser.remainingAuthSeconds -= 5;
|
||||
|
||||
//if there are more than 30 remaining seconds, recurse!
|
||||
if (currentUser.remainingAuthSeconds > 30) {
|
||||
|
||||
//we need to check when the last time the timeout was set from the server, if
|
||||
// it has been more than 30 seconds then we'll manually go and retrieve it from the
|
||||
// server - this helps to keep our local countdown in check with the true timeout.
|
||||
if (lastServerTimeoutSet != null) {
|
||||
var now = new Date();
|
||||
var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000;
|
||||
|
||||
if (seconds > 30) {
|
||||
|
||||
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
|
||||
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
|
||||
lastServerTimeoutSet = null;
|
||||
|
||||
//now go get it from the server
|
||||
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
authResource.getRemainingTimeoutSeconds().then(function (result) {
|
||||
setUserTimeoutInternal(result);
|
||||
});
|
||||
template: 'views/common/dialogs/login.html',
|
||||
modalClass: "login-overlay",
|
||||
animation: "slide",
|
||||
show: true,
|
||||
callback: onLoginDialogClose,
|
||||
dialogData: {
|
||||
isTimedOut: isTimedOut
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
}
|
||||
else {
|
||||
function onLoginDialogClose(success) {
|
||||
loginDialog = null;
|
||||
|
||||
//we are either timed out or very close to timing out so we need to show the login dialog.
|
||||
if (Umbraco.Sys.ServerVariables.umbracoSettings.keepUserLoggedIn !== true) {
|
||||
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
try {
|
||||
//NOTE: We are calling this again so that the server can create a log that the timeout has expired, we
|
||||
// don't actually care about this result.
|
||||
authResource.getRemainingTimeoutSeconds();
|
||||
}
|
||||
finally {
|
||||
userAuthExpired();
|
||||
}
|
||||
});
|
||||
if (success) {
|
||||
securityRetryQueue.retryAll(currentUser.name);
|
||||
}
|
||||
else {
|
||||
//we've got less than 30 seconds remaining so let's check the server
|
||||
|
||||
if (lastServerTimeoutSet != null) {
|
||||
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
|
||||
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
|
||||
lastServerTimeoutSet = null;
|
||||
|
||||
//now go get it from the server
|
||||
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
authResource.getRemainingTimeoutSeconds().then(function (result) {
|
||||
setUserTimeoutInternal(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
|
||||
securityRetryQueue.cancelAll();
|
||||
$location.path('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 5000, //every 5 seconds
|
||||
false); //false = do NOT execute a digest for every iteration
|
||||
}
|
||||
|
||||
/** Called to update the current user's timeout */
|
||||
function setUserTimeoutInternal(newTimeout) {
|
||||
|
||||
|
||||
var asNumber = parseFloat(newTimeout);
|
||||
if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
|
||||
currentUser.remainingAuthSeconds = newTimeout;
|
||||
lastServerTimeoutSet = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
/** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */
|
||||
function userAuthExpired(isLogout) {
|
||||
//store the last user id and clear the user
|
||||
if (currentUser && currentUser.id !== undefined) {
|
||||
lastUserId = currentUser.id;
|
||||
}
|
||||
|
||||
if (currentUser) {
|
||||
currentUser.remainingAuthSeconds = 0;
|
||||
}
|
||||
|
||||
lastServerTimeoutSet = null;
|
||||
currentUser = null;
|
||||
|
||||
//broadcast a global event that the user is no longer logged in
|
||||
eventsService.emit("app.notAuthenticated");
|
||||
|
||||
openLoginDialog(isLogout === undefined ? true : !isLogout);
|
||||
}
|
||||
|
||||
// Register a handler for when an item is added to the retry queue
|
||||
securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) {
|
||||
if (securityRetryQueue.hasMore()) {
|
||||
userAuthExpired();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
/** Internal method to display the login dialog */
|
||||
_showLoginDialog: function () {
|
||||
openLoginDialog();
|
||||
},
|
||||
/** Returns a promise, sends a request to the server to check if the current cookie is authorized */
|
||||
isAuthenticated: function () {
|
||||
//if we've got a current user then just return true
|
||||
if (currentUser) {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve(true);
|
||||
return deferred.promise;
|
||||
/**
|
||||
This methods will set the current user when it is resolved and
|
||||
will then start the counter to count in-memory how many seconds they have
|
||||
remaining on the auth session
|
||||
*/
|
||||
function setCurrentUser(usr) {
|
||||
if (!usr.remainingAuthSeconds) {
|
||||
throw "The user object is invalid, the remainingAuthSeconds is required.";
|
||||
}
|
||||
currentUser = usr;
|
||||
lastServerTimeoutSet = new Date();
|
||||
//start the timer
|
||||
countdownUserTimeout();
|
||||
}
|
||||
return authResource.isAuthenticated();
|
||||
},
|
||||
|
||||
/** Returns a promise, sends a request to the server to validate the credentials */
|
||||
authenticate: function (login, password) {
|
||||
/**
|
||||
Method to count down the current user's timeout seconds,
|
||||
this will continually count down their current remaining seconds every 5 seconds until
|
||||
there are no more seconds remaining.
|
||||
*/
|
||||
function countdownUserTimeout() {
|
||||
|
||||
return authResource.performLogin(login, password)
|
||||
.then(this.setAuthenticationSuccessful);
|
||||
},
|
||||
setAuthenticationSuccessful: function (data) {
|
||||
$timeout(function () {
|
||||
|
||||
//when it's successful, return the user data
|
||||
setCurrentUser(data);
|
||||
if (currentUser) {
|
||||
//countdown by 5 seconds since that is how long our timer is for.
|
||||
currentUser.remainingAuthSeconds -= 5;
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" };
|
||||
//if there are more than 30 remaining seconds, recurse!
|
||||
if (currentUser.remainingAuthSeconds > 30) {
|
||||
|
||||
//broadcast a global event
|
||||
eventsService.emit("app.authenticated", result);
|
||||
return result;
|
||||
},
|
||||
//we need to check when the last time the timeout was set from the server, if
|
||||
// it has been more than 30 seconds then we'll manually go and retrieve it from the
|
||||
// server - this helps to keep our local countdown in check with the true timeout.
|
||||
if (lastServerTimeoutSet != null) {
|
||||
var now = new Date();
|
||||
var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000;
|
||||
|
||||
/** Logs the user out
|
||||
*/
|
||||
logout: function () {
|
||||
if (seconds > 30) {
|
||||
|
||||
return authResource.performLogout()
|
||||
.then(function (data) {
|
||||
userAuthExpired();
|
||||
//done!
|
||||
return null;
|
||||
});
|
||||
},
|
||||
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
|
||||
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
|
||||
lastServerTimeoutSet = null;
|
||||
|
||||
/** Refreshes the current user data with the data stored for the user on the server and returns it */
|
||||
refreshCurrentUser: function() {
|
||||
var deferred = $q.defer();
|
||||
//now go get it from the server
|
||||
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
authResource.getRemainingTimeoutSeconds().then(function (result) {
|
||||
setUserTimeoutInternal(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
}
|
||||
else {
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
|
||||
|
||||
setCurrentUser(data);
|
||||
//we are either timed out or very close to timing out so we need to show the login dialog.
|
||||
if (Umbraco.Sys.ServerVariables.umbracoSettings.keepUserLoggedIn !== true) {
|
||||
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
try {
|
||||
//NOTE: We are calling this again so that the server can create a log that the timeout has expired, we
|
||||
// don't actually care about this result.
|
||||
authResource.getRemainingTimeoutSeconds();
|
||||
}
|
||||
finally {
|
||||
userAuthExpired();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
//we've got less than 30 seconds remaining so let's check the server
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
}, function () {
|
||||
//it failed, so they are not logged in
|
||||
deferred.reject();
|
||||
});
|
||||
if (lastServerTimeoutSet != null) {
|
||||
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
|
||||
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
|
||||
lastServerTimeoutSet = null;
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
//now go get it from the server
|
||||
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
|
||||
angularHelper.safeApply($rootScope, function () {
|
||||
authResource.getRemainingTimeoutSeconds().then(function (result) {
|
||||
setUserTimeoutInternal(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the current user object in a promise */
|
||||
getCurrentUser: function (args) {
|
||||
var deferred = $q.defer();
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
|
||||
if (!currentUser) {
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 5000, //every 5 seconds
|
||||
false); //false = do NOT execute a digest for every iteration
|
||||
}
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
|
||||
/** Called to update the current user's timeout */
|
||||
function setUserTimeoutInternal(newTimeout) {
|
||||
|
||||
if (args && args.broadcastEvent) {
|
||||
//broadcast a global event, will inform listening controllers to load in the user specific data
|
||||
|
||||
var asNumber = parseFloat(newTimeout);
|
||||
if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
|
||||
currentUser.remainingAuthSeconds = newTimeout;
|
||||
lastServerTimeoutSet = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
/** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */
|
||||
function userAuthExpired(isLogout) {
|
||||
//store the last user id and clear the user
|
||||
if (currentUser && currentUser.id !== undefined) {
|
||||
lastUserId = currentUser.id;
|
||||
}
|
||||
|
||||
if (currentUser) {
|
||||
currentUser.remainingAuthSeconds = 0;
|
||||
}
|
||||
|
||||
lastServerTimeoutSet = null;
|
||||
currentUser = null;
|
||||
|
||||
//broadcast a global event that the user is no longer logged in
|
||||
eventsService.emit("app.notAuthenticated");
|
||||
|
||||
openLoginDialog(isLogout === undefined ? true : !isLogout);
|
||||
}
|
||||
|
||||
// Register a handler for when an item is added to the retry queue
|
||||
securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) {
|
||||
if (securityRetryQueue.hasMore()) {
|
||||
userAuthExpired();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
/** Internal method to display the login dialog */
|
||||
_showLoginDialog: function () {
|
||||
openLoginDialog();
|
||||
},
|
||||
/** Returns a promise, sends a request to the server to check if the current cookie is authorized */
|
||||
isAuthenticated: function () {
|
||||
//if we've got a current user then just return true
|
||||
if (currentUser) {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve(true);
|
||||
return deferred.promise;
|
||||
}
|
||||
return authResource.isAuthenticated();
|
||||
},
|
||||
|
||||
/** Returns a promise, sends a request to the server to validate the credentials */
|
||||
authenticate: function (login, password) {
|
||||
|
||||
return authResource.performLogin(login, password)
|
||||
.then(this.setAuthenticationSuccessful);
|
||||
},
|
||||
setAuthenticationSuccessful: function (data) {
|
||||
|
||||
//when it's successful, return the user data
|
||||
setCurrentUser(data);
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" };
|
||||
|
||||
//broadcast a global event
|
||||
eventsService.emit("app.authenticated", result);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
setCurrentUser(data);
|
||||
/** Logs the user out
|
||||
*/
|
||||
logout: function () {
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
}, function () {
|
||||
//it failed, so they are not logged in
|
||||
deferred.reject();
|
||||
});
|
||||
return authResource.performLogout()
|
||||
.then(function (data) {
|
||||
userAuthExpired();
|
||||
//done!
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
else {
|
||||
deferred.resolve(currentUser);
|
||||
}
|
||||
/** Refreshes the current user data with the data stored for the user on the server and returns it */
|
||||
refreshCurrentUser: function () {
|
||||
var deferred = $q.defer();
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
|
||||
/** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */
|
||||
setUserTimeout: function (newTimeout) {
|
||||
setUserTimeoutInternal(newTimeout);
|
||||
}
|
||||
};
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
|
||||
|
||||
});
|
||||
setCurrentUser(data);
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
}, function () {
|
||||
//it failed, so they are not logged in
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/** Returns the current user object in a promise */
|
||||
getCurrentUser: function (args) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (!currentUser) {
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
|
||||
|
||||
if (args && args.broadcastEvent) {
|
||||
//broadcast a global event, will inform listening controllers to load in the user specific data
|
||||
eventsService.emit("app.authenticated", result);
|
||||
}
|
||||
|
||||
setCurrentUser(data);
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
}, function () {
|
||||
//it failed, so they are not logged in
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
deferred.resolve(currentUser);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/** Loads the Moment.js Locale for the current user. */
|
||||
loadMomentLocaleForCurrentUser: function () {
|
||||
var deferred = $q.defer();
|
||||
|
||||
|
||||
function loadLocales(currentUser, supportedLocales) {
|
||||
var locale = currentUser.locale.toLowerCase();
|
||||
if (locale !== 'en-us') {
|
||||
var localeUrls = [];
|
||||
if (supportedLocales.indexOf(locale + '.js') > -1) {
|
||||
localeUrls.push('lib/moment/' + locale + '.js');
|
||||
}
|
||||
if (locale.indexOf('-') > -1) {
|
||||
var majorLocale = locale.split('-')[0] + '.js';
|
||||
if (supportedLocales.indexOf(majorLocale) > -1) {
|
||||
localeUrls.push('lib/moment/' + majorLocale);
|
||||
}
|
||||
}
|
||||
assetsService.load(localeUrls).then(function () {
|
||||
deferred.resolve(localeUrls);
|
||||
});
|
||||
} else {
|
||||
deferred.resolve(['']);
|
||||
}
|
||||
}
|
||||
|
||||
var promises = {
|
||||
currentUser: this.getCurrentUser(),
|
||||
supportedLocales: javascriptLibraryService.getSupportedLocalesForMoment()
|
||||
}
|
||||
|
||||
$q.all(promises).then((values) => {
|
||||
loadLocales(values.currentUser, values.supportedLocales);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
},
|
||||
|
||||
/** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */
|
||||
setUserTimeout: function (newTimeout) {
|
||||
setUserTimeoutInternal(newTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -18,23 +18,26 @@ app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navi
|
||||
eventsService.on("app.authenticated", function(evt, data) {
|
||||
|
||||
assetsService._loadInitAssets().then(function() {
|
||||
|
||||
//Register all of the tours on the server
|
||||
tourService.registerAllTours().then(function () {
|
||||
appReady(data);
|
||||
|
||||
// Auto start intro tour
|
||||
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
|
||||
// start intro tour if it hasn't been completed or disabled
|
||||
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
|
||||
tourService.startTour(introTour);
|
||||
}
|
||||
|
||||
// Loads the user's locale settings for Moment.
|
||||
userService.loadMomentLocaleForCurrentUser().then(function() {
|
||||
|
||||
//Register all of the tours on the server
|
||||
tourService.registerAllTours().then(function () {
|
||||
appReady(data);
|
||||
|
||||
// Auto start intro tour
|
||||
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
|
||||
// start intro tour if it hasn't been completed or disabled
|
||||
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
|
||||
tourService.startTour(introTour);
|
||||
}
|
||||
});
|
||||
|
||||
}, function(){
|
||||
appReady(data);
|
||||
});
|
||||
|
||||
}, function(){
|
||||
appReady(data);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -223,14 +223,16 @@ input.umb-group-builder__group-title-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-meta .umb-locked-field__input {
|
||||
font-size: 12px !important;
|
||||
word-break: break-word;
|
||||
margin-bottom: 2px !important;
|
||||
.umb-group-builder__property-meta-alias {
|
||||
font-size: 10px;
|
||||
color: @gray-3;
|
||||
word-break: break-word;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.umb-group-builder__property-meta-label textarea {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0;
|
||||
color: @gray-1;
|
||||
|
||||
+23
-51
@@ -7,7 +7,7 @@
|
||||
* The controller for the content type editor property dialog
|
||||
*/
|
||||
|
||||
(function () {
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function EditorPickerOverlay($scope, dataTypeResource, dataTypeHelper, contentTypeResource, localizationService) {
|
||||
@@ -24,7 +24,6 @@
|
||||
vm.typesAndEditors = [];
|
||||
vm.userConfigured = [];
|
||||
vm.loading = false;
|
||||
vm.property = $scope.model.property;
|
||||
vm.tabs = [{
|
||||
active: true,
|
||||
id: 1,
|
||||
@@ -56,7 +55,7 @@
|
||||
|
||||
vm.loading = true;
|
||||
|
||||
dataTypeResource.getGroupedPropertyEditors().then(function (data) {
|
||||
dataTypeResource.getGroupedPropertyEditors().then(function(data) {
|
||||
vm.tabs[0].typesAndEditors = data;
|
||||
vm.typesAndEditors = data;
|
||||
vm.tabsLoaded = vm.tabsLoaded + 1;
|
||||
@@ -69,7 +68,7 @@
|
||||
|
||||
vm.loading = true;
|
||||
|
||||
dataTypeResource.getGroupedDataTypes().then(function (data) {
|
||||
dataTypeResource.getGroupedDataTypes().then(function(data) {
|
||||
vm.tabs[1].userConfigured = data;
|
||||
vm.userConfigured = data;
|
||||
vm.tabsLoaded = vm.tabsLoaded + 1;
|
||||
@@ -117,7 +116,7 @@
|
||||
|
||||
var parentId = -1;
|
||||
|
||||
dataTypeResource.getScaffold(parentId).then(function (dataType) {
|
||||
dataTypeResource.getScaffold(parentId).then(function(dataType) {
|
||||
|
||||
// set alias
|
||||
dataType.selectedEditor = editor.alias;
|
||||
@@ -125,11 +124,7 @@
|
||||
// set name
|
||||
var nameArray = [];
|
||||
|
||||
// content type name (if you add properties before filling out a name for the content type, we need a temp name)
|
||||
var contentTypeName = "Unnamed Content Type";
|
||||
|
||||
if ($scope.model.contentTypeName) {
|
||||
contentTypeName = $scope.model.contentTypeName;
|
||||
nameArray.push($scope.model.contentTypeName);
|
||||
}
|
||||
|
||||
@@ -143,48 +138,13 @@
|
||||
|
||||
// make name
|
||||
dataType.name = nameArray.join(" - ");
|
||||
dataType.containerName = contentTypeName;
|
||||
|
||||
// get pre values
|
||||
dataTypeResource.getPreValues(dataType.selectedEditor).then(function (preValues) {
|
||||
// if there's any configuration settings then open the dialog, else just save the editor immediately
|
||||
if (preValues.length > 0) {
|
||||
dataType.preValues = preValues;
|
||||
openEditorSettingsOverlay(dataType, true);
|
||||
} else {
|
||||
saveDataTypeWithContainerCheck(dataType.containerName, dataType, preValues, true);
|
||||
}
|
||||
});
|
||||
dataTypeResource.getPreValues(dataType.selectedEditor).then(function(preValues) {
|
||||
|
||||
});
|
||||
dataType.preValues = preValues;
|
||||
|
||||
}
|
||||
|
||||
function saveDataTypeWithContainerCheck(containerName, dataType, preValues, isNew) {
|
||||
// check if a container for the doctype already exist
|
||||
dataTypeResource.containerExist(containerName).then(function (container) {
|
||||
if (container == "true") {
|
||||
dataTypeResource.getContainer(containerName).then(
|
||||
function (container) {
|
||||
dataType.parentId = container.Id;
|
||||
saveDataType(dataType, preValues, isNew);
|
||||
});
|
||||
} else {
|
||||
dataTypeResource.createContainer(-1, containerName).then(
|
||||
function (container) {
|
||||
dataType.parentId = container.Entity.Id;
|
||||
saveDataType(dataType, preValues, isNew);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveDataType(dataType, preValues, isNew) {
|
||||
dataTypeResource.save(dataType, preValues, isNew).then(function (newDataType) {
|
||||
|
||||
contentTypeResource.getPropertyTypeScaffold(newDataType.id).then(function (propertyType) {
|
||||
|
||||
submitOverlay(newDataType, propertyType, true);
|
||||
openEditorSettingsOverlay(dataType, true);
|
||||
|
||||
});
|
||||
|
||||
@@ -194,8 +154,8 @@
|
||||
|
||||
function pickDataType(selectedDataType) {
|
||||
|
||||
dataTypeResource.getById(selectedDataType.id).then(function (dataType) {
|
||||
contentTypeResource.getPropertyTypeScaffold(dataType.id).then(function (propertyType) {
|
||||
dataTypeResource.getById(selectedDataType.id).then(function(dataType) {
|
||||
contentTypeResource.getPropertyTypeScaffold(dataType.id).then(function(propertyType) {
|
||||
submitOverlay(dataType, propertyType, false);
|
||||
});
|
||||
});
|
||||
@@ -208,9 +168,21 @@
|
||||
dataType: dataType,
|
||||
view: "views/common/overlays/contenttypeeditor/editorsettings/editorsettings.html",
|
||||
show: true,
|
||||
submit: function (model) {
|
||||
submit: function(model) {
|
||||
var preValues = dataTypeHelper.createPreValueProps(model.dataType.preValues);
|
||||
saveDataTypeWithContainerCheck(dataType.containerName, dataType, preValues, isNew);
|
||||
|
||||
dataTypeResource.save(model.dataType, preValues, isNew).then(function(newDataType) {
|
||||
|
||||
contentTypeResource.getPropertyTypeScaffold(newDataType.id).then(function(propertyType) {
|
||||
|
||||
submitOverlay(newDataType, propertyType, true);
|
||||
|
||||
vm.editorSettingsOverlay.show = false;
|
||||
vm.editorSettingsOverlay = null;
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+12
-1
@@ -4,7 +4,18 @@
|
||||
<i class="icon-alert red"></i>
|
||||
<strong class="red"><localize key="contentTypeEditor_allDocumentTypes"></localize></strong> using this editor will get updated with the new settings.
|
||||
</div>
|
||||
|
||||
|
||||
<div class="control-group umb-control-group">
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label" for="dataTypeName">
|
||||
<localize key="name"></localize>
|
||||
</label>
|
||||
<div class="controls">
|
||||
<input type="text" ng-model="model.dataType.name" class="umb-editor" umb-auto-focus focus-on-filled="true" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5><localize key="contentTypeEditor_configuration"></localize></h5>
|
||||
|
||||
<umb-property property="preValue" ng-repeat="preValue in model.dataType.preValues">
|
||||
|
||||
+1
-5
@@ -110,10 +110,7 @@
|
||||
vm.editorSettingsOverlay.title = "Editor settings";
|
||||
vm.editorSettingsOverlay.view = "views/common/overlays/contenttypeeditor/editorsettings/editorsettings.html";
|
||||
vm.editorSettingsOverlay.dataType = dataType;
|
||||
|
||||
if (dataType.preValues.length > 0) {
|
||||
vm.editorSettingsOverlay.show = true;
|
||||
}
|
||||
vm.editorSettingsOverlay.show = true;
|
||||
|
||||
vm.editorSettingsOverlay.submit = function (model) {
|
||||
|
||||
@@ -153,7 +150,6 @@
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function matchValidationType() {
|
||||
|
||||
|
||||
+21
@@ -1,5 +1,26 @@
|
||||
<div class="content-type-editor-dialog edit-property-settings" ng-controller="Umbraco.Overlay.PropertySettingsOverlay as vm">
|
||||
|
||||
<div class="umb-control-group" ng-if="!model.property.locked">
|
||||
<div class="control-group">
|
||||
<textarea class="editor-label"
|
||||
data-element="property-name"
|
||||
name="propertyLabel"
|
||||
ng-model="model.property.label"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_entername"
|
||||
umb-auto-focus
|
||||
focus-on-filled="true"
|
||||
umb-auto-resize
|
||||
required
|
||||
overlay-submit-on-enter>
|
||||
</textarea>
|
||||
<div class="umb-validation-label" val-msg-for="propertyLabel" val-toggle-msg="required">Required label</div>
|
||||
</div>
|
||||
<div class="control-group -no-margin">
|
||||
<umb-generate-alias enable-lock="true" alias-from="model.property.label" alias="model.property.alias"></umb-generate-alias>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group control-group">
|
||||
<textarea
|
||||
data-element="property-description"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
</li>
|
||||
<li data-element="section-{{section.alias}}" ng-repeat="section in sections | limitTo: maxSections" ng-class="{current: section.alias == currentSection}">
|
||||
<a href="#/{{section.alias}}"
|
||||
hotkey="ctrl+alt+{{$index+1}}"
|
||||
ng-dblclick="sectionDblClick(section)"
|
||||
ng-click="sectionClick($event, section)"
|
||||
prevent-default>
|
||||
@@ -42,8 +41,6 @@
|
||||
<ul class="sections sections-tray">
|
||||
<li ng-repeat="section in sections | limitTo: overflowingSections" ng-class="{current: section.alias == currentSection}">
|
||||
<a href="#/{{section.alias}}"
|
||||
hotkey="ctrl+alt+{{$index+1+maxSections}}"
|
||||
hotkey-when-hidden="true"
|
||||
ng-dblclick="sectionDblClick(section)"
|
||||
ng-click="sectionClick($event, section)"
|
||||
prevent-default>
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
ng-model="name"
|
||||
ng-class="{'name-is-empty': $parent.name===null || $parent.name===''}"
|
||||
umb-auto-focus
|
||||
hotkey="ctrl+,"
|
||||
val-server-field="Name"
|
||||
required />
|
||||
</ng-form>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class="alert alert-block alert-{{notification.type}} umb-notifications__notification animated -half-second fadeIn"
|
||||
ng-class="{'-no-border -extra-padding': notification.type === 'form'}">
|
||||
|
||||
<a class='close -align-right' hotkey="esc" ng-click="removeNotification($index)" prevent-default href>×</a>
|
||||
<a class='close -align-right' ng-click="removeNotification($index)" prevent-default href>×</a>
|
||||
|
||||
<div ng-if="notification.view">
|
||||
<div ng-include="notification.view"></div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<div data-element="overlay" class="umb-overlay umb-overlay-{{position}}" hotkey="esc" on-outside-click="closeOverLay()">
|
||||
|
||||
<div data-element="overlay" class="umb-overlay umb-overlay-{{position}}" on-outside-click="closeOverLay()">
|
||||
<ng-form class="umb-overlay__form" name="overlayForm" novalidate val-form-manager>
|
||||
|
||||
<div data-element="overlay-header" class="umb-overlay-header">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<ul class="nav nav-tabs umb-nav-tabs">
|
||||
<li data-element="tab-{{tab.alias}}" ng-class="{'tab-error': tabHasError}" ng-repeat="tab in model" val-tab>
|
||||
<a data-toggle="tab" hotkey="ctrl+{{$index+1}}" href="#tab{{tab.id}}{{idSuffix}}">{{ tab.label }}</a>
|
||||
<a data-toggle="tab" href="#tab{{tab.id}}{{idSuffix}}">{{ tab.label }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -4,22 +4,24 @@
|
||||
|
||||
<umb-editor-sub-header-content-right>
|
||||
|
||||
<umb-button alias="compositions"
|
||||
ng-if="compositions !== false"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label-key="contentTypeEditor_compositions"
|
||||
icon="icon-merge"
|
||||
action="openCompositionsDialog()">
|
||||
<umb-button
|
||||
alias="compositions"
|
||||
ng-if="compositions !== false"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label-key="contentTypeEditor_compositions"
|
||||
icon="icon-merge"
|
||||
action="openCompositionsDialog()">
|
||||
</umb-button>
|
||||
|
||||
<umb-button alias="reorder"
|
||||
ng-if="sorting !== false"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label-key="{{sortingButtonKey}}"
|
||||
icon="icon-navigation"
|
||||
action="toggleSortingMode();">
|
||||
<umb-button
|
||||
alias="reorder"
|
||||
ng-if="sorting !== false"
|
||||
type="button"
|
||||
button-style="link"
|
||||
label-key="{{sortingButtonKey}}"
|
||||
icon="icon-navigation"
|
||||
action="toggleSortingMode();">
|
||||
</umb-button>
|
||||
|
||||
</umb-editor-sub-header-content-right>
|
||||
@@ -38,7 +40,7 @@
|
||||
<a href="" class="umb-group-builder__group -placeholder" hotkey="alt+shift+t" ng-click="addGroup(tab)" ng-if="tab.tabState=='init' && !sortingMode" data-element="group-add">
|
||||
|
||||
<div class="umb-group-builder__group-title-wrapper -placeholder">
|
||||
<div class="umb-group-builder__group-title -placeholder"></div>
|
||||
<div class="umb-group-builder__group-title -placeholder"></div>
|
||||
</div>
|
||||
|
||||
<localize ng-if="model.groups.length === 1" key="contentTypeEditor_addNewTab"></localize>
|
||||
@@ -51,10 +53,11 @@
|
||||
|
||||
<div class="umb-group-builder__group-remove" ng-if="!sortingMode && tab.properties.length <= 1">
|
||||
<i class="icon-trash" ng-click="togglePrompt(tab)"></i>
|
||||
<umb-confirm-action ng-if="tab.deletePrompt"
|
||||
direction="left"
|
||||
on-confirm="removeGroup($index)"
|
||||
on-cancel="hidePrompt(tab)">
|
||||
<umb-confirm-action
|
||||
ng-if="tab.deletePrompt"
|
||||
direction="left"
|
||||
on-confirm="removeGroup($index)"
|
||||
on-cancel="hidePrompt(tab)">
|
||||
</umb-confirm-action>
|
||||
</div>
|
||||
|
||||
@@ -111,15 +114,15 @@
|
||||
|
||||
<!-- Init property / Property placeholder / add new property -->
|
||||
<a href=""
|
||||
data-element="property-add"
|
||||
class="umb-group-builder__property -placeholder"
|
||||
ng-if="property.propertyState=='init' && !sortingMode"
|
||||
ng-class="{'-placeholder': property.propertyState=='init'}"
|
||||
hotkey="alt+shift+p"
|
||||
hotkey-when="{{tab.tabState === 'active' && property.propertyState=='init'}}"
|
||||
ng-click="addProperty(property, tab)"
|
||||
on-focus="activateGroup(tab)"
|
||||
focus-when="{{property.focus}}">
|
||||
data-element="property-add"
|
||||
class="umb-group-builder__property -placeholder"
|
||||
ng-if="property.propertyState=='init' && !sortingMode"
|
||||
ng-class="{'-placeholder': property.propertyState=='init'}"
|
||||
hotkey="alt+shift+p"
|
||||
hotkey-when="{{tab.tabState === 'active' && property.propertyState=='init'}}"
|
||||
ng-click="addProperty(property, tab)"
|
||||
on-focus="activateGroup(tab)"
|
||||
focus-when="{{property.focus}}">
|
||||
|
||||
<div class="umb-group-builder__property-meta">
|
||||
<div class="umb-group-builder__placeholder-box -input-small"></div>
|
||||
@@ -148,25 +151,24 @@
|
||||
<div class="control-group -no-margin" ng-if="!sortingMode">
|
||||
|
||||
<div class="umb-group-builder__property-meta-alias" ng-if="property.inherited || property.locked">{{ property.alias }}</div>
|
||||
<umb-locked-field ng-if="!property.inherited && !property.locked"
|
||||
locked="locked"
|
||||
ng-model="property.alias"
|
||||
placeholder-text="'Alias...'"
|
||||
server-validation-field="{{'Groups[' + $parent.$parent.$parent.$parent.$index + '].Properties[' + $index + '].Alias'}}">
|
||||
<umb-locked-field
|
||||
ng-if="!property.inherited && !property.locked"
|
||||
locked="locked"
|
||||
ng-model="property.alias"
|
||||
placeholder-text="'Alias...'"
|
||||
server-validation-field="{{'Groups[' + $parent.$parent.$parent.$parent.$index + '].Properties[' + $index + '].Alias'}}">
|
||||
</umb-locked-field>
|
||||
|
||||
<div class="umb-group-builder__property-meta-label">
|
||||
<textarea localize="placeholder"
|
||||
placeholder="@placeholders_label"
|
||||
ng-model="property.label"
|
||||
ng-disabled="property.inherited || property.locked"
|
||||
name="groupName"
|
||||
ng-change="updateAlias(property)"
|
||||
umb-auto-resize
|
||||
select-on-focus
|
||||
umb-select-when="{{property.tempAlias}}"
|
||||
required
|
||||
val-server-field="{{'Groups[' + $parent.$parent.$parent.$parent.$index + '].Properties[' + $index + '].Label'}}">
|
||||
<textarea
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_label"
|
||||
ng-model="property.label"
|
||||
ng-disabled="property.inherited || property.locked"
|
||||
name="groupName"
|
||||
umb-auto-resize
|
||||
required
|
||||
val-server-field="{{'Groups[' + $parent.$parent.$parent.$parent.$index + '].Properties[' + $index + '].Label'}}">
|
||||
</textarea>
|
||||
|
||||
<div class="umb-validation-label" val-msg-for="groupName" val-toggle-msg="valServerField"></div>
|
||||
@@ -174,11 +176,12 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-group-builder__property-meta-description">
|
||||
<textarea localize="placeholder"
|
||||
placeholder="@placeholders_enterDescription"
|
||||
ng-model="property.description"
|
||||
ng-disabled="property.inherited || property.locked"
|
||||
umb-auto-resize>
|
||||
<textarea
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_enterDescription"
|
||||
ng-model="property.description"
|
||||
ng-disabled="property.inherited || property.locked"
|
||||
umb-auto-resize>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
@@ -241,9 +244,10 @@
|
||||
</div>
|
||||
|
||||
<ng-form name="propertyEditorPreviewForm" umb-disable-form-validation>
|
||||
<umb-property-editor ng-if="property.view !== undefined"
|
||||
model="property"
|
||||
preview="true">
|
||||
<umb-property-editor
|
||||
ng-if="property.view !== undefined"
|
||||
model="property"
|
||||
preview="true">
|
||||
</umb-property-editor>
|
||||
</ng-form>
|
||||
|
||||
@@ -262,10 +266,11 @@
|
||||
<!-- delete property -->
|
||||
<div ng-if="!property.locked" class="umb-group-builder__property-action">
|
||||
<i class="icon-trash" ng-click="togglePrompt(property)"></i>
|
||||
<umb-confirm-action ng-if="property.deletePrompt"
|
||||
direction="left"
|
||||
on-confirm="deleteProperty(tab, $index)"
|
||||
on-cancel="hidePrompt(property)">
|
||||
<umb-confirm-action
|
||||
ng-if="property.deletePrompt"
|
||||
direction="left"
|
||||
on-confirm="deleteProperty(tab, $index)"
|
||||
on-cancel="hidePrompt(property)">
|
||||
</umb-confirm-action>
|
||||
</div>
|
||||
|
||||
@@ -287,25 +292,20 @@
|
||||
|
||||
</ul>
|
||||
|
||||
<umb-overlay data-element="overlay-compositions"
|
||||
ng-if="compositionsDialogModel.show"
|
||||
model="compositionsDialogModel"
|
||||
position="right"
|
||||
view="compositionsDialogModel.view">
|
||||
<umb-overlay
|
||||
data-element="overlay-compositions"
|
||||
ng-if="compositionsDialogModel.show"
|
||||
model="compositionsDialogModel"
|
||||
position="right"
|
||||
view="compositionsDialogModel.view">
|
||||
</umb-overlay>
|
||||
|
||||
<umb-overlay data-element="overlay-property-settings"
|
||||
ng-if="propertySettingsDialogModel.show"
|
||||
model="propertySettingsDialogModel"
|
||||
position="right"
|
||||
view="propertySettingsDialogModel.view">
|
||||
</umb-overlay>
|
||||
|
||||
<umb-overlay data-element="overlay-editor-picker"
|
||||
ng-if="editorPickerOverlay.show"
|
||||
model="editorPickerOverlay"
|
||||
position="right"
|
||||
view="editorPickerOverlay.view">
|
||||
<umb-overlay
|
||||
data-element="overlay-property-settings"
|
||||
ng-if="propertySettingsDialogModel.show"
|
||||
model="propertySettingsDialogModel"
|
||||
position="right"
|
||||
view="propertySettingsDialogModel.view">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ function ColorPickerController($scope) {
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = $scope.model.value.hasOwnProperty("value")
|
||||
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
|
||||
+21
-20
@@ -130,6 +130,9 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag
|
||||
// in the description of this controller, it states that this value isn't actually used for persistence,
|
||||
// but we need to set it so that the editor and the server can detect that it's been changed, and it is used for validation.
|
||||
$scope.model.value = { selectedFiles: newVal.trimEnd(",") };
|
||||
|
||||
//need to explicity setDirty here as file upload field can't track dirty & we can't use the fileCount (hidden field/model)
|
||||
$scope.propertyForm.$setDirty();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -154,26 +157,24 @@ angular.module("umbraco")
|
||||
.controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController)
|
||||
.run(function(mediaHelper, umbRequestHelper, assetsService){
|
||||
if (mediaHelper && mediaHelper.registerFileResolver) {
|
||||
assetsService.load(["lib/moment/moment-with-locales.js"]).then(
|
||||
function () {
|
||||
//NOTE: The 'entity' can be either a normal media entity or an "entity" returned from the entityResource
|
||||
// they contain different data structures so if we need to query against it we need to be aware of this.
|
||||
mediaHelper.registerFileResolver("Umbraco.UploadField", function(property, entity, thumbnail){
|
||||
if (thumbnail) {
|
||||
if (mediaHelper.detectIfImageByExtension(property.value)) {
|
||||
//get default big thumbnail from image processor
|
||||
var thumbnailUrl = property.value + "?rnd=" + moment(entity.updateDate).format("YYYYMMDDHHmmss") + "&width=500&animationprocessmode=first";
|
||||
return thumbnailUrl;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return property.value;
|
||||
}
|
||||
});
|
||||
|
||||
//NOTE: The 'entity' can be either a normal media entity or an "entity" returned from the entityResource
|
||||
// they contain different data structures so if we need to query against it we need to be aware of this.
|
||||
mediaHelper.registerFileResolver("Umbraco.UploadField", function(property, entity, thumbnail){
|
||||
if (thumbnail) {
|
||||
if (mediaHelper.detectIfImageByExtension(property.value)) {
|
||||
//get default big thumbnail from image processor
|
||||
var thumbnailUrl = property.value + "?rnd=" + moment(entity.updateDate).format("YYYYMMDDHHmmss") + "&width=500&animationprocessmode=first";
|
||||
return thumbnailUrl;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
else {
|
||||
return property.value;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory"/>
|
||||
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory" no-dirty-check />
|
||||
|
||||
</div>
|
||||
|
||||
@@ -99,4 +99,4 @@ module.exports = function (config) {
|
||||
'karma-phantomjs-launcher'
|
||||
]
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1023,9 +1023,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7910</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7920</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7910</IISUrl>
|
||||
<IISUrl>http://localhost:7920</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
url += "&mode=crop";
|
||||
}
|
||||
}
|
||||
|
||||
var altText = Model.value.altText ?? Model.value.caption ?? string.Empty;
|
||||
|
||||
<img src="@url" alt="@Model.value.caption">
|
||||
<img src="@url" alt="@altText">
|
||||
|
||||
if (Model.value.caption != null)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<key alias="update">Bijwerken</key>
|
||||
</area>
|
||||
<area alias="assignDomain">
|
||||
<key alias="permissionDenied">Permission denied.</key>
|
||||
<key alias="permissionDenied">Toegang geweigerd.</key>
|
||||
<key alias="addNew">Nieuw domein toevoegen</key>
|
||||
<key alias="remove">verwijderen</key>
|
||||
<key alias="invalidNode">Ongeldige node.</key>
|
||||
@@ -1379,10 +1379,10 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
|
||||
<key alias="httpsCheckEnableHttpsDescription">Zet in de appSettings van de web.config de umbracoSSL instelling op 'true'.</key>
|
||||
<key alias="httpsCheckEnableHttpsSuccess">De appSetting 'umbracoUseSSL' is nu ingesteld op 'true', cookies zullen als 'secure' worden aangemerkt.</key>
|
||||
|
||||
<key alias="rectifyButton">Fix</key>
|
||||
<key alias="cannotRectifyShouldNotEqual">Cannot fix a check with a value comparison type of 'ShouldNotEqual'.</key>
|
||||
<key alias="cannotRectifyShouldEqualWithValue">Cannot fix a check with a value comparison type of 'ShouldEqual' with a provided value.</key>
|
||||
<key alias="valueToRectifyNotProvided">Value to fix check not provided.</key>
|
||||
<key alias="rectifyButton">Herstellen</key>
|
||||
<key alias="cannotRectifyShouldNotEqual">Kan een controle met vergelijkingstype 'ShouldNotEqual' niet herstellen.</key>
|
||||
<key alias="cannotRectifyShouldEqualWithValue">Kan een controle met vergelijkingstype 'ShouldNotEqual' en gedefinieerde waarde niet herstellen.</key>
|
||||
<key alias="valueToRectifyNotProvided">Waarde om te herstellen niet gedefinieerd.</key>
|
||||
|
||||
<key alias="compilationDebugCheckSuccessMessage">Debug compiliate mode staat uit.</key>
|
||||
<key alias="compilationDebugCheckErrorMessage">Debug compiliate mode staat momenteel aan. Wij raden aan deze instelling uit te zetten voor livegang.</key>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
public class BackOfficeAssetsController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
[HttpGet]
|
||||
public IEnumerable<string> GetSupportedMomentLocales()
|
||||
{
|
||||
var momentLocaleFolder = "moment";
|
||||
var fileSystem = FileSystemProviderManager.Current.JavaScriptLibraryFileSystem;
|
||||
var cultures = fileSystem.GetFiles(momentLocaleFolder, "*.js").ToList();
|
||||
for (var i = 0; i < cultures.Count(); i++)
|
||||
{
|
||||
cultures[i] = cultures[i]
|
||||
.Substring(cultures[i].IndexOf(momentLocaleFolder) + momentLocaleFolder.Length + 1);
|
||||
}
|
||||
return cultures;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -268,6 +268,10 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
"helpApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<HelpController>(
|
||||
controller => controller.GetContextHelpForPage("","",""))
|
||||
},
|
||||
{
|
||||
"backOfficeAssetsApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<BackOfficeAssetsController>(
|
||||
controller => controller.GetSupportedMomentLocales())
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -188,23 +188,6 @@ namespace Umbraco.Web.Editors
|
||||
: Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public bool ContainerExist(string name)
|
||||
{
|
||||
var result = Services.DataTypeService.GetContainers(name, 1);
|
||||
|
||||
return result.Any();
|
||||
}
|
||||
|
||||
public HttpResponseMessage GetContainer(string name)
|
||||
{
|
||||
var result = Services.DataTypeService.GetContainers(name, 1);
|
||||
|
||||
return result.Any()
|
||||
? Request.CreateResponse(HttpStatusCode.OK, result.First())
|
||||
: Request.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data type
|
||||
/// </summary>
|
||||
|
||||
@@ -63,6 +63,10 @@ namespace Umbraco.Web.Scheduling
|
||||
{
|
||||
using (var wc = new HttpClient())
|
||||
{
|
||||
if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri))
|
||||
{
|
||||
wc.BaseAddress = baseUri;
|
||||
}
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
|
||||
//TODO: pass custom the authorization header, currently these aren't really secured!
|
||||
@@ -122,4 +126,4 @@ namespace Umbraco.Web.Scheduling
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
'lib/angular/1.1.5/angular.min.js',
|
||||
'lib/underscore/underscore-min.js',
|
||||
|
||||
'lib/moment/moment-with-locales.js',
|
||||
'lib/moment/moment.min.js',
|
||||
|
||||
'lib/jquery-ui/jquery-ui.min.js',
|
||||
'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js',
|
||||
|
||||
@@ -316,6 +316,7 @@
|
||||
<Compile Include="Cache\TemplateCacheRefresher.cs" />
|
||||
<Compile Include="Cache\UnpublishedPageCacheRefresher.cs" />
|
||||
<Compile Include="Cache\UserCacheRefresher.cs" />
|
||||
<Compile Include="Editors\BackOfficeAssetsController .cs" />
|
||||
<Compile Include="Features\DisabledFeatures.cs" />
|
||||
<Compile Include="Editors\BackOfficeNotificationsController.cs" />
|
||||
<Compile Include="Editors\BackOfficeServerVariables.cs" />
|
||||
|
||||
Reference in New Issue
Block a user