Merge branch 'temp8' into temp8-3640

This commit is contained in:
Stephan
2019-02-01 10:47:34 +01:00
17 changed files with 303 additions and 214 deletions

View File

@@ -160,5 +160,8 @@ namespace Umbraco.Core.Models
return result;
}
/// <inheritdoc />
IContentType IContentType.DeepCloneWithResetIdentities(string newAlias) => (IContentType)DeepCloneWithResetIdentities(newAlias);
}
}

View File

@@ -504,9 +504,9 @@ namespace Umbraco.Core.Models
}
}
public IContentType DeepCloneWithResetIdentities(string alias)
public ContentTypeBase DeepCloneWithResetIdentities(string alias)
{
var clone = (ContentType)DeepClone();
var clone = (ContentTypeBase)DeepClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
foreach (var propertyGroup in clone.PropertyGroups)

View File

@@ -44,29 +44,7 @@ namespace Umbraco.Core.Models
/// <inheritdoc />
public override bool IsPublishing => IsPublishingConst;
/// <summary>
/// Creates a deep clone of the current entity with its identity/alias and it's property identities reset
/// </summary>
/// <returns></returns>
public new IMediaType DeepCloneWithResetIdentities(string alias)
{
var clone = (MediaType)DeepClone();
clone.Alias = alias;
clone.Key = Guid.Empty;
foreach (var propertyGroup in clone.PropertyGroups)
{
propertyGroup.ResetIdentity();
propertyGroup.ResetDirtyProperties(false);
}
foreach (var propertyType in clone.PropertyTypes)
{
propertyType.ResetIdentity();
propertyType.ResetDirtyProperties(false);
}
clone.ResetIdentity();
clone.ResetDirtyProperties(false);
return clone;
}
/// <inheritdoc />
IMediaType IMediaType.DeepCloneWithResetIdentities(string newAlias) => (IMediaType)DeepCloneWithResetIdentities(newAlias);
}
}

View File

@@ -594,7 +594,7 @@ namespace Umbraco.Core.Services.Implement
//var originalb = (ContentTypeCompositionBase)original;
// but we *know* it has to be a ContentTypeCompositionBase anyways
var originalb = (ContentTypeCompositionBase) (object) original;
var clone = (TItem) originalb.DeepCloneWithResetIdentities(alias);
var clone = (TItem) (object) originalb.DeepCloneWithResetIdentities(alias);
clone.Name = name;
@@ -645,7 +645,7 @@ namespace Umbraco.Core.Services.Implement
//var copyingb = (ContentTypeCompositionBase) copying;
// but we *know* it has to be a ContentTypeCompositionBase anyways
var copyingb = (ContentTypeCompositionBase) (object)copying;
copy = (TItem) copyingb.DeepCloneWithResetIdentities(alias);
copy = (TItem) (object) copyingb.DeepCloneWithResetIdentities(alias);
copy.Name = copy.Name + " (copy)"; // might not be unique

View File

@@ -23,10 +23,10 @@ namespace Umbraco.Examine
/// <summary>
/// By default these are the member fields we index
/// </summary>
public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email" };
public static readonly string[] DefaultMemberIndexFields = { "id", "nodeName", "updateDate", "loginName", "email", UmbracoExamineIndex.NodeKeyFieldName };
private static readonly IEnumerable<string> ValidCategories = new[] { IndexTypes.Member };
protected override IEnumerable<string> ValidIndexCategories => ValidCategories;
}
}

View File

