Merge branch '7.0.0' of https://github.com/umbraco/Umbraco-CMS into 7.0.0

This commit is contained in:
Sebastiaan Janssen
2013-09-26 15:45:44 +02:00
18 changed files with 408 additions and 112 deletions

View File

@@ -0,0 +1,46 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbContentName
* @restrict E
* @function
* @description
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
**/
angular.module("umbraco.directives")
.directive('umbContentName', function ($timeout) {
return {
require: "ngModel",
restrict: 'E',
replace: true,
templateUrl: 'views/directives/umb-content-name.html',
scope: {
placeholder: '@placeholder',
model: '=ngModel'
},
link: function(scope, element, attrs, ngModel) {
ngModel.$render = function(){
$timeout(function(){
if(scope.model === ""){
scope.goEdit();
}
}, 100);
};
scope.goEdit = function(){
scope.editMode = true;
$timeout(function(){
element.find("input").focus();
}, 100);
};
scope.exitEdit = function(){
scope.editMode = false;
if(scope.model === ""){
scope.model = "Empty...";
}
};
}
};
});

View File

@@ -0,0 +1,20 @@
angular.module("umbraco.directives")
.directive('localize', function ($log, localizationService) {
return {
restrict: 'E',
scope:{
key: '@'
},
replace: true,
link: function (scope, element, attrs) {
var key = scope.key;
if(key[0] === '#')
{
key = key.slice(1);
}
var value = localizationService.getLocalizedString(key);
element.html(value);
}
};
});

View File

@@ -1,50 +0,0 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbContentName
* @restrict E
* @function
* @description
* Used by editors that require naming an entity. Shows a textbox/headline with a required validator within it's own form.
**/
angular.module("umbraco.directives")
.directive('umbContentName', function ($timeout) {
return {
require: "ngModel",
restrict: 'E',
replace: true,
templateUrl: 'views/directives/umb-content-name.html',
scope: {
placeholder: '@placeholder',
model: '=ngModel'
},
link: function(scope, element, attrs, modelCtrl) {
var input = $(element).find('input');
var h1 = $(element).find('h1');
input.hide();
input.on("blur", function () {
//Don't hide the input field if there is no value in it
var val = input.val() || "empty";
input.hide();
h1.text(val);
h1.show();
});
h1.on("click", function () {
h1.hide();
input.show().focus();
});
$timeout(function(){
if(!scope.model){
h1.hide();
input.show().focus();
}
}, 500);
}
};
});

View File

@@ -0,0 +1,107 @@
/**
* @ngdoc service
* @name umbraco.resources.logResource
* @description Retrives log history from umbraco
*
*
**/
function logResource($q, $http, umbRequestHelper) {
//the factory object returned
return {
/**
* @ngdoc method
* @name umbraco.resources.userResource#getEntityLog
* @methodOf umbraco.resources.logResource
*
* @description
* Gets the log history for a give entity id
*
* ##usage
* <pre>
* logResource.getEntityLog(1234)
* .then(function(log) {
* alert('its here!');
* });
* </pre>
*
* @param {Int} id id of entity to return log history
* @returns {Promise} resourcePromise object containing the log.
*
*/
getEntityLog: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetEntityLog",
[{ id: id }])),
'Failed to retreive user data for id ' + id);
},
/**
* @ngdoc method
* @name umbraco.resources.userResource#getUserLog
* @methodOf umbraco.resources.logResource
*
* @description
* Gets the current users' log history for a given type of log entry
*
* ##usage
* <pre>
* logResource.getUserLog("save", new Date())
* .then(function(log) {
* alert('its here!');
* });
* </pre>
*
* @param {String} type logtype to query for
* @param {DateTime} since query the log back to this date, by defalt 7 days ago
* @returns {Promise} resourcePromise object containing the log.
*
*/
getUserLog: function (type, since) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetUserLog",
[{ logtype: type, sinceDate: since }])),
'Failed to retreive user data for id ' + id);
},
/**
* @ngdoc method
* @name umbraco.resources.userResource#getLog
* @methodOf umbraco.resources.logResource
*
* @description
* Gets the log history for a given type of log entry
*
* ##usage
* <pre>
* logResource.getLog("save", new Date())
* .then(function(log) {
* alert('its here!');
* });
* </pre>
*
* @param {String} type logtype to query for
* @param {DateTime} since query the log back to this date, by defalt 7 days ago
* @returns {Promise} resourcePromise object containing the log.
*
*/
getLog: function (type, since) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetLog",
[{ logtype: type, sinceDate: since }])),
'Failed to retreive user data for id ' + id);
}
};
}
angular.module('umbraco.resources').factory('logResource', logResource);

