Merge branch 'temp8' of https://github.com/umbraco/Umbraco-CMS into temp8
This commit is contained in:
@@ -40,7 +40,6 @@
|
||||
|
||||
<!-- 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" />
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/// </summary>
|
||||
/// <remarks>Every strongly-typed property set class should inherit from <c>PublishedElementModel</c>
|
||||
/// (or inherit from a class that inherits from... etc.) so they are picked by the factory.</remarks>
|
||||
public class PublishedElementModel : PublishedElementWrapped
|
||||
public abstract class PublishedElementModel : PublishedElementWrapped
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
|
||||
@@ -41,10 +41,17 @@
|
||||
//We fetch all ancestors of the node to generate the footer breadcrumb navigation
|
||||
if (!$scope.page.isNew) {
|
||||
if (content.parentId && content.parentId !== -1) {
|
||||
entityResource.getAncestors(content.id, "document")
|
||||
entityResource.getAncestors(content.id, "document", $scope.culture)
|
||||
.then(function (anc) {
|
||||
$scope.ancestors = anc;
|
||||
});
|
||||
$scope.$watch('culture',
|
||||
function(value, oldValue) {
|
||||
entityResource.getAncestors(content.id, "document", value)
|
||||
.then(function (anc) {
|
||||
$scope.ancestors = anc;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
(function () {
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:multi
|
||||
* @restrict A
|
||||
* @description Used on input fields when you want to validate multiple fields at once.
|
||||
**/
|
||||
function multi($parse, $rootScope) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
link: function (scope, elem, attrs, ngModelCtrl) {
|
||||
var validate = $parse(attrs.multi)(scope);
|
||||
ngModelCtrl.$viewChangeListeners.push(function () {
|
||||
// ngModelCtrl.$setValidity('multi', validate());
|
||||
$rootScope.$broadcast('multi:valueChanged');
|
||||
});
|
||||
|
||||
var deregisterListener = scope.$on('multi:valueChanged', function (event) {
|
||||
ngModelCtrl.$setValidity('multi', validate());
|
||||
});
|
||||
scope.$on('$destroy', deregisterListener); // optional, only required for $rootScope.$on
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.directives.validation').directive('multi', ['$parse', '$rootScope', multi]);
|
||||
})();
|
||||
@@ -242,6 +242,44 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
{ id: id, culture: culture })),
|
||||
'Failed to publish content with id ' + id);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.contentResource#getCultureAndDomains
|
||||
* @methodOf umbraco.resources.contentResource
|
||||
*
|
||||
* @description
|
||||
* Gets the culture and hostnames for a content item with the given Id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* contentResource.getCultureAndDomains(1234)
|
||||
* .then(function(data) {
|
||||
* alert(data.Domains, data.Language);
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Int} id the ID of the node to get the culture and domains for.
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getCultureAndDomains: function (id) {
|
||||
if (!id) {
|
||||
throw "id cannot be null";
|
||||
}
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetCultureAndDomains", { id: id })),
|
||||
'Failed to retreive culture and hostnames for ' + id);
|
||||
},
|
||||
saveLanguageAndDomains: function (model) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"PostSaveLanguageAndDomains"),
|
||||
model));
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.contentResource#emptyRecycleBin
|
||||
@@ -334,26 +372,26 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*/
|
||||
getById: function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetById",
|
||||
{ id: id })),
|
||||
'Failed to retrieve data for content id ' + id)
|
||||
.then(function(result) {
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetById",
|
||||
{ id: id })),
|
||||
'Failed to retrieve data for content id ' + id)
|
||||
.then(function (result) {
|
||||
return $q.when(umbDataFormatter.formatContentGetData(result));
|
||||
});
|
||||
},
|
||||
|
||||
getBlueprintById: function (id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetBlueprintById",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve data for content id ' + id)
|
||||
.then(function(result) {
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetBlueprintById",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve data for content id ' + id)
|
||||
.then(function (result) {
|
||||
return $q.when(umbDataFormatter.formatContentGetData(result));
|
||||
});
|
||||
},
|
||||
@@ -410,15 +448,15 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
});
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetByIds",
|
||||
idQuery)),
|
||||
'Failed to retrieve data for content with multiple ids')
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetByIds",
|
||||
idQuery)),
|
||||
'Failed to retrieve data for content with multiple ids')
|
||||
.then(function (result) {
|
||||
//each item needs to be re-formatted
|
||||
_.each(result, function(r) {
|
||||
_.each(result, function (r) {
|
||||
umbDataFormatter.formatContentGetData(r)
|
||||
});
|
||||
return $q.when(result);
|
||||
@@ -461,13 +499,13 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
getScaffold: function (parentId, alias) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetEmpty",
|
||||
[{ contentTypeAlias: alias }, { parentId: parentId }])),
|
||||
'Failed to retrieve data for empty content item type ' + alias)
|
||||
.then(function(result) {
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetEmpty",
|
||||
[{ contentTypeAlias: alias }, { parentId: parentId }])),
|
||||
'Failed to retrieve data for empty content item type ' + alias)
|
||||
.then(function (result) {
|
||||
return $q.when(umbDataFormatter.formatContentGetData(result));
|
||||
});
|
||||
},
|
||||
@@ -475,13 +513,13 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
getBlueprintScaffold: function (parentId, blueprintId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetEmpty",
|
||||
[{ blueprintId: blueprintId }, { parentId: parentId }])),
|
||||
'Failed to retrieve blueprint for id ' + blueprintId)
|
||||
.then(function(result) {
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"GetEmpty",
|
||||
[{ blueprintId: blueprintId }, { parentId: parentId }])),
|
||||
'Failed to retrieve blueprint for id ' + blueprintId)
|
||||
.then(function (result) {
|
||||
return $q.when(umbDataFormatter.formatContentGetData(result));
|
||||
});
|
||||
},
|
||||
|
||||
@@ -288,17 +288,19 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
* Gets ancestor entities for a given item
|
||||
*
|
||||
*
|
||||
* @param {string} type Object type name
|
||||
* @param {string} type Object type name
|
||||
* @param {string} culture Culture
|
||||
* @returns {Promise} resourcePromise object containing the entity.
|
||||
*
|
||||
*/
|
||||
getAncestors: function (id, type) {
|
||||
getAncestors: function (id, type, culture) {
|
||||
if (culture === undefined) culture = "";
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetAncestors",
|
||||
[{id: id}, {type: type}])),
|
||||
[{ id: id }, { type: type }, { culture: culture }])),
|
||||
'Failed to retrieve ancestor data for id ' + id);
|
||||
},
|
||||
|
||||
|
||||
@@ -1,24 +1,70 @@
|
||||
<div ng-controller="Umbraco.Editors.Content.AssignDomainController as vm">
|
||||
<div class="umb-dialog-body">
|
||||
<umb-pane>
|
||||
<p>UI magic to be done...</p>
|
||||
</umb-pane>
|
||||
</div>
|
||||
<div ng-controller="Umbraco.Editors.Content.AssignDomainController as vm" ng-cloak>
|
||||
<div class="umb-dialog-body">
|
||||
<umb-pane>
|
||||
<h5 class="umb-pane-title"><localize key="assignDomain_setLanguage">Culture</localize></h5>
|
||||
<label for="assignDomain_language" class="control-label"><localize key="general_language"></localize></label>
|
||||
<select class="umb-property-editor umb-dropdown" name="language" id="assignDomain_language" ng-model="vm.language" ng-options="lang.name for lang in vm.languages">
|
||||
<option value="">{{vm.inherit}}</option>
|
||||
</select>
|
||||
</umb-pane>
|
||||
<umb-pane>
|
||||
<h5 class="umb-pane-title"><localize key="assignDomain_setDomains">Domains</localize></h5>
|
||||
<form name="vm.domainForm" novalidate="" ng-submit="vm.save()" class="control-group umb-control-group">
|
||||
<small class="help-inline">
|
||||
<localize key="assignDomain_domainHelp"></localize>
|
||||
</small>
|
||||
<div class="umb-el-wrap hidelabel">
|
||||
<table class="table domains" ng-if="vm.domains.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><localize key="assignDomain_domain"></localize></th>
|
||||
<th><localize key="assignDomain_language"></localize></th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="domain in vm.domains">
|
||||
<td>
|
||||
<input type="text" ng-model="domain.Name" multi="vm.validateDomain" ng-pattern="vm.domainPattern" name="domain_name_{{$index}}" />
|
||||
<span ng-if="vm.domainForm.$submitted" ng-messages="vm.domainForm['domain_name_' + $index].$error">
|
||||
<span class="help-inline" ng-message="multi"><localize key="assignDomain_duplicateDomain"></localize></span>
|
||||
<span class="help-inline" ng-message="pattern"><localize key="assignDomain_invalidDomain"></localize></span>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<select name="domain_language_{{$index}}" class="language" ng-model="domain.Lang" ng-options="lang.name for lang in vm.languages"></select>
|
||||
</td>
|
||||
<td>
|
||||
<umb-button icon="icon-trash"
|
||||
action="vm.removeDomain($index)"
|
||||
type="button"
|
||||
button-style="danger">
|
||||
</umb-button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<umb-button label-key="assignDomain_addNew"
|
||||
action="vm.addDomain()"
|
||||
type="button">
|
||||
</umb-button>
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
|
||||
<div class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
<umb-button label-key="general_cancel"
|
||||
action="vm.closeDialog()"
|
||||
type="button"
|
||||
button-style="link">
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
label-key="general_cancel"
|
||||
action="vm.closeDialog()"
|
||||
type="button"
|
||||
button-style="link">
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
label-key="buttons_save"
|
||||
type="button"
|
||||
button-style="success">
|
||||
</umb-button>
|
||||
<umb-button label-key="buttons_save"
|
||||
type="submit"
|
||||
button-style="success">
|
||||
</umb-button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</umb-pane>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,126 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function AssignDomainController($scope) {
|
||||
|
||||
function AssignDomainController($scope, localizationService, languageResource, contentResource) {
|
||||
var vm = this;
|
||||
vm.closeDialog = closeDialog;
|
||||
|
||||
function closeDialog() {
|
||||
$scope.nav.hideDialog();
|
||||
vm.addDomain = addDomain;
|
||||
vm.removeDomain = removeDomain;
|
||||
vm.save = save;
|
||||
vm.validateDomain = validateDomain;
|
||||
vm.languages = [];
|
||||
vm.domains = [];
|
||||
vm.language = null;
|
||||
vm.domainPattern = /^(http[s]?:\/\/)?([-\w]+(\.[-\w]+)*)(:\d+)?(\/[-\w]*|-)?$/gi; //TODO: This regex is not working as it should.
|
||||
function activate() {
|
||||
languageResource.getAll().then(function (langs) {
|
||||
vm.languages = langs;
|
||||
var defLang = langs.filter(function (l) {
|
||||
return l.isDefault;
|
||||
});
|
||||
|
||||
if (defLang.length > 0) {
|
||||
vm.defaultLanguage = defLang[0];
|
||||
}
|
||||
else {
|
||||
vm.defaultLanguage = langs[0];
|
||||
}
|
||||
getCultureAndDomains();
|
||||
});
|
||||
|
||||
localizationService.localize("assignDomain_inherit").then(function (value) {
|
||||
vm.inherit = value;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function getCultureAndDomains () {
|
||||
contentResource.getCultureAndDomains($scope.currentNode.id)
|
||||
.then(function (data) {
|
||||
if (data.Language !== "undefined") {
|
||||
var lang = vm.languages.filter(function (l) {
|
||||
return matchLanguageById(l, data.Language.Id);
|
||||
|
||||
});
|
||||
if (lang.length > 0) {
|
||||
vm.language = lang[0];
|
||||
}
|
||||
}
|
||||
vm.domains = data.Domains.map(function (d) {
|
||||
var matchedLangs = vm.languages.filter(function (l) {
|
||||
return matchLanguageById(l, d.Language);
|
||||
|
||||
});
|
||||
return {
|
||||
Name: d.Name,
|
||||
Lang: matchedLangs.length > 0 ? matchedLangs[0] : vm.defaultLanguage
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function matchLanguageById(language, id) {
|
||||
return language.Id === id;
|
||||
}
|
||||
|
||||
function closeDialog() {
|
||||
$scope.nav.hideDialog();
|
||||
}
|
||||
|
||||
function addDomain() {
|
||||
vm.domains.push({
|
||||
Name: '',
|
||||
Lang: vm.defaultLanguage
|
||||
});
|
||||
}
|
||||
|
||||
function removeDomain(index) {
|
||||
vm.domains.splice(index, 1);
|
||||
}
|
||||
|
||||
function validateDomain() {
|
||||
var valid = true, duplicateTest = {};
|
||||
if (vm.domains.length > 1) {
|
||||
|
||||
vm.domains.map(function (d, index) {
|
||||
if (d.Name in duplicateTest) {
|
||||
valid = false;
|
||||
}
|
||||
else {
|
||||
duplicateTest[d.Name] = index;
|
||||
}
|
||||
});
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
||||
if (vm.domainForm.$valid) {
|
||||
var data = {
|
||||
NodeId: $scope.currentNode.id,
|
||||
Domains: vm.domains.map(function (d) {
|
||||
return {
|
||||
Name: d.Name,
|
||||
Lang: d.Lang.id
|
||||
};
|
||||
}),
|
||||
Language: vm.language != null ? vm.language.id : 0
|
||||
};
|
||||
console.log(data);
|
||||
contentResource.saveLanguageAndDomains(data).then(function () {
|
||||
closeDialog();
|
||||
}, function (e) {
|
||||
console.log(e); //TODO: not sure how best to handle this case
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log('not valid');
|
||||
}
|
||||
}
|
||||
|
||||
activate();
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Content.AssignDomainController", AssignDomainController);
|
||||
})();
|
||||
|
||||
})();
|
||||
@@ -279,7 +279,8 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
|
||||
_.each($scope.model.config.contentTypes, function (contentType) {
|
||||
contentResource.getScaffold(-20, contentType.ncAlias).then(function (scaffold) {
|
||||
// remove all tabs except the specified tab
|
||||
var tab = _.find(scaffold.tabs, function (tab) {
|
||||
var tabs = scaffold.variants[0].tabs;
|
||||
var tab = _.find(tabs, function (tab) {
|
||||
return tab.id != 0 && (tab.alias.toLowerCase() == contentType.ncTabAlias.toLowerCase() || contentType.ncTabAlias == "");
|
||||
});
|
||||
scaffold.tabs = [];
|
||||
|
||||
@@ -333,7 +333,6 @@
|
||||
<Content Include="Umbraco\Developer\RelationTypes\RelationTypesWebService.asmx" />
|
||||
<Content Include="Umbraco\Developer\RelationTypes\TreeMenu\ActionDeleteRelationType.js" />
|
||||
<Content Include="Umbraco\Developer\RelationTypes\TreeMenu\ActionNewRelationType.js" />
|
||||
<Content Include="Umbraco\Dialogs\AssignDomain2.aspx" />
|
||||
<Content Include="Umbraco\Dialogs\ChangeDocType.aspx">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Content>
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<%@ Page Language="c#" MasterPageFile="../masterpages/umbracoDialog.Master" Codebehind="AssignDomain2.aspx.cs" AutoEventWireup="True" Inherits="umbraco.dialogs.AssignDomain2" %>
|
||||
<%@ Import Namespace="Umbraco.Web" %>
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="Umbraco.Web._Legacy.Controls" Assembly="Umbraco.Web" %>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="head" runat="server">
|
||||
<umb:JsInclude runat="server" FilePath="Dialogs/AssignDomain2.js" PathNameAlias="UmbracoClient" />
|
||||
<umb:JsInclude runat="server" FilePath="PunyCode/punycode.min.js" PathNameAlias="UmbracoClient" />
|
||||
<umb:JsInclude runat="server" FilePath="/Umbraco/lib/jquery-validate/jquery.validate.min.js" PathNameAlias="UmbracoClient" />
|
||||
<umb:CssInclude runat="server" FilePath="Dialogs/AssignDomain2.css" PathNameAlias="UmbracoClient" />
|
||||
<script type="text/javascript">
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
var dialog = new Umbraco.Dialogs.AssignDomain2({
|
||||
nodeId: <%=GetNodeId()%>,
|
||||
restServiceLocation: '<%=GetRestServicePath() %>',
|
||||
invalidDomain: '<%=Services.TextService.Localize("assignDomain/invalidDomain") %>',
|
||||
duplicateDomain: '<%=Services.TextService.Localize("assignDomain/duplicateDomain") %>',
|
||||
<asp:Literal runat="server" ID="data" />
|
||||
});
|
||||
dialog.init();
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="body" runat="server">
|
||||
|
||||
<div class="umb-dialog-body">
|
||||
|
||||
<cc1:Feedback ID="feedback" runat="server" />
|
||||
<div id="komask"></div>
|
||||
|
||||
<cc1:Pane runat="server" ID="pane_language" cssClass="hide">
|
||||
<cc1:PropertyPanel runat="server" ID="prop_language">
|
||||
<select class="umb-property-editor umb-dropdown" name="language" data-bind="options: languages, optionsText: 'Code', optionsValue: 'Id', value: language, optionsCaption: '<%=Services.TextService.Localize("assignDomain/inherit") %> '"></select>
|
||||
<!-- <small class="help-inline"><%=Services.TextService.Localize("assignDomain/setLanguageHelp") %></small>-->
|
||||
</cc1:PropertyPanel>
|
||||
</cc1:Pane>
|
||||
|
||||
|
||||
<cc1:Pane runat="server" ID="pane_domains">
|
||||
<small class="help-inline"><%=Services.TextService.Localize("assignDomain/domainHelp") %></small>
|
||||
<cc1:PropertyPanel runat="server">
|
||||
<table class="table domains" data-bind="visible: domains().length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%=Services.TextService.Localize("assignDomain/domain") %></th>
|
||||
<th><%=Services.TextService.Localize("assignDomain/language") %></th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="foreach: domains">
|
||||
<tr>
|
||||
<td valign="top"><input class="domain duplicate" data-bind="value: Name, uniqueName: true" /><input type="hidden" value="" data-bind="uniqueName: true"/></td>
|
||||
<td valign="top"><select class="language" data-bind="options: $parent.languages, optionsText: 'Code', optionsValue: 'Id', value: Lang, uniqueName: true"></select></td>
|
||||
<td valign="top"><a href="#" class="btn btn-danger" data-bind="click: $parent.removeDomain"><i class="icon icon-trash"></i></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
<cc1:PropertyPanel runat="server">
|
||||
<button class="btn" data-bind="click: addDomain"><%=Services.TextService.Localize("assignDomain/addNew") %></button>
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
|
||||
</cc1:Pane>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div runat="server" ID="p_buttons" class="umb-dialog-footer btn-toolbar umb-btn-toolbar">
|
||||
<a href="#" class="btn btn-link" onclick="UmbClientMgr.closeModalWindow()"><%=Services.TextService.Localize("general/cancel")%></a>
|
||||
<button class="btn btn-primary" id="btnSave"><%=Services.TextService.Localize("buttons/save") %></button>
|
||||
</div>
|
||||
|
||||
</asp:Content>
|
||||
@@ -56,6 +56,8 @@ namespace Umbraco.Web.Editors
|
||||
private readonly PropertyEditorCollection _propertyEditors;
|
||||
private readonly Lazy<IDictionary<string, ILanguage>> _allLangs;
|
||||
|
||||
public object Domains { get; private set; }
|
||||
|
||||
public ContentController(IPublishedSnapshotService publishedSnapshotService, PropertyEditorCollection propertyEditors)
|
||||
{
|
||||
if (publishedSnapshotService == null) throw new ArgumentNullException(nameof(publishedSnapshotService));
|
||||
@@ -1146,6 +1148,18 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
public ContentDomainsAndCulture GetCultureAndDomains(int id)
|
||||
{
|
||||
var nodeDomains = Services.DomainService.GetAssignedDomains(id, true).ToArray();
|
||||
var wildcard = nodeDomains.FirstOrDefault(d => d.IsWildcard);
|
||||
var domains = nodeDomains.Where(d => !d.IsWildcard).Select(d => new DomainDisplay(d.DomainName, d.LanguageId.GetValueOrDefault(0)));
|
||||
return new ContentDomainsAndCulture
|
||||
{
|
||||
Domains = domains,
|
||||
Language = wildcard == null || !wildcard.LanguageId.HasValue ? "undefined" : wildcard.LanguageId.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public DomainSave PostSaveLanguageAndDomains(DomainSave model)
|
||||
{
|
||||
|
||||
@@ -10,15 +10,18 @@ using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using Umbraco.Core.Models;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using System.Web.Http.Controllers;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Xml;
|
||||
using Umbraco.Web.Models.Mapping;
|
||||
using Umbraco.Web.Search;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -211,7 +214,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
var ancestors = GetAncestors(id, type);
|
||||
var ancestors = GetResultForAncestors(id, type);
|
||||
|
||||
//if content, skip the first node for replicating NiceUrl defaults
|
||||
if(type == UmbracoEntityTypes.Document) {
|
||||
@@ -582,9 +585,10 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<EntityBasic> GetAncestors(int id, UmbracoEntityTypes type)
|
||||
[HttpQueryStringFilter("queryStrings")]
|
||||
public IEnumerable<EntityBasic> GetAncestors(int id, UmbracoEntityTypes type, FormDataCollection queryStrings)
|
||||
{
|
||||
return GetResultForAncestors(id, type);
|
||||
return GetResultForAncestors(id, type, queryStrings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -626,7 +630,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<EntityBasic> GetResultForAncestors(int id, UmbracoEntityTypes entityType)
|
||||
private IEnumerable<EntityBasic> GetResultForAncestors(int id, UmbracoEntityTypes entityType, FormDataCollection queryStrings = null)
|
||||
{
|
||||
var objectType = ConvertToObjectType(entityType);
|
||||
if (objectType.HasValue)
|
||||
@@ -666,12 +670,14 @@ namespace Umbraco.Web.Editors
|
||||
ids = lids.ToArray();
|
||||
}
|
||||
|
||||
var culture = queryStrings?.GetValue<string>("culture");
|
||||
|
||||
return ids.Length == 0
|
||||
? Enumerable.Empty<EntityBasic>()
|
||||
: Services.EntityService.GetAll(objectType.Value, ids)
|
||||
.WhereNotNull()
|
||||
.OrderBy(x => x.Level)
|
||||
.Select(Mapper.Map<EntityBasic>);
|
||||
.Select(x => Mapper.Map<EntityBasic>(x, opts => { opts.SetCulture(culture);}));
|
||||
}
|
||||
//now we need to convert the unknown ones
|
||||
switch (entityType)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
public class ContentDomainsAndCulture
|
||||
{
|
||||
public IEnumerable<DomainDisplay> Domains { get; set; }
|
||||
|
||||
public string Language { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
var contentTypeUdiResolver = new ContentTypeUdiResolver();
|
||||
|
||||
CreateMap<EntitySlim, EntityBasic>()
|
||||
.ForMember(dest => dest.Name, opt => opt.ResolveUsing<NameResolver>())
|
||||
.ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(ObjectTypes.GetUdiType(src.NodeObjectType), src.Key)))
|
||||
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => GetContentTypeIcon(src)))
|
||||
.ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed))
|
||||
@@ -179,5 +180,33 @@ namespace Umbraco.Web.Models.Mapping
|
||||
CreateMap<IEnumerable<SearchResult>, IEnumerable<SearchResultItem>>()
|
||||
.ConvertUsing(results => results.Select(Mapper.Map<SearchResultItem>).ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the name for a content item/content variant
|
||||
/// </summary>
|
||||
private class NameResolver : IValueResolver<EntitySlim, EntityBasic, string>
|
||||
{
|
||||
public string Resolve(EntitySlim source, EntityBasic destination, string destMember, ResolutionContext context)
|
||||
{
|
||||
if (!(source is DocumentEntitySlim doc))
|
||||
return source.Name;
|
||||
|
||||
// invariant = only 1 name
|
||||
if (!doc.Variations.VariesByCulture()) return source.Name;
|
||||
|
||||
// variant = depends on culture
|
||||
var culture = context.Options.GetCulture();
|
||||
|
||||
// if there's no culture here, the issue is somewhere else (UI, whatever) - throw!
|
||||
if (culture == null)
|
||||
//throw new InvalidOperationException("Missing culture in mapping options.");
|
||||
// fixme we should throw, but this is used in various places that won't set a culture yet
|
||||
return source.Name;
|
||||
|
||||
// if we don't have a name for a culture, it means the culture is not available, and
|
||||
// hey we should probably not be mapping it, but it's too late, return a fallback name
|
||||
return doc.CultureNames.TryGetValue(culture, out var name) && !name.IsNullOrWhiteSpace() ? name : $"(({source.Name}))";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +272,9 @@ namespace Umbraco.Web.PropertyEditors
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(object rawValue, string valueType, object dataTypeConfiguration)
|
||||
{
|
||||
if (rawValue == null)
|
||||
yield break;
|
||||
|
||||
var value = JsonConvert.DeserializeObject<List<object>>(rawValue.ToString());
|
||||
if (value == null)
|
||||
yield break;
|
||||
|
||||
@@ -55,19 +55,18 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
using (_proflog.DebugDuration<PublishedPropertyType>($"ConvertPropertyToNestedContent ({propertyType.DataType.Id})"))
|
||||
{
|
||||
var value = (string)inter;
|
||||
if (string.IsNullOrWhiteSpace(value)) return null;
|
||||
|
||||
var objects = JsonConvert.DeserializeObject<List<JObject>>(value);
|
||||
if (objects.Count == 0)
|
||||
return Enumerable.Empty<IPublishedElement>();
|
||||
|
||||
var configuration = propertyType.DataType.ConfigurationAs<NestedContentConfiguration>();
|
||||
var contentTypes = configuration.ContentTypes;
|
||||
var elements = contentTypes.Length > 1
|
||||
? new List<IPublishedElement>()
|
||||
: PublishedModelFactory.CreateModelList(contentTypes[0].Alias);
|
||||
|
||||
var value = (string)inter;
|
||||
if (string.IsNullOrWhiteSpace(value)) return elements;
|
||||
|
||||
var objects = JsonConvert.DeserializeObject<List<JObject>>(value);
|
||||
if (objects.Count == 0) return elements;
|
||||
|
||||
foreach (var sourceObject in objects)
|
||||
{
|
||||
var element = ConvertToElement(sourceObject, referenceCacheLevel, preview);
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<Compile Include="Editors\BackOfficeServerVariables.cs" />
|
||||
<Compile Include="ImageProcessorLogger.cs" />
|
||||
<Compile Include="Macros\MacroTagParser.cs" />
|
||||
<Compile Include="Models\ContentEditing\ContentDomainsAndCulture.cs" />
|
||||
<Compile Include="Models\ContentEditing\ContentSavedState.cs" />
|
||||
<Compile Include="Models\Mapping\ContentSavedStateResolver.cs" />
|
||||
<Compile Include="OwinExtensions.cs" />
|
||||
|
||||
Reference in New Issue
Block a user