@@ -407,46 +407,6 @@ namespace Umbraco.Tests.Services
Assert.IsNull(doc2.GetValue("title", "en-US"));
}
[Test]
public void Deleting_Media_Type_With_Hierarchy_Of_Media_Items_Moves_Orphaned_Media_To_Recycle_Bin()
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
//delete the first content type, all other content of different content types should be in the recycle bin
ServiceContext.MediaTypeService.Delete(contentTypes[0]);
var found = ServiceContext.MediaService.GetByIds(ids);
Assert.AreEqual(4, found.Count());
foreach (var content in found)
{
Assert.IsTrue(content.Trashed);
}
}
[Test]
public void Deleting_Content_Type_With_Hierarchy_Of_Content_Items_Moves_Orphaned_Content_To_Recycle_Bin()
{
@@ -491,60 +451,6 @@ namespace Umbraco.Tests.Services
}
}
[Test]
public void Deleting_Media_Types_With_Hierarchy_Of_Media_Items_Doesnt_Raise_Trashed_Event_For_Deleted_Items()
{
MediaService.Trashed += MediaServiceOnTrashed;
try
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
foreach (var contentType in contentTypes.Reverse())
{
ServiceContext.MediaTypeService.Delete(contentType);
}
}
finally
{
MediaService.Trashed -= MediaServiceOnTrashed;
}
}
private void MediaServiceOnTrashed(IMediaService sender, MoveEventArgs<IMedia> e)
{
foreach (var item in e.MoveInfoCollection)
{
//if this item doesn't exist then Fail!
var exists = ServiceContext.MediaService.GetById(item.Entity.Id);
if (exists == null)
Assert.Fail("The item doesn't exist");
}
}
[Test]
public void Deleting_Content_Types_With_Hierarchy_Of_Content_Items_Doesnt_Raise_Trashed_Event_For_Deleted_Items_1()
{
@@ -1109,12 +1015,13 @@ namespace Umbraco.Tests.Services
var metaContentType = MockedContentTypes.CreateMetaContentType();
service.Save(metaContentType);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", metaContentType);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", metaContentType) as IContentType;
service.Save(simpleContentType);
var categoryId = simpleContentType.Id;
// Act
var sut = simpleContentType.DeepCloneWithResetIdentities("newcategory");
Assert.IsNotNull(sut);
service.Save(sut);
// Assert
@@ -1146,11 +1053,12 @@ namespace Umbraco.Tests.Services
var parentContentType2 = MockedContentTypes.CreateSimpleContentType("parent2", "Parent2", null, true);
service.Save(parentContentType2);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1, true);
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", parentContentType1, true) as IContentType;
service.Save(simpleContentType);
// Act
var clone = simpleContentType.DeepCloneWithResetIdentities("newcategory");
Assert.IsNotNull(clone);
clone.RemoveContentType("parent1");
clone.AddContentType(parentContentType2);
clone.ParentId = parentContentType2.Id;
@@ -2114,22 +2022,6 @@ namespace Umbraco.Tests.Services
Assert.IsNull(contentType2.Description);
}
[Test]
public void Empty_Description_Is_Always_Null_After_Saving_Media_Type()
{
var service = ServiceContext.MediaTypeService;
var mediaType = MockedContentTypes.CreateSimpleMediaType("mediaType", "Media Type");
mediaType.Description = null;
service.Save(mediaType);
var mediaType2 = MockedContentTypes.CreateSimpleMediaType("mediaType2", "Media Type 2");
mediaType2.Description = string.Empty;
service.Save(mediaType2);
Assert.IsNull(mediaType.Description);
Assert.IsNull(mediaType2.Description);
}
[Test]
public void Variations_In_Compositions()
{

View File

@@ -0,0 +1,195 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using NUnit.Framework;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Services
{
[TestFixture]
[Apartment(ApartmentState.STA)]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest, PublishedRepositoryEvents = true)]
public class MediaTypeServiceTests : TestWithSomeContentBase
{
[Test]
public void Empty_Description_Is_Always_Null_After_Saving_Media_Type()
{
var mediaType = MockedContentTypes.CreateSimpleMediaType("mediaType", "Media Type");
mediaType.Description = null;
ServiceContext.MediaTypeService.Save(mediaType);
var mediaType2 = MockedContentTypes.CreateSimpleMediaType("mediaType2", "Media Type 2");
mediaType2.Description = string.Empty;
ServiceContext.MediaTypeService.Save(mediaType2);
Assert.IsNull(mediaType.Description);
Assert.IsNull(mediaType2.Description);
}
[Test]
public void Deleting_Media_Type_With_Hierarchy_Of_Media_Items_Moves_Orphaned_Media_To_Recycle_Bin()
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
//delete the first content type, all other content of different content types should be in the recycle bin
ServiceContext.MediaTypeService.Delete(contentTypes[0]);
var found = ServiceContext.MediaService.GetByIds(ids);
Assert.AreEqual(4, found.Count());
foreach (var content in found)
{
Assert.IsTrue(content.Trashed);
}
}
[Test]
public void Deleting_Media_Types_With_Hierarchy_Of_Media_Items_Doesnt_Raise_Trashed_Event_For_Deleted_Items()
{
MediaService.Trashed += MediaServiceOnTrashed;
try
{
IMediaType contentType1 = MockedContentTypes.CreateSimpleMediaType("test1", "Test1");
ServiceContext.MediaTypeService.Save(contentType1);
IMediaType contentType2 = MockedContentTypes.CreateSimpleMediaType("test2", "Test2");
ServiceContext.MediaTypeService.Save(contentType2);
IMediaType contentType3 = MockedContentTypes.CreateSimpleMediaType("test3", "Test3");
ServiceContext.MediaTypeService.Save(contentType3);
var contentTypes = new[] { contentType1, contentType2, contentType3 };
var parentId = -1;
var ids = new List<int>();
for (int i = 0; i < 2; i++)
{
for (var index = 0; index < contentTypes.Length; index++)
{
var contentType = contentTypes[index];
var contentItem = MockedMedia.CreateSimpleMedia(contentType, "MyName_" + index + "_" + i, parentId);
ServiceContext.MediaService.Save(contentItem);
parentId = contentItem.Id;
ids.Add(contentItem.Id);
}
}
foreach (var contentType in contentTypes.Reverse())
{
ServiceContext.MediaTypeService.Delete(contentType);
}
}
finally
{
MediaService.Trashed -= MediaServiceOnTrashed;
}
}
private void MediaServiceOnTrashed(IMediaService sender, MoveEventArgs<IMedia> e)
{
foreach (var item in e.MoveInfoCollection)
{
//if this item doesn't exist then Fail!
var exists = ServiceContext.MediaService.GetById(item.Entity.Id);
if (exists == null)
Assert.Fail("The item doesn't exist");
}
}
[Test]
public void Can_Copy_MediaType_By_Performing_Clone()
{
// Arrange
var mediaType = MockedContentTypes.CreateImageMediaType("Image2") as IMediaType;
ServiceContext.MediaTypeService.Save(mediaType);
// Act
var sut = mediaType.DeepCloneWithResetIdentities("Image2_2");
Assert.IsNotNull(sut);
ServiceContext.MediaTypeService.Save(sut);
// Assert
Assert.That(sut.HasIdentity, Is.True);
Assert.AreEqual(mediaType.ParentId, sut.ParentId);
Assert.AreEqual(mediaType.Level, sut.Level);
Assert.AreEqual(mediaType.PropertyTypes.Count(), sut.PropertyTypes.Count());
Assert.AreNotEqual(mediaType.Id, sut.Id);
Assert.AreNotEqual(mediaType.Key, sut.Key);
Assert.AreNotEqual(mediaType.Path, sut.Path);
Assert.AreNotEqual(mediaType.SortOrder, sut.SortOrder);
Assert.AreNotEqual(mediaType.PropertyTypes.First(x => x.Alias.Equals("umbracoFile")).Id, sut.PropertyTypes.First(x => x.Alias.Equals("umbracoFile")).Id);
Assert.AreNotEqual(mediaType.PropertyGroups.First(x => x.Name.Equals("Media")).Id, sut.PropertyGroups.First(x => x.Name.Equals("Media")).Id);
}
[Test]
public void Can_Copy_MediaType_To_New_Parent_By_Performing_Clone()
{
// Arrange
var parentMediaType1 = MockedContentTypes.CreateSimpleMediaType("parent1", "Parent1");
ServiceContext.MediaTypeService.Save(parentMediaType1);
var parentMediaType2 = MockedContentTypes.CreateSimpleMediaType("parent2", "Parent2", null, true);
ServiceContext.MediaTypeService.Save(parentMediaType2);
var mediaType = MockedContentTypes.CreateImageMediaType("Image2") as IMediaType;
ServiceContext.MediaTypeService.Save(mediaType);
// Act
var clone = mediaType.DeepCloneWithResetIdentities("newcategory");
Assert.IsNotNull(clone);
clone.RemoveContentType("parent1");
clone.AddContentType(parentMediaType2);
clone.ParentId = parentMediaType2.Id;
ServiceContext.MediaTypeService.Save(clone);
// Assert
Assert.That(clone.HasIdentity, Is.True);
var clonedMediaType = ServiceContext.MediaTypeService.Get(clone.Id);
var originalMediaType = ServiceContext.MediaTypeService.Get(mediaType.Id);
Assert.That(clonedMediaType.CompositionAliases().Any(x => x.Equals("parent2")), Is.True);
Assert.That(clonedMediaType.CompositionAliases().Any(x => x.Equals("parent1")), Is.False);
Assert.AreEqual(clonedMediaType.Path, "-1," + parentMediaType2.Id + "," + clonedMediaType.Id);
Assert.AreEqual(clonedMediaType.PropertyTypes.Count(), originalMediaType.PropertyTypes.Count());
Assert.AreNotEqual(clonedMediaType.ParentId, originalMediaType.ParentId);
Assert.AreEqual(clonedMediaType.ParentId, parentMediaType2.Id);
Assert.AreNotEqual(clonedMediaType.Id, originalMediaType.Id);
Assert.AreNotEqual(clonedMediaType.Key, originalMediaType.Key);
Assert.AreNotEqual(clonedMediaType.Path, originalMediaType.Path);
Assert.AreNotEqual(clonedMediaType.PropertyTypes.First(x => x.Alias.StartsWith("umbracoFile")).Id, originalMediaType.PropertyTypes.First(x => x.Alias.StartsWith("umbracoFile")).Id);
Assert.AreNotEqual(clonedMediaType.PropertyGroups.First(x => x.Name.StartsWith("Media")).Id, originalMediaType.PropertyGroups.First(x => x.Name.StartsWith("Media")).Id);
}
}
}

