Merge branch 'temp8' into temp8-3675-variant-tags

This commit is contained in:
Stephan
2018-12-12 08:58:25 +01:00
18 changed files with 307 additions and 313 deletions

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using Examine;
namespace Umbraco.Examine
{
/// <summary>
/// Creates <see cref="IIndex"/>'s
/// </summary>
public interface IIndexCreator
{
IEnumerable<IIndex> Create();
}
}

View File

@@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using Examine;
using Umbraco.Core;
namespace Umbraco.Examine
{
/// <summary>
/// Exposes diagnostic information about an index
/// </summary>

View File

@@ -5,18 +5,17 @@ using Umbraco.Core.Models;
namespace Umbraco.Examine
{
/// <summary>
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="TContent"/>
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="T"/>
/// </summary>
/// <typeparam name="TContent"></typeparam>
public interface IValueSetBuilder<in TContent>
where TContent : IContentBase
/// <typeparam name="T"></typeparam>
public interface IValueSetBuilder<in T>
{
/// <summary>
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="TContent"/>
/// Creates a collection of <see cref="ValueSet"/> to be indexed based on a collection of <see cref="T"/>
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
IEnumerable<ValueSet> GetValueSets(params TContent[] content);
IEnumerable<ValueSet> GetValueSets(params T[] content);
}
}

View File

@@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.IO;
using Examine;
using Examine.LuceneEngine.Directories;
using Lucene.Net.Store;
using Umbraco.Core.IO;
namespace Umbraco.Examine
{
/// <inheritdoc />
/// <summary>
/// Abstract class for creating Lucene based Indexes
/// </summary>
public abstract class LuceneIndexCreator : IIndexCreator
{
public abstract IEnumerable<IIndex> Create();
/// <summary>
/// Creates a file system based Lucene <see cref="Lucene.Net.Store.Directory"/> with the correct locking guidelines for Umbraco
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public virtual Lucene.Net.Store.Directory CreateFileSystemLuceneDirectory(string name)
{
//TODO: We should have a single AppSetting to be able to specify a default DirectoryFactory so we can have a single
//setting to configure all indexes that use this to easily swap the directory to Sync/%temp%/blog, etc...
var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name));
if (!dirInfo.Exists)
System.IO.Directory.CreateDirectory(dirInfo.FullName);
var luceneDir = new SimpleFSDirectory(dirInfo);
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
//which simply checks the existence of the lock file
// The full syntax of this is: new NoPrefixSimpleFsLockFactory(dirInfo)
// however, we are setting the DefaultLockFactory in startup so we'll use that instead since it can be managed globally.
luceneDir.SetLockFactory(DirectoryFactory.DefaultLockFactory(dirInfo));
return luceneDir;
}
}
}

View File

@@ -66,6 +66,7 @@
<Compile Include="ExamineExtensions.cs" />
<Compile Include="IContentValueSetBuilder.cs" />
<Compile Include="IContentValueSetValidator.cs" />
<Compile Include="IIndexCreator.cs" />
<Compile Include="IIndexDiagnostics.cs" />
<Compile Include="IIndexPopulator.cs" />
<Compile Include="IndexPopulator.cs" />
@@ -88,6 +89,7 @@
<Compile Include="UmbracoExamineIndexDiagnostics.cs" />
<Compile Include="UmbracoExamineIndex.cs" />
<Compile Include="UmbracoExamineSearcher.cs" />
<Compile Include="LuceneIndexCreator.cs" />
<Compile Include="UmbracoMemberIndex.cs" />
<Compile Include="..\SolutionInfo.cs">
<Link>Properties\SolutionInfo.cs</Link>

View File