View File

@@ -0,0 +1,84 @@
angular.module('umbraco.services')
.factory('localizationService', function ($http, $q, $rootScope, $window, $filter, userService) {
var localize = {
// use the $window service to get the language of the user's browser
language: userService.getCurrentUser().locale,
// array to hold the localized resource string entries
dictionary:[],
// location of the resource file
url: "js/language.aspx",
// flag to indicate if the service hs loaded the resource file
resourceFileLoaded:false,
// success handler for all server communication
successCallback:function (data) {
// store the returned array in the dictionary
localize.dictionary = data;
// set the flag that the resource are loaded
localize.resourceFileLoaded = true;
// broadcast that the file has been loaded
$rootScope.$broadcast('localizeResourcesUpdates');
},
// allows setting of language on the fly
setLanguage: function(value) {
localize.language = value;
localize.initLocalizedResources();
},
// allows setting of resource url on the fly
setUrl: function(value) {
localize.url = value;
localize.initLocalizedResources();
},
// builds the url for locating the resource file
buildUrl: function() {
return '/i18n/resources-locale_' + localize.language + '.js';
},
// loads the language resource file from the server
initLocalizedResources:function () {
var deferred = $q.defer();
// build the url to retrieve the localized resource file
$http({ method:"GET", url:localize.url, cache:false })
.then(function(response){
localize.resourceFileLoaded = true;
localize.dictionary = response.data;
$rootScope.$broadcast('localizeResourcesUpdates');
return deferred.resolve(localize.dictionary);
}, function(err){
return deferred.reject("Something broke");
});
return deferred.promise;
},
// checks the dictionary for a localized resource string
getLocalizedString: function(value) {
if(localize.resourceFileLoaded){
return _lookup(value);
}else{
localize.initLocalizedResources().then(function(dic){
return _lookup(value);
});
}
},
_lookup: function(value){
var entry = localize.dictionary[value];
if(entry){
return entry;
}
return "[" + value + "]";
}
};
// force the load of the resource file
localize.initLocalizedResources();
// return the local instance when called
return localize;
});

View File

@@ -22,6 +22,11 @@ label.control-label {
padding-top: 8px !important;
}
.umb-status-label{
color: @gray !important;
}
.controls-row label{padding: 0px 10px 0px 10px; vertical-align: center}

View File

@@ -63,16 +63,7 @@ h1.headline{height: 40px; padding: 30px 0 0 20px;}
margin: -2px 0 0 0;
}
.umb-headline-editor-wrapper input{
display: none;
font-size: @fontSizeMedium
}
.umb-headline-editor-wrapper h1.umb-headline-editor:hover, .umb-headline-editor-wrapper input {
border-bottom: 1px dashed @grayLight;
}
.umb-headline-editor-wrapper input:focus {
.umb-headline-editor-wrapper input {
background: none;
border: none;
width: auto;

View File

@@ -42,7 +42,7 @@ data-file-upload="options" data-file-upload-progress="" data-ng-class="{'fileupl
ng-show="showFolderInput"
ng-model="newFolderName"
ng-keyup="submitFolder($event)"
ng-blur="showFolderInput = false">
on-blur="showFolderInput = false">
</li>
</ul>
</div>

View File

@@ -6,7 +6,7 @@
* @description
* The controller for the content editor
*/
function ContentEditController($scope, $routeParams, contentResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, editorContextService) {
function ContentEditController($scope, $routeParams, $q, $timeout, $window, contentResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, editorContextService) {
//initialize the file manager
fileManager.clearFiles();
@@ -68,7 +68,28 @@ function ContentEditController($scope, $routeParams, contentResource, notificati
});
};
$scope.preview = function(content){
if(!content.id){
$scope.save().then(function(data){
$window.open('dialogs/preview.aspx?id='+data.id,'umbpreview');
});
}else{
$window.open('dialogs/preview.aspx?id='+content.id,'umbpreview');
}
};
$scope.setStatus = function(status){
//add localization
$scope.status = status;
$timeout(function(){
$scope.status = undefined;
}, 2500);
};
$scope.save = function () {
var deferred = $q.defer();
$scope.setStatus("Saving...");
$scope.$broadcast("saving", { scope: $scope });
var currentForm = angularHelper.getRequiredCurrentForm($scope);
@@ -86,6 +107,8 @@ function ContentEditController($scope, $routeParams, contentResource, notificati
newContent: data,
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data)
});
deferred.resolve(data);
}, function (err) {
contentEditingHelper.handleSaveError({
@@ -93,7 +116,11 @@ function ContentEditController($scope, $routeParams, contentResource, notificati
allNewProps: contentEditingHelper.getAllProps(err.data),
allOrigProps: contentEditingHelper.getAllProps($scope.content)
});
deferred.reject(err);
});
return deferred.promise;
};
}

