diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbcontentname.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbcontentname.directive.js new file mode 100644 index 0000000000..5ccfeb047b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/editors/umbcontentname.directive.js @@ -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..."; + } + }; + } + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/localize.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/localize.directive.js new file mode 100644 index 0000000000..70c412465b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/localize.directive.js @@ -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); + } + }; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/umbcontentname.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/umbcontentname.directive.js deleted file mode 100644 index 3245950795..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/directives/umbcontentname.directive.js +++ /dev/null @@ -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); - } - }; - }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js new file mode 100644 index 0000000000..ad74cd44e7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js @@ -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 + *
+         * logResource.getEntityLog(1234)
+         *    .then(function(log) {
+         *        alert('its here!');
+         *    });
+         * 
+ * + * @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 + *
+         * logResource.getUserLog("save", new Date())
+         *    .then(function(log) {
+         *        alert('its here!');
+         *    });
+         * 
+ * + * @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 + *
+         * logResource.getLog("save", new Date())
+         *    .then(function(log) {
+         *        alert('its here!');
+         *    });
+         * 
+ * + * @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); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js b/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js new file mode 100644 index 0000000000..b7b7b99b98 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js @@ -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; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index e74c0ddc20..b5396efc13 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -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} diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index e5187da1c6..a59a4da001 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -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; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html index bef16e2b72..d2d2113ad0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html @@ -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"> diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js index 8d04c4531c..28746df55e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.edit.controller.js @@ -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; }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/content/edit.html b/src/Umbraco.Web.UI.Client/src/views/content/edit.html index 18cdfebb66..9bdc494d50 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/edit.html @@ -13,13 +13,18 @@
+
-
- Preview page - data-hotkey="ctrl+s">Preview page +
+
+ +
+ Publish diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js index 09f0d64a82..74149da018 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js @@ -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); diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/StartupDashboardLastEdits.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/StartupDashboardLastEdits.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Umbraco.Web.UI.Client/src/views/directives/umb-content-name.html b/src/Umbraco.Web.UI.Client/src/views/directives/umb-content-name.html index d98664bbf0..49d53e3693 100644 --- a/src/Umbraco.Web.UI.Client/src/views/directives/umb-content-name.html +++ b/src/Umbraco.Web.UI.Client/src/views/directives/umb-content-name.html @@ -2,8 +2,15 @@ -

{{model}}

- {{model}} + + diff --git a/src/Umbraco.Web.UI/config/Dashboard.Release.config b/src/Umbraco.Web.UI/config/Dashboard.Release.config index d393286ed8..0689c584d5 100644 --- a/src/Umbraco.Web.UI/config/Dashboard.Release.config +++ b/src/Umbraco.Web.UI/config/Dashboard.Release.config @@ -85,6 +85,7 @@ +
member @@ -110,4 +111,5 @@ /umbraco/dashboard/ExamineManagement.ascx
+ \ No newline at end of file diff --git a/src/Umbraco.Web.UI/config/Dashboard.config b/src/Umbraco.Web.UI/config/Dashboard.config index 03c15552a6..5eef4294e3 100644 --- a/src/Umbraco.Web.UI/config/Dashboard.config +++ b/src/Umbraco.Web.UI/config/Dashboard.config @@ -1,5 +1,6 @@  +
settings @@ -13,7 +14,7 @@
- +
developer @@ -26,7 +27,11 @@ views/dashboard/developer/developerdashboardvideos.html + + /umbraco/dashboard/ExamineManagement.ascx +
+
media @@ -51,6 +56,7 @@
+
translator @@ -63,11 +69,15 @@ admin - views/dashboard/startupdashboardintro.html + views/dashboard/startupdashboardintro.html views/dashboard/startupdashboardkits.html - editorwriter + + editor + writer + + views/dashboard/startupdashboardvideos.html @@ -81,6 +91,7 @@
+
member @@ -97,17 +108,4 @@
- -
- - developer - - - /umbraco/dashboard/ExamineManagement.ascx - -
-<<<<<<< HEAD -======= - ->>>>>>> d689ad488c8ef902054b47389a65412edf59c4e7
\ No newline at end of file diff --git a/src/Umbraco.Web/Editors/LogController.cs b/src/Umbraco.Web/Editors/LogController.cs new file mode 100644 index 0000000000..8d4b768ee4 --- /dev/null +++ b/src/Umbraco.Web/Editors/LogController.cs @@ -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 +{ + /// + /// The API controller used for getting log history + /// + [PluginController("UmbracoApi")] + public class LogController : UmbracoAuthorizedJsonController + { + public IEnumerable GetEntityLog([FromUri] int id) + { + return Log.Instance.GetLogItems(id); + } + + public IEnumerable 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 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); + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 696a2d185b..852779bc67 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -303,6 +303,7 @@ + diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/js/language.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/js/language.aspx.cs index 234b16181d..90c3878608 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/js/language.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/js/language.aspx.cs @@ -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