@@ -148,7 +148,7 @@ namespace Umbraco.Tests.Services
//change the content type to be invariant, we will also update the name here to detect the copy changes
doc.SetCultureName("Hello2", "en-US");
ServiceContext.ContentService.Save(doc);
contentType.Variations = ContentVariation.Nothing;
contentType.Variations = ContentVariation.Nothing;
ServiceContext.ContentTypeService.Save(contentType);
doc = ServiceContext.ContentService.GetById(doc.Id); //re-get
@@ -372,7 +372,7 @@ namespace Umbraco.Tests.Services
doc2 = ServiceContext.ContentService.GetById(doc2.Id); //re-get
//this will be null because the doc type was changed back to variant but it's property types don't get changed back
Assert.IsNull(doc.GetValue("title", "en-US"));
Assert.IsNull(doc.GetValue("title", "en-US"));
Assert.IsNull(doc2.GetValue("title", "en-US"));
}
@@ -1714,50 +1714,65 @@ namespace Umbraco.Tests.Services
// Arrange
var service = ServiceContext.ContentTypeService;
// create 'page' content type with a 'Content_' group
var page = MockedContentTypes.CreateSimpleContentType("page", "Page", null, false, "Content_");
Assert.IsTrue(page.PropertyGroups.Contains("Content_"));
Assert.AreEqual(3, page.PropertyTypes.Count());
service.Save(page);
// create 'contentPage' content type as a child of 'page'
var contentPage = MockedContentTypes.CreateSimpleContentType("contentPage", "Content Page", page, true);
service.Save(contentPage);
var composition = MockedContentTypes.CreateMetaContentType();
composition.AddPropertyGroup("Content");
service.Save(composition);
//Adding Meta-composition to child doc type
contentPage.AddContentType(composition);
Assert.AreEqual(3, contentPage.PropertyTypes.Count());
service.Save(contentPage);
// Act
var propertyTypeOne = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "testTextbox")
// add 'Content' group to 'meta' content type
var meta = MockedContentTypes.CreateMetaContentType();
meta.AddPropertyGroup("Content");
Assert.AreEqual(2, meta.PropertyTypes.Count());
service.Save(meta);
// add 'meta' content type to 'contentPage' composition
contentPage.AddContentType(meta);
service.Save(contentPage);
// add property 'prop1' to 'contentPage' group 'Content_'
var prop1 = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "testTextbox")
{
Name = "Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88
};
var firstOneAdded = contentPage.AddPropertyType(propertyTypeOne, "Content_");
var propertyTypeTwo = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "anotherTextbox")
var prop1Added = contentPage.AddPropertyType(prop1, "Content_");
Assert.IsTrue(prop1Added);
// add property 'prop2' to 'contentPage' group 'Content'
var prop2 = new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Ntext, "anotherTextbox")
{
Name = "Another Test Textbox", Description = "", Mandatory = false, SortOrder = 1, DataTypeId = -88
};
var secondOneAdded = contentPage.AddPropertyType(propertyTypeTwo, "Content");
var prop2Added = contentPage.AddPropertyType(prop2, "Content");
Assert.IsTrue(prop2Added);
// save 'contentPage' content type
service.Save(contentPage);
Assert.That(page.PropertyGroups.Contains("Content_"), Is.True);
var propertyGroup = page.PropertyGroups["Content_"];
page.PropertyGroups.Add(new PropertyGroup(true) { Id = propertyGroup.Id, Name = "ContentTab", SortOrder = 0});
var group = page.PropertyGroups["Content_"];
group.Name = "ContentTab"; // rename the group
service.Save(page);
Assert.AreEqual(3, page.PropertyTypes.Count());
// Assert
Assert.That(firstOneAdded, Is.True);
Assert.That(secondOneAdded, Is.True);
// get 'contentPage' content type again
var contentPageAgain = service.Get("contentPage");
Assert.IsNotNull(contentPageAgain);
var contentType = service.Get("contentPage");
Assert.That(contentType, Is.Not.Null);
// assert that 'Content_' group is still there because we don't propagate renames
var findGroup = contentPageAgain.CompositionPropertyGroups.FirstOrDefault(x => x.Name == "Content_");
Assert.IsNotNull(findGroup);
var compositionPropertyGroups = contentType.CompositionPropertyGroups;
// now it is still 1, because we don't propagate renames anymore
Assert.That(compositionPropertyGroups.Count(x => x.Name.Equals("Content_")), Is.EqualTo(1));
var propertyTypeCount = contentType.PropertyTypes.Count();
var compPropertyTypeCount = contentType.CompositionPropertyTypes.Count();
// count all property types (local and composed)
var propertyTypeCount = contentPageAgain.PropertyTypes.Count();
Assert.That(propertyTypeCount, Is.EqualTo(5));
// count composed property types
var compPropertyTypeCount = contentPageAgain.CompositionPropertyTypes.Count();
Assert.That(compPropertyTypeCount, Is.EqualTo(10));
}

View File

