-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
DictionaryTreeController.cs
143 lines (124 loc) · 6.09 KB
/
DictionaryTreeController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Trees;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Trees;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Web.BackOffice.Trees
{
// We are allowed to see the dictionary tree, if we are allowed to manage templates, such that se can use the
// dictionary items in templates, even when we dont have authorization to manage the dictionary items
[Authorize(Policy = AuthorizationPolicies.TreeAccessDictionaryOrTemplates)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
[Tree(Constants.Applications.Translation, Constants.Trees.Dictionary, TreeGroup = Constants.Trees.Groups.Settings)]
public class DictionaryTreeController : TreeController
{
private readonly IMenuItemCollectionFactory _menuItemCollectionFactory;
private readonly ILocalizationService _localizationService;
public DictionaryTreeController(ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IMenuItemCollectionFactory menuItemCollectionFactory, ILocalizationService localizationService, IEventAggregator eventAggregator) : base(localizedTextService, umbracoApiControllerTypeCollection, eventAggregator)
{
_menuItemCollectionFactory = menuItemCollectionFactory;
_localizationService = localizationService;
}
protected override ActionResult<TreeNode?> CreateRootNode(FormCollection queryStrings)
{
var rootResult = base.CreateRootNode(queryStrings);
if (!(rootResult.Result is null))
{
return rootResult;
}
var root = rootResult.Value;
// the default section is settings, falling back to this if we can't
// figure out where we are from the querystring parameters
var section = Constants.Applications.Translation;
if (!queryStrings["application"].ToString().IsNullOrWhiteSpace())
section = queryStrings["application"];
if (root is not null)
{
// this will load in a custom UI instead of the dashboard for the root node
root.RoutePath = $"{section}/{Constants.Trees.Dictionary}/list";
}
return root;
}
/// <summary>
/// The method called to render the contents of the tree structure
/// </summary>
/// <param name="id">The id of the tree item</param>
/// <param name="queryStrings">
/// All of the query string parameters passed from jsTree
/// </param>
/// <remarks>
/// We are allowing an arbitrary number of query strings to be passed in so that developers are able to persist custom data from the front-end
/// to the back end to be used in the query for model data.
/// </remarks>
protected override ActionResult<TreeNodeCollection> GetTreeNodes(string id, FormCollection queryStrings)
{
if (!int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intId))
{
throw new InvalidOperationException("Id must be an integer");
}
var nodes = new TreeNodeCollection();
Func<IDictionaryItem, string> ItemSort() => item => item.ItemKey;
if (id == Constants.System.RootString)
{
nodes.AddRange(
_localizationService.GetRootDictionaryItems()?.OrderBy(ItemSort()).Select(
x => CreateTreeNode(
x.Id.ToInvariantString(),
id,
queryStrings,
x.ItemKey,
Constants.Icons.Dictionary,
_localizationService.GetDictionaryItemChildren(x.Key)?.Any() ?? false)) ?? Enumerable.Empty<TreeNode>());
}
else
{
// maybe we should use the guid as URL param to avoid the extra call for getting dictionary item
var parentDictionary = _localizationService.GetDictionaryItemById(intId);
if (parentDictionary == null)
return nodes;
nodes.AddRange(_localizationService.GetDictionaryItemChildren(parentDictionary.Key)?.ToList().OrderBy(ItemSort()).Select(
x => CreateTreeNode(
x.Id.ToInvariantString(),
id,
queryStrings,
x.ItemKey,
Constants.Icons.Dictionary,
_localizationService.GetDictionaryItemChildren(x.Key)?.Any() ?? false)) ?? Enumerable.Empty<TreeNode>());
}
return nodes;
}
/// <summary>
/// Returns the menu structure for the node
/// </summary>
/// <param name="id">The id of the tree item</param>
/// <param name="queryStrings">
/// All of the query string parameters passed from jsTree
/// </param>
/// <returns></returns>
protected override ActionResult<MenuItemCollection> GetMenuForNode(string id, FormCollection queryStrings)
{
var menu = _menuItemCollectionFactory.Create();
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
if (id != Constants.System.RootString)
{
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true);
}
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
}
}