hide/show toggle works (but only when element is not expanded)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"javascript": [
|
||||
"~/App_Plugins/brothers.uNesting/uNesting.js"
|
||||
"~/App_Plugins/brothers.uNesting/uNesting.js",
|
||||
"~/App_Plugins/brothers.uNesting/uNesting.directives.js"
|
||||
],
|
||||
"css": [
|
||||
"~/App_Plugins/brothers.uNesting/uNesting.css"
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
position: relative;
|
||||
margin-top: 1px;
|
||||
padding: 20px 0;
|
||||
color: #1b264f;
|
||||
color: #000;
|
||||
border-radius: 3px 3px 0 0;
|
||||
border-bottom: none;
|
||||
background: none;
|
||||
@@ -107,8 +107,7 @@
|
||||
top: 50%;
|
||||
margin-top: -12px;
|
||||
left: 3px;
|
||||
font-size: 1.4rem;
|
||||
z-index: 1;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.unesting-item-header-content.--has-icon
|
||||
@@ -130,15 +129,15 @@
|
||||
bottom: -15px;
|
||||
}
|
||||
|
||||
.unesting-item-header:hover .unesting-item-header-inner .unesting-item-header-content
|
||||
/*.unesting-item-header:hover .unesting-item-header-inner .unesting-item-header-content
|
||||
{
|
||||
padding-right: 130px;
|
||||
}
|
||||
}*/
|
||||
|
||||
.unesting-item-header-content
|
||||
{
|
||||
line-height: 20px;
|
||||
color: #1b264f;
|
||||
color: #000;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
}
|
||||
@@ -189,9 +188,10 @@ un-config
|
||||
{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
margin-top: -22px;
|
||||
display: flex;
|
||||
grid-gap: 8px;
|
||||
}
|
||||
@@ -200,6 +200,7 @@ un-config
|
||||
{
|
||||
transition: opacity .12s ease-in-out;
|
||||
opacity: 0;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.unesting-item-header:hover .unesting-icons > *
|
||||
@@ -215,11 +216,11 @@ un-config
|
||||
height: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #e9e9eb;
|
||||
border-radius: 16px;
|
||||
cursor: pointer;
|
||||
color: #1b264f;
|
||||
color: #000;
|
||||
transition: background 0.12s ease;
|
||||
border: 1px solid #f6f6f7;
|
||||
}
|
||||
|
||||
.unesting-icon.is-negative:hover
|
||||
@@ -241,7 +242,7 @@ un-config
|
||||
height: 3px;
|
||||
width: 3px;
|
||||
border-radius: 50%;
|
||||
background: #1b264f;
|
||||
background: #000;
|
||||
display: inline-block;
|
||||
margin: 0 1px;
|
||||
opacity: .6;
|
||||
@@ -280,7 +281,7 @@ un-config
|
||||
|
||||
.unesting-content > .umb-pane
|
||||
{
|
||||
margin: 30px 20px;
|
||||
margin: 30px 20px 30px 20px;
|
||||
}
|
||||
|
||||
.unesting-item.is-active > .unesting-content
|
||||
@@ -324,9 +325,14 @@ un-config
|
||||
border-bottom-color: #e9e9eb;
|
||||
}
|
||||
|
||||
.unesting-item .unesting-item .unesting-icons > *
|
||||
{
|
||||
background: #faf8f8;
|
||||
border-color: #e9e9eb;
|
||||
}
|
||||
|
||||
|
||||
/* media */
|
||||
|
||||
.unesting-media
|
||||
{
|
||||
display: flex;
|
||||
@@ -431,7 +437,7 @@ un-config
|
||||
background: #f6f4f4;
|
||||
border-radius: 4px;
|
||||
width: 180px;
|
||||
min-height: 60px;
|
||||
/*min-height: 60px;*/
|
||||
max-height: 65px;
|
||||
padding: 10px 15px;
|
||||
display: block;
|
||||
@@ -444,7 +450,7 @@ un-config
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #1b264f;
|
||||
color: #333;
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 5px;
|
||||
@@ -514,7 +520,7 @@ un-config
|
||||
{
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #1b264f;
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
@@ -531,9 +537,9 @@ un-config
|
||||
|
||||
|
||||
/* doctypepicker */
|
||||
.unesting-doctype-textarea
|
||||
.unesting-doctype-template
|
||||
{
|
||||
width: 100%;
|
||||
width: 400px;
|
||||
height: 64px;
|
||||
max-height: 200px;
|
||||
min-height: 32px;
|
||||
@@ -572,7 +578,7 @@ un-config
|
||||
.unesting-item[unesting-alias="newsletterHeadline"] .unesting-text-partial[unesting-index="0"]
|
||||
{
|
||||
font-size: 16px;
|
||||
color: #1b264f;
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@@ -594,9 +600,12 @@ un-config
|
||||
content: '“';
|
||||
}
|
||||
|
||||
.umb-nested-content-property-container
|
||||
{
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
/* generic overrides */
|
||||
|
||||
.btn-info
|
||||
{
|
||||
color: #454957;
|
||||
|
||||
@@ -0,0 +1,457 @@
|
||||
|
||||
|
||||
angular.module('umbraco.directives').directive('unContent', function ($compile)
|
||||
{
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
item: '=',
|
||||
node: '=',
|
||||
config: '='
|
||||
},
|
||||
link: function (scope, element)
|
||||
{
|
||||
// get template
|
||||
var template = scope.config && scope.config.nameTemplate ? scope.config.nameTemplate : null;
|
||||
|
||||
// compile & render template
|
||||
function render()
|
||||
{
|
||||
// merge element values into local scope
|
||||
angular.merge(scope, scope.item);
|
||||
|
||||
// nothing when no template is specified
|
||||
if (!template)
|
||||
{
|
||||
element.html('');
|
||||
//element.html(scope.node.documentType.description);
|
||||
return;
|
||||
}
|
||||
|
||||
// create html and compile
|
||||
element.html(template);
|
||||
$compile(element.contents())(scope);
|
||||
}
|
||||
|
||||
//scope.$watch('item', function (value)
|
||||
//{
|
||||
// render();
|
||||
//});
|
||||
|
||||
// first-time rendering
|
||||
render();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
angular.module('umbraco.directives').directive('unMedia', function ($http, $compile, umbRequestHelper)
|
||||
{
|
||||
var sizes = {
|
||||
small: 'width=30&height=30&mode=crop&quality=60',
|
||||
medium: 'width=60&height=60&mode=crop&quality=60',
|
||||
large: 'width=100&height=100&mode=crop&quality=60',
|
||||
wide: 'width=100&height=60&mode=crop&quality=60',
|
||||
high: 'width=60&height=100&mode=crop&quality=60'
|
||||
};
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
model: '=',
|
||||
key: '@',
|
||||
titleKey: '@',
|
||||
limit: '@',
|
||||
size: '@',
|
||||
hideLabel: '@'
|
||||
},
|
||||
|
||||
template: '<div class="unesting-media" unesting-size="{{_size}}">' +
|
||||
'<div class="unesting-media-item" ng-repeat="item in media" ng-class="{\'has-title\': !!item.title}">' +
|
||||
'<img src="{{item.src}}" title="{{item.title}}" class="unesting-media-item-image" />' +
|
||||
'<span class="unesting-media-item-text" ng-if="item.title">{{item.title | unHtml }}</span>' +
|
||||
'</div>' +
|
||||
'<span class="unesting-media-more" ng-if="count > media.length">+{{count - media.length}}</span>' +
|
||||
'</div>',
|
||||
|
||||
link: function (scope, element)
|
||||
{
|
||||
scope._size = sizes[scope.size] ? scope.size : 'medium';
|
||||
|
||||
var resize = sizes[scope._size];
|
||||
var limit = scope.limit || 5;
|
||||
scope.media = [];
|
||||
|
||||
var titleCache = {};
|
||||
|
||||
|
||||
// compile & render template
|
||||
function render()
|
||||
{
|
||||
var ids = scope.model;
|
||||
|
||||
if (!scope.model)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isArray(scope.model))
|
||||
{
|
||||
if (typeof scope.model[0] !== 'string' && !scope.key)
|
||||
{
|
||||
console.error("You need the <un-media key='my_key' /> property for nested media");
|
||||
return;
|
||||
}
|
||||
|
||||
ids = _.map(scope.model, function (item)
|
||||
{
|
||||
if (typeof item === 'string')
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
var value = item[scope.key];
|
||||
|
||||
if (scope.titleKey)
|
||||
{
|
||||
titleCache[value] = item[scope.titleKey];
|
||||
}
|
||||
|
||||
return value;
|
||||
}).join(',');
|
||||
}
|
||||
|
||||
ids = _.filter(ids.split(','), function (id) { return !!id; });
|
||||
scope.count = ids.length;
|
||||
|
||||
var query = "ids=" + ids.slice(0, limit).join('&ids=');
|
||||
var url = $http.get(Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "/backoffice/UmbracoApi/Unesting/GetMediaByUdis?" + query);
|
||||
|
||||
umbRequestHelper.resourcePromise(url, 'Failed to retrieve data for media ids').then(function (result)
|
||||
{
|
||||
_.each(result, function (src, id)
|
||||
{
|
||||
scope.media.push({
|
||||
id: id,
|
||||
src: src + "?" + resize,
|
||||
title: titleCache[id]
|
||||
});
|
||||
});
|
||||
|
||||
// hide label if requested
|
||||
if (scope.media.length > 0 && (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1'))
|
||||
{
|
||||
element.closest('.unesting-item-header').addClass('no-label');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
angular.module('umbraco.directives').directive('unText', function ($filter)
|
||||
{
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
model: '=',
|
||||
maxLines: '@',
|
||||
hideLabel: '@'
|
||||
},
|
||||
|
||||
template: '<div class="unesting-text" ng-if="items.length" ng-style="{ \'-webkit-line-clamp\': {{maxLines}}, \'max-height\': \'{{maxLines * 20}}px\' }">' +
|
||||
'<span class="unesting-text-partial" unesting-index="{{$index}}" ng-repeat="text in items" ng-bind-html="text"></span>' +
|
||||
'</div>',
|
||||
|
||||
link: function (scope, element)
|
||||
{
|
||||
scope.maxLines = +scope.maxLines || 2;
|
||||
scope.items = [];
|
||||
|
||||
if (!scope.model)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// hide label if requested
|
||||
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
|
||||
{
|
||||
element.closest('.unesting-item-header').addClass('no-label');
|
||||
}
|
||||
|
||||
var partials = _.filter(!_.isArray(scope.model) ? [scope.model] : scope.model, function (text) { return !!text; });
|
||||
|
||||
scope.items = _.map(partials, function (text)
|
||||
{
|
||||
return $filter('unHtml')(text, 1000);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
angular.module('umbraco.directives').directive('unBoxes', function ($compile)
|
||||
{
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
model: '=',
|
||||
key: '@',
|
||||
titleKey: '@',
|
||||
limit: '@',
|
||||
size: '@',
|
||||
hideLabel: '@'
|
||||
},
|
||||
|
||||
template: '<div class="unesting-boxes" unesting-size="{{size}}">' +
|
||||
'<div class="unesting-boxes-item" ng-repeat="item in items" ng-class="{\'has-title\': !!item.title}">' +
|
||||
'<span class="unesting-boxes-item-headline" ng-if="item.headline">{{item.headline | unHtml }}</span>' +
|
||||
'<span class="unesting-boxes-item-text" ng-if="item.text" ng-style="{ \'max-height\': \'{{item.maxLines * 20}}px\', \'-webkit-line-clamp\': {{item.maxLines}} }">{{item.text | unHtml:200 }}</span>' +
|
||||
'</div>' +
|
||||
'<span class="unesting-boxes-more" ng-if="count > items.length">+{{count - items.length}}</span>' +
|
||||
'</div>',
|
||||
|
||||
link: function (scope, element)
|
||||
{
|
||||
var maxLines = {
|
||||
medium: 3,
|
||||
large: 6
|
||||
};
|
||||
|
||||
scope.size = maxLines[scope.size] ? scope.size : 'medium';
|
||||
var limit = +scope.limit || 3;
|
||||
scope.items = [];
|
||||
|
||||
if (!scope.model)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// hide label if requested
|
||||
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
|
||||
{
|
||||
element.closest('.unesting-item-header').addClass('no-label');
|
||||
}
|
||||
|
||||
if (!_.isArray(scope.model))
|
||||
{
|
||||
console.error("The <un-boxes model='my_array' /> model has to be an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isObject(scope.model[0]) && !scope.key)
|
||||
{
|
||||
console.error("You need the <un-boxes key='my_key' /> property for nested elements");
|
||||
return;
|
||||
}
|
||||
|
||||
var items = [];
|
||||
_.each(scope.model, function (item)
|
||||
{
|
||||
var max = maxLines[scope.size];
|
||||
|
||||
if (item)
|
||||
{
|
||||
if (typeof item === 'string')
|
||||
{
|
||||
items.push({
|
||||
maxLines: max,
|
||||
text: item
|
||||
});
|
||||
}
|
||||
|
||||
var headline = item[scope.titleKey];
|
||||
|
||||
items.push({
|
||||
maxLines: headline ? max - 1 : max,
|
||||
headline: headline,
|
||||
text: item[scope.key]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
scope.items = items.slice(0, limit);
|
||||
scope.count = items.length;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
angular.module('umbraco.directives').directive('unFigure', function ($filter)
|
||||
{
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
image: '=',
|
||||
text: '=',
|
||||
headline: '=',
|
||||
size: '@',
|
||||
maxLines: '@',
|
||||
hideLabel: '@'
|
||||
},
|
||||
|
||||
template: '<div class="unesting-figure" ng-if="hasContent">' +
|
||||
'<un-media ng-if="image" model="image" size="{{size}}" />' +
|
||||
'<div class="unesting-figure-content">' +
|
||||
'<span class="unesting-figure-headline" ng-if="headline">{{headline | unHtml }}</span>' +
|
||||
'<span class="unesting-figure-text" ng-if="text" ng-style="{ \'max-height\': \'{{maxLines * 20}}px\', \'-webkit-line-clamp\': {{maxLines}} }">{{text | unHtml:800 }}</span>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
|
||||
link: function (scope, element)
|
||||
{
|
||||
scope.hasContent = !!(scope.text || scope.headline || scope.image);
|
||||
|
||||
// hide label if requested
|
||||
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
|
||||
{
|
||||
element.closest('.unesting-item-header').toggleClass('no-label', scope.hasContent);
|
||||
}
|
||||
|
||||
// calculate max lines
|
||||
scope.maxLines = +scope.maxLines || 3;
|
||||
if (scope.headline)
|
||||
{
|
||||
scope.maxLines -= 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
angular.module('umbraco.directives').directive('unConfig', function ($filter)
|
||||
{
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
hideLabel: '@',
|
||||
asColumns: '@'
|
||||
},
|
||||
|
||||
template: '',
|
||||
|
||||
link: function (scope, element)
|
||||
{
|
||||
if (scope.hideLabel === true || scope.hideLabel === 'true' || scope.hideLabel === '1')
|
||||
{
|
||||
element.closest('.unesting-item-header').addClass('no-label');
|
||||
}
|
||||
if (scope.asColumns === true || scope.asColumns === 'true' || scope.asColumns === '1')
|
||||
{
|
||||
element.closest('.unesting-item-header').addClass('as-columns');
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
angular.module("umbraco.directives").directive('uNestingContentEditor', [
|
||||
|
||||
function ()
|
||||
{
|
||||
var link = function ($scope)
|
||||
{
|
||||
// Clone the model because some property editors
|
||||
// do weird things like updating and config values
|
||||
// so we want to ensure we start from a fresh every
|
||||
// time, we'll just sync the value back when we need to
|
||||
$scope.model = angular.copy($scope.ngModel);
|
||||
$scope.nodeContext = $scope.model;
|
||||
|
||||
// Find the selected tab
|
||||
var selectedTab = $scope.model.variants[0].tabs[0];
|
||||
|
||||
if ($scope.tabAlias)
|
||||
{
|
||||
angular.forEach($scope.model.variants[0].tabs, function (tab)
|
||||
{
|
||||
if (tab.alias.toLowerCase() === $scope.tabAlias.toLowerCase())
|
||||
{
|
||||
selectedTab = tab;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.tabs = $scope.model.variants[0].tabs;
|
||||
|
||||
var contentTab = _.find($scope.tabs, function (tab)
|
||||
{
|
||||
var alias = tab.alias.toLowerCase();
|
||||
return tab.id !== 0 && alias !== 'unestingsettings' && (!$scope.tabAlias || alias === $scope.tabAlias.toLowerCase());
|
||||
});
|
||||
|
||||
$scope.contentProperties = _.filter(contentTab.properties, function (prop)
|
||||
{
|
||||
return prop.propertyAlias.toLowerCase() !== 'unestinghide';
|
||||
});
|
||||
|
||||
//var settingsTab = _.find($scope.tabs, function (tab)
|
||||
//{
|
||||
// var alias = tab.alias.toLowerCase();
|
||||
// return tab.id !== 0 && alias === 'unestingsettings';
|
||||
//});
|
||||
|
||||
//$scope.settingsProperties = settingsTab ? settingsTab.properties : [];
|
||||
$scope.settingsProperties = [];
|
||||
|
||||
// Listen for sync request
|
||||
var unsubscribe = $scope.$on("ncSyncVal", function (ev, args)
|
||||
{
|
||||
if (args.key === $scope.model.key)
|
||||
{
|
||||
// Tell inner controls we are submitting
|
||||
$scope.$broadcast("formSubmitting", { scope: $scope });
|
||||
|
||||
// Sync the values back
|
||||
angular.forEach($scope.ngModel.variants[0].tabs, function (tab)
|
||||
{
|
||||
if (tab.alias.toLowerCase() === selectedTab.alias.toLowerCase())
|
||||
{
|
||||
|
||||
var localPropsMap = selectedTab.properties.reduce(function (map, obj)
|
||||
{
|
||||
map[obj.alias] = obj;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
angular.forEach(tab.properties, function (prop)
|
||||
{
|
||||
if (localPropsMap.hasOwnProperty(prop.alias))
|
||||
{
|
||||
prop.value = localPropsMap[prop.alias].value;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('$destroy', function ()
|
||||
{
|
||||
unsubscribe();
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
restrict: "E",
|
||||
replace: true,
|
||||
templateUrl: Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "/views/propertyeditors/nestedcontent/nestedcontent.editor.html",
|
||||
scope: {
|
||||
ngModel: '=',
|
||||
tabAlias: '='
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
}
|
||||
]);
|
||||
@@ -32,7 +32,8 @@
|
||||
ng-model="config.ncTabAlias" required></select>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="unesting-doctype-textarea" ng-model="config.nameTemplate" rows="1" cols="40"></textarea>
|
||||
<div class="unesting-doctype-template" model="config.nameTemplate" umb-ace-editor="aceOptions"></div>
|
||||
<!--<textarea class="unesting-doctype-textarea" ng-model="config.nameTemplate" rows="1" cols="40"></textarea>-->
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger" ng-click="remove($index)">
|
||||
@@ -43,7 +44,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
<button type="button" class="btn" ng-click="add()" ng-disabled="!canAdd()">
|
||||
<button type="button" class="btn" ng-click="add()">
|
||||
<localize key="general_add">Add</localize>
|
||||
</button>
|
||||
<i class="icon icon-help-alt medium umb-nested-content__help-icon" ng-click="showHelpText = !showHelpText"></i>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="umb-pane unesting-editor-pane" ng-class="{ 'has-settings': hasSettings }">
|
||||
<div class="umb-pane unesting-editor-pane" ng-class="{ 'has-settings': settingsProperties.length > 0 }">
|
||||
<div class="unesting-editor-pane-content">
|
||||
<div ng-repeat="property in contentProperties" class="umb-nested-content-property-container">
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="unesting-editor-pane-settings" ng-if="hasSettings">
|
||||
|
||||
<div class="unesting-editor-pane-settings" ng-if="settingsProperties.length > 0">
|
||||
<div ng-repeat="property in settingsProperties" class="umb-nested-content-property-container">
|
||||
|
||||
<umb-property property="property" unesting-property="{{property.propertyAlias}}" ng-class="{'umb-nested-content--not-supported': property.notSupported}">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<div class="unesting-item" ng-repeat="node in nodes"
|
||||
unesting-alias="{{node.documentType.alias}}"
|
||||
ng-class="{ 'is-active' : $parent.realCurrentNode.key === node.key, 'umb-nested-content__item--single' : $parent.singleMode, 'is-hidden': !!model.value[$index]['uNestingHide'] === '1' }">
|
||||
ng-class="{ 'is-active' : $parent.realCurrentNode.key === node.key, 'umb-nested-content__item--single' : $parent.singleMode, 'is-hidden': isHidden(model.value[$index]) }">
|
||||
|
||||
<div class="unesting-item-header" ng-click="$parent.editNode($index)" ng-hide="$parent.singleMode">
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<i class="icon icon-trash-alt"></i>
|
||||
</a>
|
||||
|
||||
<a class="unesting-icon is-negative hidden-toggle" localize="title" title="general_visibility" ng-if="canHide(model.value[$index])" ng-click="clickHide($event, node, $index);" prevent-default>
|
||||
<a class="unesting-icon is-negative hidden-toggle" localize="title" title="general_visibility" ng-if="canHide(model.value[$index])" ng-click="clickHide($event, node, ncTabAlias);" prevent-default>
|
||||
<i class="icon icon-lock"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace UmbracoPackages
|
||||
{
|
||||
/// <remarks>
|
||||
/// This controller is decorated with the UmbracoApplicationAuthorizeAttribute which means that any user requesting
|
||||
/// access to ALL of the methods on this controller will need access to the media application.
|
||||
/// </remarks>
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoApplicationAuthorize(Constants.Applications.Media)]
|
||||
public class MediaExtendedController : ContentControllerBase
|
||||
{
|
||||
public MediaExtendedController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper)
|
||||
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return media for the specified UDIs
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<Udi, string> GetByUdis([FromUri]Udi[] ids)
|
||||
{
|
||||
var foundMedia = Services.MediaService.GetByIds(ids.Select(x => (x as GuidUdi).Guid));
|
||||
return foundMedia.ToDictionary(media => (Udi)media.GetUdi(), media =>
|
||||
{
|
||||
string json = media.GetValue<string>("umbracoFile");
|
||||
return JsonConvert.DeserializeObject<SrcData>(json).Src;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
class SrcData
|
||||
{
|
||||
public string Src { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,6 +395,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App_Plugins\brothers.uNesting\uNesting.directives.js" />
|
||||
<Content Include="App_Plugins\brothers.uNesting\uNesting.editor.html" />
|
||||
<Content Include="App_Plugins\brothers.uNesting\uNesting.css" />
|
||||
<Content Include="App_Plugins\brothers.uNesting\uNesting.docTypePicker.html" />
|
||||
@@ -471,7 +472,7 @@
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MediaExtendedController.cs" />
|
||||
<Compile Include="UnestingController.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace UmbracoPackages
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[UmbracoApplicationAuthorize(Constants.Applications.Content)]
|
||||
public class UnestingController : ContentControllerBase
|
||||
{
|
||||
private IContentTypeCommonRepository ContentTypeRepository { get; set; }
|
||||
|
||||
|
||||
public UnestingController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper, IContentTypeCommonRepository contentTypeRepository)
|
||||
: base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper)
|
||||
{
|
||||
ContentTypeRepository = contentTypeRepository;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return media for the specified UDIs
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<Udi, string> GetMediaByUdis([FromUri]Udi[] ids)
|
||||
{
|
||||
var foundMedia = Services.MediaService.GetByIds(ids.Select(x => (x as GuidUdi).Guid));
|
||||
return foundMedia.ToDictionary(media => (Udi)media.GetUdi(), media =>
|
||||
{
|
||||
string json = media.GetValue<string>("umbracoFile");
|
||||
return JsonConvert.DeserializeObject<SrcData>(json).Src;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an empty content item for the
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias"></param>
|
||||
/// <param name="parentId"></param>
|
||||
public Dictionary<string, ContentItemDisplay> GetScaffolds([FromUri]string[] a)
|
||||
{
|
||||
int parentId = -20;
|
||||
// string contentTypeAlias, int parentId
|
||||
|
||||
var contentTypes = ContentTypeRepository.GetAllTypes().Where(x => a.Contains(x.Alias, StringComparer.InvariantCultureIgnoreCase));
|
||||
|
||||
if (!contentTypes.Any())
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
return contentTypes.Select(contentType =>
|
||||
{
|
||||
var emptyContent = Services.ContentService.Create("", parentId, contentType.Alias, Security.GetUserId().ResultOr(0));
|
||||
var mapped = MapToDisplay(emptyContent);
|
||||
|
||||
// TODO we need access to the translation service
|
||||
// translate the content type name if applicable
|
||||
//mapped.ContentTypeName = Services.TextService.UmbracoDictionaryTranslate(mapped.ContentTypeName);
|
||||
// if your user type doesn't have access to the Settings section it would not get this property mapped
|
||||
if (mapped.DocumentType != null)
|
||||
{
|
||||
//mapped.DocumentType.Name = Services.TextService.UmbracoDictionaryTranslate(mapped.DocumentType.Name);
|
||||
}
|
||||
|
||||
//remove the listview app if it exists
|
||||
mapped.ContentApps = mapped.ContentApps.Where(x => x.Alias != "umbListView").ToList();
|
||||
|
||||
return mapped;
|
||||
}).ToDictionary(x => x.ContentTypeAlias, x => x);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used to map an <see cref="IContent"/> instance to a <see cref="ContentItemDisplay"/> and ensuring a language is present if required
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
private ContentItemDisplay MapToDisplay(IContent content)
|
||||
{
|
||||
var display = Mapper.Map<ContentItemDisplay>(content);
|
||||
display.AllowPreview = display.AllowPreview && content.Trashed == false && content.ContentType.IsElement == false;
|
||||
return display;
|
||||
}
|
||||
|
||||
|
||||
class SrcData
|
||||
{
|
||||
public string Src { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
@inherits Umbraco.Web.Mvc.UmbracoViewPage
|
||||
<section class="section section--themed section--header section--content-center-bottom">
|
||||
<div class="section__hero-content">
|
||||
<h1 class="no-air">@Model.GetProperty("PageTitle").GetValue()</h1>
|
||||
@*<h1 class="no-air">@Model.GetProperty("PageTitle").GetValue()</h1>*@
|
||||
</div>
|
||||
</section>
|
||||
Reference in New Issue
Block a user