View File

@@ -13,13 +13,18 @@
</div>
<div class="span8">
<div class="btn-toolbar pull-right umb-btn-toolbar">
<div class="btn-group">
<a class="btn" ng-click="preview(content)">Preview page</a>
data-hotkey="ctrl+s">Preview page</a>
<div class="btn-group" ng-animate="'fade'" ng-show="status">
<p class="btn btn-link umb-status-label">{{status}}</p>
</div>
<div class="btn-group">
<a class="btn" ng-click="preview(content)">Preview page</a>
</div>
<div class="btn-group">
<a class="btn btn-success" href="#" ng-click="saveAndPublish()"
prevent-default data-hotkey="ctrl+p">Publish</a>

View File

@@ -16,19 +16,13 @@ function startUpVideosDashboardController($scope, xmlhelper, $log, $http) {
}
angular.module("umbraco").controller("Umbraco.Dashboard.StartupVideosController", startUpVideosDashboardController);
function startupLatestEditsController($scope) {
}
angular.module("umbraco").controller("Umbraco.Dashboard.StartupLatestEditsController", startupLatestEditsController);
function MediaFolderBrowserDashboardController($scope, xmlhelper, $log, userResource) {
//this is the model we will pass to the service
$scope.profile = {};
$scope.changePassword = function (p) {
userResource.changePassword(p.oldPassword, p.newPassword).then(function () {
$scope.passwordForm.$setValidity(true);
}, function () {
//this only happens if there is a wrong oldPassword sent along
$scope.passwordForm.oldpass.$setValidity("oldPassword", false);
});
}
function MediaFolderBrowserDashboardController($scope) {
}
angular.module("umbraco").controller("Umbraco.Dashboard.MediaFolderBrowserDashboardController", MediaFolderBrowserDashboardController);

View File

@@ -2,8 +2,15 @@
<ng-form name="contentNameForm">
<h1>{{model}}</h1>
<input name="name" type="text" placeholder="{{placeholder}}" ng-model="model"
<h1 ng-click="goEdit()" ng-hide="editMode">{{model}}</h1>
<input
on-blur="editMode = false"
ng-show="editMode"
name="name"
type="text"
placeholder="{{placeholder}}"
ng-model="model"
required
val-server-field="Name" />

View File

@@ -85,6 +85,7 @@
</control>
</tab>
</section>
<section alias="StartupMemberDashboardSection">
<areas>
<area>member</area>
@@ -110,4 +111,5 @@
<control>/umbraco/dashboard/ExamineManagement.ascx</control>
</tab>
</section>
</dashBoard>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<dashBoard>
<section alias="StartupSettingsDashboardSection">
<areas>
<area>settings</area>
@@ -13,7 +14,7 @@
</control>
</tab>
</section>
<section alias="StartupDeveloperDashboardSection">
<areas>
<area>developer</area>
@@ -26,7 +27,11 @@
views/dashboard/developer/developerdashboardvideos.html
</control>
</tab>
<tab caption="Examine Management">
<control>/umbraco/dashboard/ExamineManagement.ascx</control>
</tab>
</section>
<section alias="StartupMediaDashboardSection">
<areas>
<area>media</area>
@@ -51,6 +56,7 @@
</control>
</tab>
</section>
<section alias="StartupDashboardSection">
<access>
<deny>translator</deny>
@@ -63,11 +69,15 @@
<grant>admin</grant>
</access>
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/startupdashboardintro.html
views/dashboard/startupdashboardintro.html
</control>
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/startupdashboardkits.html
<access><deny>editor</deny><deny>writer</deny></access></control>
<access>
<deny>editor</deny>
<deny>writer</deny>
</access>
</control>
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/startupdashboardvideos.html
</control>
@@ -81,6 +91,7 @@
</control>
</tab>
</section>
<section alias="StartupMemberDashboardSection">
<areas>
<area>member</area>
@@ -97,17 +108,4 @@
</control>
</tab>
</section>
<section alias="ExamineManagement">
<areas>
<area>developer</area>
</areas>
<tab caption="Examine Management">
<control>/umbraco/dashboard/ExamineManagement.ascx</control>
</tab>
</section>
<<<<<<< HEAD
=======
>>>>>>> d689ad488c8ef902054b47389a65412edf59c4e7
</dashBoard>

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using umbraco.BusinessLogic;
using Umbraco.Web.Mvc;
namespace Umbraco.Web.Editors
{
/// <summary>
/// The API controller used for getting log history
/// </summary>
[PluginController("UmbracoApi")]
public class LogController : UmbracoAuthorizedJsonController
{
public IEnumerable<LogItem> GetEntityLog([FromUri] int id)
{
return Log.Instance.GetLogItems(id);
}
public IEnumerable<LogItem> GetUserLog([FromUri] string logType, [FromUri] DateTime sinceDate)
{
if (sinceDate == null)
sinceDate = DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0, 0));
var u = new User(Security.CurrentUser);
return Log.Instance.GetLogItems(u, (LogTypes)Enum.Parse(typeof(LogTypes), logType), sinceDate);
}
public IEnumerable<LogItem> GetLog([FromUri] string logType, DateTime sinceDate)
{
if (sinceDate == null)
sinceDate = DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0, 0));
return Log.Instance.GetLogItems( (LogTypes)Enum.Parse(typeof(LogTypes), logType), sinceDate);
}
}
}