@@ -124,58 +124,6 @@
</tr>
</table>
<h1>Content Picker</h1>
Opens a content picker.</br>
<strong>view: </strong>contentpicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.selection</td>
<td>Array</td>
<td>Array of content objects</td>
</tr>
</table>
<h1>Icon Picker</h1>
Opens an icon picker.</br>
<strong>view: </strong>iconpicker
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tr>
<td>model.icon</td>
<td>String</td>
<td>The icon class</td>
</tr>
</table>
<h1>Item Picker</h1>
Opens an item picker.</br>
<strong>view: </strong>itempicker
@@ -220,170 +168,6 @@ Opens an item picker.</br>
</tr>
</table>
<h1>Macro Picker</h1>
Opens a media picker.</br>
<strong>view: </strong>macropicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.dialogData</td>
<td>Object</td>
<td>Object which contains array of allowedMacros. Set to <code>null</code> to allow all.</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.macroParams</td>
<td>Array</td>
<td>Array of macro params</td>
</tr>
<tr>
<td>model.selectedMacro</td>
<td>Object</td>
<td>The selected macro</td>
</tr>
</tbody>
</table>
<h1>Media Picker</h1>
Opens a media picker.</br>
<strong>view: </strong>mediapicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
<tr>
<td>model.onlyImages</td>
<td>Boolean</td>
<td>Only display files that have an image file-extension</td>
</tr>
<tr>
<td>model.disableFolderSelect</td>
<td>Boolean</td>
<td>Disable folder selection</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.selectedImages</td>
<td>Array</td>
<td>Array of selected images</td>
</tr>
</tbody>
</table>
<h1>Member Group Picker</h1>
Opens a member group picker.</br>
<strong>view: </strong>membergrouppicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.selectedMemberGroup</td>
<td>String</td>
<td>The selected member group</td>
</tr>
<tr>
<td>model.selectedMemberGroups (multiPicker)</td>
<td>Array</td>
<td>The selected member groups</td>
</tr>
</tbody>
</table>
<h1>Member Picker</h1>
Opens a member picker. </br>
<strong>view: </strong>memberpicker
<table>
<thead>
<tr>
<th>Param</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.multiPicker</td>
<td>Boolean</td>
<td>Pick one or multiple items</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Returns</th>
<th>Type</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>model.selection</td>
<td>Array</td>
<td>Array of selected members/td>
</tr>
</tbody>
</table>
<h1>YSOD</h1>
Opens an overlay to show a custom YSOD. </br>
<strong>view: </strong>ysod

View File