View File

@@ -149,6 +149,7 @@
<Compile Include="Services\EntityXmlSerializerTests.cs" />
<Compile Include="Packaging\CreatedPackagesRepositoryTests.cs" />
<Compile Include="Services\MemberGroupServiceTests.cs" />
<Compile Include="Services\MediaTypeServiceTests.cs" />
<Compile Include="Testing\Objects\TestDataSource.cs" />
<Compile Include="Published\PublishedSnapshotTestObjects.cs" />
<Compile Include="Published\ModelTypeTests.cs" />

View File

@@ -24,10 +24,10 @@
function umbTagsEditorController($rootScope, assetsService, umbRequestHelper, angularHelper, $timeout, $element) {
var vm = this;
let vm = this;
var typeahead;
var tagsHound;
let typeahead;
let tagsHound;
vm.$onInit = onInit;
vm.$onChanges = onChanges;
@@ -52,50 +52,52 @@
vm.isLoading = false;
//ensure that the models are formatted correctly
configureViewModel();
// Set the visible prompt to -1 to ensure it will not be visible
vm.promptIsVisible = "-1";
tagsHound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
initialize: false,
identify: function (obj) { return obj.id; },
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
//pre-fetch the tags for this category
prefetch: {
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", { tagGroup: vm.config.group, culture: vm.culture }),
//TTL = 5 minutes
ttl: 300000,
transform: dataTransform
ttl: 300000
},
//dynamically get the tags for this category (they may have changed on the server)
remote: {
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", { tagGroup: vm.config.group, culture: vm.culture }),
transform: dataTransform
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", { tagGroup: vm.config.group, culture: vm.culture, query: "%QUERY" }),
wildcard: "%QUERY"
}
});
tagsHound.initialize(true);
//configure the type ahead
$timeout(function () {
tagsHound.initialize().then(function() {
//configure the type ahead
var sources = {
//see: https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#options
// name = the data set name, we'll make this the tag group name
name: vm.config.group,
display: "value",
// name = the data set name, we'll make this the tag group name + culture
name: vm.config.group + (vm.culture ? vm.culture : ""),
display: "text",
//source: tagsHound
source: function (query, cb) {
source: function (query, syncCallback, asyncCallback) {
tagsHound.search(query,
function(suggestions) {
cb(removeCurrentTagsFromSuggestions(suggestions));
syncCallback(removeCurrentTagsFromSuggestions(suggestions));
}, function(suggestions) {
asyncCallback(removeCurrentTagsFromSuggestions(suggestions));
});
}
};
var opts = {
//This causes some strangeness as it duplicates the textbox, best leave off for now.
hint: false,
hint: true,
highlight: true,
cacheKey: new Date(), // Force a cache refresh each time the control is initialized
minLength: 1
@@ -104,28 +106,35 @@
typeahead = $element.find('.tags-' + vm.htmlId).typeahead(opts, sources)
.bind("typeahead:selected", function (obj, datum, name) {
angularHelper.safeApply($rootScope, function () {
addTagInternal(datum["value"]);
addTagInternal(datum["text"]);
vm.tagToAdd = "";
// clear the typed text
typeahead.typeahead('val', '');
});
}).bind("typeahead:autocompleted", function (obj, datum, name) {
angularHelper.safeApply($rootScope, function () {
addTagInternal(datum["value"]);
addTagInternal(datum["text"]);
vm.tagToAdd = "";
// clear the typed text
typeahead.typeahead('val', '');
});
}).bind("typeahead:opened", function (obj) {
});
});
});
});
}
/**
* Watch for value changes
* @param {any} changes
*/
function onChanges(changes) {
// watch for value changes externally
//when the model 'value' changes, sync the viewModel object
if (changes.value) {
if (!changes.value.isFirstChange() && changes.value.currentValue !== changes.value.previousValue) {
@@ -166,6 +175,7 @@
});
updateModelValue(vm.viewModel);
}
}
else if (angular.isArray(vm.value)) {
@@ -175,12 +185,10 @@
}
function updateModelValue(val) {
if (val) {
vm.onValueChanged({ value: val });
}
else {
vm.onValueChanged({ value: [] });
}
val = val ? val : [];
vm.onValueChanged({ value: val });
reValidate();
}
@@ -252,29 +260,19 @@
function hidePrompt() {
vm.promptIsVisible = "-1";
}
//helper method to format the data for bloodhound
function dataTransform(list) {
//transform the result to what bloodhound wants
var tagList = _.map(list, function (i) {
return { value: i.text };
});
// remove current tags from the list
return $.grep(tagList, function (tag) {
return ($.inArray(tag.value, vm.viewModel) === -1);
});
}
// helper method to remove current tags
function removeCurrentTagsFromSuggestions(suggestions) {
return $.grep(suggestions, function (suggestion) {
return ($.inArray(suggestion.value, vm.viewModel) === -1);
return ($.inArray(suggestion.text, vm.viewModel) === -1);
});
}
function reValidate() {
//this is required to re-validate
vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length);
//this is required to re-validate for the mandatory validation
if (vm.tagEditorForm && vm.tagEditorForm.tagCount) {
vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length);
}
}
}