View File

@@ -303,6 +303,7 @@
<Compile Include="Editors\DashboardController.cs" />
<Compile Include="Editors\DataTypeController.cs" />
<Compile Include="Editors\DataTypeValidateAttribute.cs" />
<Compile Include="Editors\LogController.cs" />
<Compile Include="Editors\MacroController.cs" />
<Compile Include="Models\ContentEditing\MacroParameter.cs" />
<Compile Include="Models\ContentEditing\UmbracoEntityTypes.cs" />

View File

@@ -1,6 +1,6 @@
using System;
using System.Text;
using System.Xml;
using umbraco.BasePages;
using umbraco.BusinessLogic;
@@ -10,7 +10,7 @@ namespace umbraco.js
{
protected void Page_Load(object sender, EventArgs e)
{
Response.ContentType = "text/javascript";
Response.ContentType = "application/json";
User u = base.getUser();
if(u == null)
return;
@@ -18,29 +18,48 @@ namespace umbraco.js
XmlDocument all = ui.getLanguageFile(lang);
if(all == null)
return;
Response.Write("\nvar uiKeys = new Array();\n");
StringBuilder sb = new StringBuilder();
sb.Append("{");
foreach(XmlNode x in all.DocumentElement.ChildNodes)
{
if(x == null)
continue;
foreach(XmlNode key in x.ChildNodes)
{
if (key.FirstChild == null || string.IsNullOrEmpty(key.FirstChild.Value))
continue;
XmlNode n1 = x.Attributes.GetNamedItem("alias");
if(n1 == null)
continue;
XmlNode n2 = key.Attributes.GetNamedItem("alias");
if(n2 == null)
continue;
string _tempKey = string.Format("{0}_{1}", n1.Value, n2.Value);
sb.Append("\n");
for (int i = 0; i < x.ChildNodes.Count; i++)
{
sb.Append("\n");
XmlNode key = x.ChildNodes[i];
if (key.FirstChild == null || string.IsNullOrEmpty(key.FirstChild.Value))
continue;
XmlNode n1 = x.Attributes.GetNamedItem("alias");
if (n1 == null)
continue;
XmlNode n2 = key.Attributes.GetNamedItem("alias");
if (n2 == null)
continue;
string _tempKey = string.Format("{0}_{1}", n1.Value, n2.Value);
// we need to remove linie breaks as they can't break js
string tmpStr = key.FirstChild.Value.Replace("\\", "\\\\").Replace("'", "\\'").Replace("\r", "").Replace("\n", "");
Response.Write(string.Format("uiKeys['{0}'] = '{1}';\n", _tempKey, tmpStr));
}
string tmpStr = key.FirstChild.Value.Replace("\\", "\\\\").Replace("\"", "'").Replace("\r", "").Replace("\n", "");
sb.Append("\"" + _tempKey + "\": \"" + tmpStr + "\",");
}
}
sb.Remove(sb.Length - 1, 1);
sb.Append("}");
Response.Write(sb.ToString());
}
#region Web Form Designer generated code