@@ -35,7 +35,7 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
/**
* @ngdoc method
* @name umbraco.resources.relationTypeResource#getRelationObjectTypes
* @methodof umbraco.resources.relationTypeResource
* @methodOf umbraco.resources.relationTypeResource
*
* @description
* Gets a list of Umbraco object types which can be associated with a relation.
@@ -54,7 +54,7 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
/**
* @ngdoc method
* @name umbraco.resources.relationTypeResource#save
* @methodof umbraco.resources.relationTypeResource
* @methodOf umbraco.resources.relationTypeResource
*
* @description
* Updates a relation type.
@@ -74,7 +74,7 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
/**
* @ngdoc method
* @name umbraco.resources.relationTypeResource#create
* @methodof umbraco.resources.relationTypeResource
* @methodOf umbraco.resources.relationTypeResource
*
* @description
* Creates a new relation type.
@@ -94,7 +94,7 @@ function relationTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
/**
* @ngdoc method
* @name umbraco.resources.relationTypeResource#deleteById
* @methodof umbraco.resources.relationTypeResource
* @methodOf umbraco.resources.relationTypeResource
*
* @description
* Deletes a relation type with a given ID.

View File

@@ -4,6 +4,76 @@
*
* @description
* Added in Umbraco 8.0. Application-wide service for handling infinite editing.
*
*
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<button type="button" ng-click="vm.open()">Open</button>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.open = open;
function open() {
var mediaPickerOptions = {
multiPicker: true,
submit: function(model) {
editorService.close();
},
close: function() {
editorService.close();
}
}
editorService.mediaPicker(mediaPickerOptions);
};
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
<h3>Custom view example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.open = open;
function open() {
var options = {
view: "path/to/view.html"
submit: function(model) {
editorService.close();
},
close: function() {
editorService.close();
}
}
editorService.open(options);
};
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
*/
(function () {
"use strict";
@@ -43,6 +113,10 @@
*
* @description
* Method to open a new editor in infinite editing
*
* @param {Object} editor rendering options
* @param {String} editor.view Path to view
* @param {String} editor.size Sets the size of the editor ("Small"). If nothing is set it will use full width.
*/
function open(editor) {
@@ -108,8 +182,12 @@
*
* @description
* Opens a media editor in infinite editing, the submit callback returns the updated content item
* @param {Object} editor rendering options
* @param {String} editor.id The id of the content item
* @param {Boolean} editor.create Create new content item
* @param {Function} editor.submit Callback function when the publish and close button is clicked. Returns the editor model object
* @param {Function} editor.close Callback function when the close button is clicked.
*
* @returns {Object} editor object
*/
function contentEditor(editor) {
@@ -124,6 +202,12 @@
*
* @description
* Opens a content picker in infinite editing, the submit callback returns an array of selected items
*
* @param {Object} editor rendering options
* @param {Boolean} editor.multiPicker Pick one or multiple items
* @param {Function} editor.submit Callback function when the submit button is clicked. Returns the editor model object
* @param {Function} editor.close Callback function when the close button is clicked.
*
* @returns {Object} editor object
*/
function contentPicker(editor) {
@@ -218,11 +302,13 @@
*
* @description
* Opens an embed editor in infinite editing.
* @param {Object} editor rendering options
* @param {String} editor.icon The icon class
* @param {String} editor.color The color class
* @param {Callback} editor.submit Saves, submits, and closes the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
*/
function linkPicker(editor) {
editor.view = "views/common/infiniteeditors/linkpicker/linkpicker.html";
editor.size = "small";
@@ -236,6 +322,7 @@
*
* @description
* Opens a media editor in infinite editing, the submit callback returns the updated media item
* @param {Object} editor rendering options
* @param {String} editor.id The id of the media item
* @param {Boolean} editor.create Create new media item
* @param {Callback} editor.submit Saves, submits, and closes the editor
@@ -254,6 +341,7 @@
*
* @description
* Opens a media picker in infinite editing, the submit callback returns an array of selected media items
* @param {Object} editor rendering options
* @param {Boolean} editor.multiPicker Pick one or multiple items
* @param {Boolean} editor.onlyImages Only display files that have an image file-extension
* @param {Boolean} editor.disableFolderSelect Disable folder selection
@@ -276,6 +364,7 @@
*
* @description
* Opens an icon picker in infinite editing, the submit callback returns the selected icon
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -293,6 +382,7 @@
*
* @description
* Opens the document type editor in infinite editing, the submit callback returns the saved document type
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -309,6 +399,7 @@
*
* @description
* Opens the media type editor in infinite editing, the submit callback returns the saved media type
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -318,24 +409,75 @@
open(editor);
}
/**
* @ngdoc method
* @name umbraco.services.editorService#queryBuilder
* @methodOf umbraco.services.editorService
*
* @description
* Opens the query builder in infinite editing, the submit callback returns the generted query
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
*/
function queryBuilder(editor) {
editor.view = "views/common/infiniteeditors/querybuilder/querybuilder.html";
editor.size = "small";
open(editor);
}
/**
* @ngdoc method
* @name umbraco.services.editorService#treePicker
* @methodOf umbraco.services.editorService
*
* @description
* Opens the query builder in infinite editing, the submit callback returns the generted query
* @param {Object} editor rendering options
* @param {String} options.section tree section to display
* @param {String} options.treeAlias specific tree to display
* @param {Boolean} options.multiPicker should the tree pick one or multiple items before returning
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
*/
function treePicker(editor) {
editor.view = "views/common/infiniteeditors/treepicker/treepicker.html";
editor.size = "small";
open(editor);
}
/**
* @ngdoc method
* @name umbraco.services.editorService#nodePermissions
* @methodOf umbraco.services.editorService
*
* @description
* Opens the an editor to set node permissions.
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
*/
function nodePermissions(editor) {
editor.view = "views/common/infiniteeditors/nodepermissions/nodepermissions.html";
editor.size = "small";
open(editor);
}
/**
* @ngdoc method
* @name umbraco.services.editorService#insertCodeSnippet
* @methodOf umbraco.services.editorService
*
* @description
* Open an editor to insert code snippets into the code editor
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
*/
function insertCodeSnippet(editor) {
editor.view = "views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.html";
editor.size = "small";
@@ -349,6 +491,7 @@
*
* @description
* Opens the user group picker in infinite editing, the submit callback returns an array of the selected user groups
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -366,6 +509,7 @@
*
* @description
* Opens the user group picker in infinite editing, the submit callback returns the saved template
* @param {Object} editor rendering options
* @param {String} editor.id The template id
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
@@ -382,7 +526,8 @@
* @methodOf umbraco.services.editorService
*
* @description
* Opens the section picker in infinite editing, the submit callback returns an array of the selected sections
* Opens the section picker in infinite editing, the submit callback returns an array of the selected sections¨
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -400,6 +545,7 @@
*
* @description
* Opens the insert field editor in infinite editing, the submit callback returns the code snippet
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -417,6 +563,7 @@
*
* @description
* Opens the template sections editor in infinite editing, the submit callback returns the type to insert
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -429,11 +576,12 @@
/**
* @ngdoc method
* @name umbraco.services.editorService#sectionPicker
* @name umbraco.services.editorService#userPicker
* @methodOf umbraco.services.editorService
*
* @description
* Opens the section picker in infinite editing, the submit callback returns an array of the selected users
* @param {Object} editor rendering options
* @param {Callback} editor.submit Submits the editor
* @param {Callback} editor.close Closes the editor
* @returns {Object} editor object
@@ -452,6 +600,7 @@
* @description
* Opens the section picker in infinite editing, the submit callback returns an array of the selected items
*
* @param {Object} editor rendering options
* @param {Array} editor.availableItems Array of available items.
* @param {Array} editor.selectedItems Array of selected items. When passed in the selected items will be filtered from the available items.
* @param {Boolean} editor.filter Set to false to hide the filter.
@@ -485,12 +634,14 @@
/**
* @ngdoc method
* @name umbraco.services.editorService#macroPicker
* @name umbraco.services.editorService#memberGroupPicker
* @methodOf umbraco.services.editorService
*
* @description
* Opens a member group picker in infinite editing.
*
* @param {Object} editor rendering options
* @param {Object} editor.multiPicker Pick one or multiple items.
* @param {Callback} editor.submit Submits the editor.
* @param {Callback} editor.close Closes the editor.
* @returns {Object} editor object

View File

@@ -1,13 +1,14 @@
.umb-dashboards-forms-install {
background: url('../img/forms/installer-background.png');
background-repeat: repeat-x;
position: relative;
top: -30px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding-top: 30px;
box-shadow: inset 0px -40px 30px 25px rgba(255,255,255,1);
-moz-border-radius: 0px 0px 200px 200px;
-webkit-border-radius: 0px 0px 200px 200px;
border-radius: 0px 0px 200px 200px;
background-color: @white;
overflow: auto;
small {
font-size: 14px;

View File

@@ -1,10 +0,0 @@
{
"dashboards": [
{
"name": "Install Umbraco Forms",
"alias": "installUmbracoForms",
"view": "views/dashboard/forms/formsdashboardintro.html",
"sections": [ "forms" ]
}
]
}

View File

@@ -231,7 +231,6 @@
<Content Include="Umbraco\Install\Views\Web.config" />
<Content Include="App_Plugins\ModelsBuilder\package.manifest" />
<Content Include=".eslintignore" />
<Content Include="App_Plugins\UmbracoForms\package.manifest" />
<None Include="Config\404handlers.Release.config">
<DependentUpon>404handlers.config</DependentUpon>
</None>

View File

@@ -22,6 +22,17 @@
</tab>
</section>
<section alias="StartupFormsDashboardSection">
<areas>
<area>forms</area>
</areas>
<tab caption="Install Umbraco Forms">
<control panelCaption="">
views/dashboard/forms/formsdashboardintro.html
</control>
</tab>
</section>
<section alias="StartupMediaDashboardSection">
<areas>
<area>media</area>

View File

@@ -30,9 +30,5 @@
<add initialize="true" sortOrder="1" alias="memberGroups" application="member" title="Member Groups" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberGroupTreeController, Umbraco.Web" />
<!--Translation-->
<add initialize="true" application="translation" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" />
<!-- Custom -->
<add initialize="true" sortOrder="2" alias="datasource" application="forms" title="Datasources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.DataSourceTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="0" alias="form" application="forms" title="Forms" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="3" alias="prevaluesource" application="forms" title="Prevalue sources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.PreValueSourceTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="3" alias="formsecurity" application="users" title="Forms Security" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormSecurityTreeController, Umbraco.Forms.Web" />
</trees>

View File

@@ -30,9 +30,5 @@
<add initialize="true" sortOrder="1" alias="memberGroups" application="member" title="Member Groups" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberGroupTreeController, Umbraco.Web" />
<!--Translation-->
<add initialize="true" application="translation" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" />
<!-- Custom -->
<add initialize="true" sortOrder="2" alias="datasource" application="forms" title="Datasources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.DataSourceTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="0" alias="form" application="forms" title="Forms" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="3" alias="prevaluesource" application="forms" title="Prevalue sources" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.PreValueSourceTreeController, Umbraco.Forms.Web" />
<add initialize="true" sortOrder="3" alias="formsecurity" application="users" title="Forms Security" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Forms.Web.Trees.FormSecurityTreeController, Umbraco.Forms.Web" />
</trees>

View File

@@ -1,13 +1,14 @@
using System.Collections.Generic;
using Examine;
using Umbraco.Examine;
namespace Umbraco.Web.Search
{
/// <inheritdoc />
/// <summary>
/// Used to create the Umbraco indexes
/// </summary>
public interface IUmbracoIndexesCreator
public interface IUmbracoIndexesCreator : IIndexCreator
{
IEnumerable<IIndex> Create();
}
}

View File

@@ -21,7 +21,7 @@ namespace Umbraco.Web.Search
/// <summary>
/// Creates the indexes used by Umbraco
/// </summary>
public class UmbracoIndexesCreator : IUmbracoIndexesCreator
public class UmbracoIndexesCreator : LuceneIndexCreator, IUmbracoIndexesCreator
{
//TODO: we should inject the different IValueSetValidator so devs can just register them instead of overriding this class?
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Search
/// Creates the Umbraco indexes
/// </summary>
/// <returns></returns>
public IEnumerable<IIndex> Create()
public override IEnumerable<IIndex> Create()
{
return new []
{
@@ -61,7 +61,7 @@ namespace Umbraco.Web.Search
Constants.UmbracoIndexes.InternalIndexName,
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath),
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.InternalIndexPath),
new CultureInvariantWhitespaceAnalyzer(),
ProfilingLogger,
LanguageService,
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Search
Constants.UmbracoIndexes.ExternalIndexName,
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath),
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.ExternalIndexPath),
new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30),
ProfilingLogger,
LanguageService,
@@ -89,27 +89,13 @@ namespace Umbraco.Web.Search
Constants.UmbracoIndexes.MembersIndexName,
//fixme - how to deal with languages like in UmbracoContentIndexer.CreateFieldValueTypes
UmbracoExamineIndex.UmbracoIndexFieldDefinitions,
GetFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath),
CreateFileSystemLuceneDirectory(Constants.UmbracoIndexes.MembersIndexPath),
new CultureInvariantWhitespaceAnalyzer(),
ProfilingLogger,
GetMemberValueSetValidator());
return index;
}
public virtual Lucene.Net.Store.Directory GetFileSystemLuceneDirectory(string name)
{
var dirInfo = new DirectoryInfo(Path.Combine(IOHelper.MapPath(SystemDirectories.Data), "TEMP", "ExamineIndexes", name));
if (!dirInfo.Exists)
System.IO.Directory.CreateDirectory(dirInfo.FullName);
var luceneDir = new SimpleFSDirectory(dirInfo);
//we want to tell examine to use a different fs lock instead of the default NativeFSFileLock which could cause problems if the appdomain
//terminates and in some rare cases would only allow unlocking of the file if IIS is forcefully terminated. Instead we'll rely on the simplefslock
//which simply checks the existence of the lock file
luceneDir.SetLockFactory(new NoPrefixSimpleFsLockFactory(dirInfo));
return luceneDir;
}
public virtual IContentValueSetValidator GetContentValueSetValidator()
{
return new ContentValueSetValidator(false, true, PublicAccessService);

View File

@@ -78,10 +78,20 @@ namespace Umbraco.Web.Trees
}
}
var multiTree = TreeRootNode.CreateMultiTreeRoot(collection);
multiTree.Name = Services.TextService.Localize("sections/" + application);
if(collection.Count > 0)
{
var multiTree = TreeRootNode.CreateMultiTreeRoot(collection);
multiTree.Name = Services.TextService.Localize("sections/" + application);
return multiTree;
return multiTree;
}
//Otherwise its a application/section with no trees (aka a full screen app)
//For example we do not have a Forms tree definied in C# & can not attribute with [Tree(isSingleNodeTree:true0]
var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
var section = Services.TextService.Localize("sections/" + application);
return TreeRootNode.CreateSingleTreeRoot(rootId, null, null, section, TreeNodeCollection.Empty, true);
}
var rootNodeGroups = new List<TreeRootNode>();