View File

@@ -201,7 +201,8 @@ input[type="button"] {
}
// Made for Umbraco, 2019
.btn-selection {
.buttonBackground(@pinkLight, ligthen(@pinkLight, 20%), @blueExtraDark, @blueDark);
@btnSelectionBackgroundHover: darken(@pinkLight, 10%);
.buttonBackground(@pinkLight, @btnSelectionBackgroundHover, @blueExtraDark, @blueDark);
}
// Made for Umbraco, 2019, used for buttons that has to stand back.
.btn-white {

View File

@@ -5,7 +5,7 @@
.umb-layout-selector__active-layout {
box-sizing: border-box;
border: 1px solid transparent;
border: 1px solid @inputBorder;
cursor: pointer;
height: 30px;
width: 30px;
@@ -16,7 +16,7 @@
}
.umb-layout-selector__active-layout:hover {
border-color: @gray-8;
border-color: @inputBorderFocus;
}
.umb-layout-selector__dropdown {

View File

@@ -90,13 +90,13 @@ input.umb-table__input {
.umb-table-body .umb-table-row {
color: @gray-5;
border-top: 1px solid @gray-8;
border-top: 1px solid @gray-9;
cursor: pointer;
font-size: 14px;
position: relative;
min-height: 52px;
&:hover {
background-color: @gray-10;
background-color: @ui-option-hover;
}
}
@@ -151,12 +151,26 @@ input.umb-table__input {
// Show checkmark when checked, hide file icon
.umb-table-row--selected {
/*
.umb-table-body__fileicon {
display: none;
}
.umb-table-body__checkicon {
display: inline-block;
}
*/
&::before {
content: "";
position: absolute;
z-index:1;
top: 1px;
left: 1px;
right: 1px;
bottom: 1px;
border: 2px solid @ui-selected-border;
box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%);
pointer-events: none;
}
}
// Table Row Styles

View File

@@ -1,12 +1,9 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.TagsController",
function ($scope, angularHelper) {
function ($scope) {
$scope.valueChanged = function(value) {
$scope.model.value = value;
// the model value seems to be a reference to the same array, so we need
// to set the form as dirty explicitly when the content of the array changes
angularHelper.getCurrentForm($scope).$setDirty();
}
}

View File

@@ -259,7 +259,7 @@ namespace Umbraco.Web.Editors
},
{
"tagsDataBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<TagsDataController>(
controller => controller.GetTags("", ""))
controller => controller.GetTags("", "", null))
},
{
"examineMgmtBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<ExamineManagementController>(

View File

@@ -43,12 +43,16 @@ namespace Umbraco.Web.Editors
public class EntityController : UmbracoAuthorizedJsonController
{
private readonly ITreeService _treeService;
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState,
ITreeService treeService)
ITreeService treeService, SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
{
_treeService = treeService;
_searchableTreeCollection = searchableTreeCollection;
_treeSearcher = treeSearcher;
}
/// <summary>
@@ -69,15 +73,6 @@ namespace Umbraco.Web.Editors
}
}
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
public EntityController(SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
{
_searchableTreeCollection = searchableTreeCollection;
_treeSearcher = treeSearcher;
}
/// <summary>
/// Returns an Umbraco alias given a string
/// </summary>

View File

@@ -592,11 +592,6 @@ namespace Umbraco.Web.Editors
if (builtInAliases.Contains(p.Alias) == false && valueMapped != null)
{
p.SetValue(valueMapped.GetValue());
// FIXME: /task - ok, I give up, at that point tags are dead here, until we figure it out
// p.TagChanges.Behavior = valueMapped.TagChanges.Behavior;
// p.TagChanges.Enable = valueMapped.TagChanges.Enable;
// p.TagChanges.Tags = valueMapped.TagChanges.Tags;
}
}
}

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
@@ -15,10 +17,28 @@ namespace Umbraco.Web.PropertyEditors
[PluginController("UmbracoApi")]
public class TagsDataController : UmbracoAuthorizedApiController
{
public IEnumerable<TagModel> GetTags(string tagGroup, string culture)
/// <summary>
/// Returns all tags matching tagGroup, culture and an optional query
/// </summary>
/// <param name="tagGroup"></param>
/// <param name="culture"></param>
/// <param name="query"></param>
/// <returns></returns>
public IEnumerable<TagModel> GetTags(string tagGroup, string culture, string query = null)
{
if (culture == string.Empty) culture = null;
return Umbraco.TagQuery.GetAllTags(tagGroup, culture);
var result = Umbraco.TagQuery.GetAllTags(tagGroup, culture);
if (!query.IsNullOrWhiteSpace())
{
//TODO: add the query to TagQuery + the tag service, this is ugly but all we can do for now.
//currently we are post filtering this :( but works for now
result = result.Where(x => x.Text.InvariantContains(query));
}
return result.OrderBy(x => x.Text);
}
}
}