Merge branch '7.0.0' of https://github.com/umbraco/Umbraco-CMS into 7.0.0
This commit is contained in:
@@ -34,16 +34,28 @@ function authResource($q, $http, umbRequestHelper, angularHelper) {
|
||||
"PostLogout")));
|
||||
},
|
||||
|
||||
/** Sends a request to the server to check if the current cookie value is valid for the user */
|
||||
isAuthenticated: function () {
|
||||
/** Sends a request to the server to get the current user details, will return a 401 if the user is not logged in */
|
||||
getCurrentUser: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"authenticationApiBaseUrl",
|
||||
"GetCurrentUser")),
|
||||
'Server call failed for checking authorization');
|
||||
}
|
||||
'Server call failed for getting current user');
|
||||
},
|
||||
|
||||
/** Checks if the user is logged in or not - does not return 401 or 403 */
|
||||
isAuthenticated: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"authenticationApiBaseUrl",
|
||||
"IsAuthenticated")),
|
||||
'Server call failed for checking authentication');
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.memberResource#getByLogin
|
||||
* @name umbraco.resources.memberResource#getByKey
|
||||
* @methodOf umbraco.resources.memberResource
|
||||
*
|
||||
* @description
|
||||
@@ -34,7 +34,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* memberResource.getByLogin("tom")
|
||||
* memberResource.getByKey("0000-0000-000-00000-000")
|
||||
* .then(function(member) {
|
||||
* var mymember = member;
|
||||
* alert('its here!');
|
||||
@@ -45,20 +45,20 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object containing the member item.
|
||||
*
|
||||
*/
|
||||
getByLogin: function (loginName) {
|
||||
getByKey: function (key) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetByLogin",
|
||||
[{ loginName: loginName }])),
|
||||
'Failed to retreive data for member id ' + loginName);
|
||||
"GetByKey",
|
||||
[{ key: key }])),
|
||||
'Failed to retreive data for member id ' + key);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.memberResource#deleteByLogin
|
||||
* @name umbraco.resources.memberResource#deleteByKey
|
||||
* @methodOf umbraco.resources.memberResource
|
||||
*
|
||||
* @description
|
||||
@@ -66,7 +66,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* memberResource.deleteByLogin(1234)
|
||||
* memberResource.deleteByKey("0000-0000-000-00000-000")
|
||||
* .then(function() {
|
||||
* alert('its gone!');
|
||||
* });
|
||||
@@ -76,14 +76,14 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
deleteByLogin: function (id) {
|
||||
deleteByKey: function (key) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.delete(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"DeleteById",
|
||||
[{ id: id }])),
|
||||
'Failed to delete item ' + id);
|
||||
"DeleteByKey",
|
||||
[{ key: key }])),
|
||||
'Failed to delete item ' + key);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,30 +53,20 @@ angular.module('umbraco.services')
|
||||
|
||||
return {
|
||||
|
||||
/** Internal method to display the login dialog */
|
||||
_showLoginDialog: function () {
|
||||
openLoginDialog();
|
||||
},
|
||||
|
||||
/** Returns a promise, sends a request to the server to check if the current cookie is authorized */
|
||||
isAuthenticated: function (args) {
|
||||
|
||||
return authResource.isAuthenticated()
|
||||
.then(function(data) {
|
||||
|
||||
//note, this can return null if they are not authenticated
|
||||
if (!data) {
|
||||
throw "Not authenticated";
|
||||
}
|
||||
else {
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId };
|
||||
|
||||
if (args.broadcastEvent) {
|
||||
//broadcast a global event, will inform listening controllers to load in the user specific data
|
||||
$rootScope.$broadcast("authenticated", result);
|
||||
}
|
||||
|
||||
currentUser = data;
|
||||
currentUser.avatar = 'http://www.gravatar.com/avatar/' + data.emailHash + '?s=40&d=404';
|
||||
return result;
|
||||
}
|
||||
});
|
||||
isAuthenticated: function () {
|
||||
//if we've got a current user then just return true
|
||||
if (currentUser) {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve(true);
|
||||
return deferred.promise;
|
||||
}
|
||||
return authResource.isAuthenticated();
|
||||
},
|
||||
|
||||
/** Returns a promise, sends a request to the server to validate the credentials */
|
||||
@@ -97,6 +87,7 @@ angular.module('umbraco.services')
|
||||
});
|
||||
},
|
||||
|
||||
/** Logs the user out and redirects to the login page */
|
||||
logout: function () {
|
||||
return authResource.performLogout()
|
||||
.then(function (data) {
|
||||
@@ -107,14 +98,38 @@ angular.module('umbraco.services')
|
||||
//broadcast a global event
|
||||
$rootScope.$broadcast("notAuthenticated");
|
||||
|
||||
openLoginDialog();
|
||||
$location.path("/login").search({check: false});
|
||||
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
/** Returns the current user object, if null then calls to authenticated or authenticate must be called */
|
||||
getCurrentUser: function () {
|
||||
return currentUser;
|
||||
/** Returns the current user object in a promise */
|
||||
getCurrentUser: function (args) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
if (!currentUser) {
|
||||
authResource.getCurrentUser()
|
||||
.then(function(data) {
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId };
|
||||
|
||||
if (args.broadcastEvent) {
|
||||
//broadcast a global event, will inform listening controllers to load in the user specific data
|
||||
$rootScope.$broadcast("authenticated", result);
|
||||
}
|
||||
|
||||
currentUser = data;
|
||||
currentUser.avatar = 'http://www.gravatar.com/avatar/' + data.emailHash + '?s=40&d=404';
|
||||
deferred.resolve(currentUser);
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
deferred.resolve(currentUser);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,15 +1,62 @@
|
||||
app.config(function ($routeProvider) {
|
||||
|
||||
/** This checks if the user is authenticated for a route and what the isRequired is set to.
|
||||
Depending on whether isRequired = true, it first check if the user is authenticated and will resolve successfully
|
||||
otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected
|
||||
path that is resolved from this method and prevent default (prevent the route from executing) */
|
||||
var checkAuth = function(isRequired) {
|
||||
return {
|
||||
isAuthenticated: function ($q, userService, $route) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
//don't need to check if we've redirected to login and we've already checked auth
|
||||
if (!$route.current.params.section && $route.current.params.check === false) {
|
||||
deferred.resolve(true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
userService.isAuthenticated()
|
||||
.then(function () {
|
||||
if (isRequired) {
|
||||
//this will resolve successfully so the route will continue
|
||||
deferred.resolve(true);
|
||||
}
|
||||
else {
|
||||
deferred.reject({ path: "/" });
|
||||
}
|
||||
}, function () {
|
||||
if (isRequired) {
|
||||
//the check=false is checked above so that we don't have to make another http call to check
|
||||
//if they are logged in since we already know they are not.
|
||||
deferred.reject({ path: "/login", search: { check: false } });
|
||||
}
|
||||
else {
|
||||
//this will resolve successfully so the route will continue
|
||||
deferred.resolve(true);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$routeProvider
|
||||
.when('/login', {
|
||||
templateUrl: 'views/common/login.html',
|
||||
//ensure auth is *not* required so it will redirect to /content otherwise
|
||||
resolve: checkAuth(false)
|
||||
})
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default" || rp.section === "")
|
||||
if (rp.section.toLowerCase() === "default" || rp.section.toLowerCase() === "umbraco" || rp.section === "")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/dashboard.html';
|
||||
}
|
||||
},
|
||||
resolve: checkAuth(true)
|
||||
})
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
@@ -18,7 +65,8 @@ app.config(function ($routeProvider) {
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
},
|
||||
resolve: checkAuth(true)
|
||||
})
|
||||
.when('/:section/:method', {
|
||||
templateUrl: function(rp) {
|
||||
@@ -32,7 +80,8 @@ app.config(function ($routeProvider) {
|
||||
// dashboards (as tabs if we wanted) and each tab could actually be a route link to one of these views?
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}
|
||||
},
|
||||
resolve: checkAuth(true)
|
||||
})
|
||||
.when('/:section/:tree/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
@@ -43,9 +92,10 @@ app.config(function ($routeProvider) {
|
||||
//we don't need to put views into section folders since theoretically trees
|
||||
// could be moved among sections, we only need folders for specific trees.
|
||||
return 'views/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
},
|
||||
resolve: checkAuth(true)
|
||||
})
|
||||
.otherwise({ redirectTo: '/content' });
|
||||
.otherwise({ redirectTo: '/login' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
@@ -53,10 +103,28 @@ app.config(function ($routeProvider) {
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', '$log', '$rootScope', function (userService, $log, $rootScope) {
|
||||
app.run(['userService', '$log', '$rootScope', '$location', function (userService, $log, $rootScope, $location) {
|
||||
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
var firstRun = true;
|
||||
|
||||
/** when we have a successful first route that is not the login page - meaning the user is authenticated
|
||||
we'll get the current user from the user service and ensure it broadcasts it's events. If the route
|
||||
is successful from after a login then this will not actually do anything since the authenticated event would
|
||||
have alraedy fired, but if the user is loading the angularjs app for the first time and they are already authenticated
|
||||
then this is when the authenticated event will be fired.
|
||||
*/
|
||||
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
|
||||
if (firstRun && !$location.url().toLowerCase().startsWith("/login")) {
|
||||
firstRun = false;
|
||||
userService.getCurrentUser({ broadcastEvent: true });
|
||||
}
|
||||
});
|
||||
|
||||
/** When the route change is rejected - based on checkAuth - we'll prevent the rejected route from executing including
|
||||
wiring up it's controller, etc... and then redirect to the rejected URL. */
|
||||
$rootScope.$on('$routeChangeError', function (event, current, previous, rejection) {
|
||||
event.preventDefault();
|
||||
$location.path(rejection.path).search(rejection.search);
|
||||
});
|
||||
|
||||
userService.isAuthenticated({broadcastEvent: true});
|
||||
}]);
|
||||
|
||||
@@ -5,9 +5,9 @@ angular.module("umbraco")
|
||||
$scope.history = historyService.current;
|
||||
|
||||
$scope.logout = function () {
|
||||
userService.logout();
|
||||
$scope.hide();
|
||||
$location.path("/");
|
||||
userService.logout().then(function() {
|
||||
$scope.hide();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.gotoHistory = function (link) {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/** This controller is simply here to launch the login dialog when the route is explicitly changed to /login */
|
||||
angular.module('umbraco').controller("Umbraco.LoginController", function ($scope, userService, $location) {
|
||||
|
||||
userService._showLoginDialog();
|
||||
|
||||
//when a user is authorized redirect - this will only be handled here when we are actually on the /login route
|
||||
$scope.$on("authenticated", function(evt, data) {
|
||||
$location.path("/").search("");
|
||||
});
|
||||
|
||||
});
|
||||
3
src/Umbraco.Web.UI.Client/src/views/common/login.html
Normal file
3
src/Umbraco.Web.UI.Client/src/views/common/login.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<div ng-controller="Umbraco.LoginController">
|
||||
|
||||
</div>
|
||||
@@ -8,7 +8,7 @@
|
||||
* The main application controller
|
||||
*
|
||||
*/
|
||||
function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, notificationsService, userService, navigationService, legacyJsLoader) {
|
||||
function MainController($scope, $location, $routeParams, $rootScope, $timeout, $http, $log, notificationsService, userService, navigationService, legacyJsLoader) {
|
||||
|
||||
var legacyTreeJsLoaded = false;
|
||||
|
||||
@@ -78,6 +78,12 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log,
|
||||
$scope.authenticated = data.authenticated;
|
||||
$scope.user = data.user;
|
||||
|
||||
//if the user has changed we need to redirect to the root so they don't try to continue editing the
|
||||
//last item in the URL
|
||||
if (data.lastUserId && data.lastUserId !== data.user.id) {
|
||||
$location.path("/").search("");
|
||||
}
|
||||
|
||||
//var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404";
|
||||
//$http.jsonp(url).then(function(response){
|
||||
// $log.log("found: " + response);
|
||||
|
||||
@@ -13,7 +13,7 @@ function MemberDeleteController($scope, memberResource, treeService, navigationS
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
memberResource.deleteByLogin($scope.currentNode.id).then(function () {
|
||||
memberResource.deleteByKey($scope.currentNode.id).then(function () {
|
||||
$scope.currentNode.loading = false;
|
||||
|
||||
//TODO: Need to sync tree, etc...
|
||||
|
||||
@@ -22,7 +22,7 @@ function MemberEditController($scope, $routeParams, $q, $timeout, $window, membe
|
||||
}
|
||||
else {
|
||||
//we are editing so get the content item from the server
|
||||
memberResource.getByLogin($routeParams.id)
|
||||
memberResource.getByKey($routeParams.id)
|
||||
.then(function(data) {
|
||||
$scope.loaded = true;
|
||||
$scope.content = data;
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
function booleanEditorController($scope, $rootScope, assetsService) {
|
||||
$scope.renderModel = {
|
||||
value: false
|
||||
};
|
||||
if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) {
|
||||
$scope.renderModel.value = true;
|
||||
|
||||
function setupViewModel() {
|
||||
$scope.renderModel = {
|
||||
value: false
|
||||
};
|
||||
if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) {
|
||||
$scope.renderModel.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
setupViewModel();
|
||||
|
||||
$scope.$watch("renderModel.value", function (newVal) {
|
||||
$scope.model.value = newVal === true ? "1" : "0";
|
||||
});
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
setupViewModel();
|
||||
};
|
||||
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.Editors.BooleanController", booleanEditorController);
|
||||
@@ -1,22 +1,27 @@
|
||||
angular.module("umbraco").controller("Umbraco.Editors.CheckboxListController",
|
||||
function($scope) {
|
||||
|
||||
$scope.selectedItems = [];
|
||||
|
||||
|
||||
if (!angular.isObject($scope.model.config.items)) {
|
||||
throw "The model.config.items property must be either a dictionary";
|
||||
}
|
||||
|
||||
//now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set
|
||||
// to "" gets selected by default
|
||||
if ($scope.model.value === null || $scope.model.value === undefined) {
|
||||
$scope.model.value = [];
|
||||
|
||||
function setupViewModel() {
|
||||
$scope.selectedItems = [];
|
||||
|
||||
//now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set
|
||||
// to "" gets selected by default
|
||||
if ($scope.model.value === null || $scope.model.value === undefined) {
|
||||
$scope.model.value = [];
|
||||
}
|
||||
|
||||
for (var i in $scope.model.config.items) {
|
||||
var isChecked = _.contains($scope.model.value, i);
|
||||
$scope.selectedItems.push({ checked: isChecked, key: i, val: $scope.model.config.items[i] });
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in $scope.model.config.items) {
|
||||
var isChecked = _.contains($scope.model.value, i);
|
||||
$scope.selectedItems.push({ checked: isChecked, key: i, val: $scope.model.config.items[i] });
|
||||
}
|
||||
setupViewModel();
|
||||
|
||||
|
||||
//update the model when the items checked changes
|
||||
$scope.$watch("selectedItems", function(newVal, oldVal) {
|
||||
@@ -29,5 +34,12 @@ angular.module("umbraco").controller("Umbraco.Editors.CheckboxListController",
|
||||
}
|
||||
|
||||
}, true);
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
setupViewModel();
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -1,75 +1,84 @@
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.GoogleMapsController",
|
||||
function ($rootScope, $scope, notificationsService, dialogService, assetsService, $log, $timeout) {
|
||||
|
||||
assetsService.loadJs('http://www.google.com/jsapi')
|
||||
.then(function(){
|
||||
google.load("maps", "3",
|
||||
{
|
||||
callback: initMap,
|
||||
other_params: "sensor=false"
|
||||
|
||||
assetsService.loadJs('http://www.google.com/jsapi')
|
||||
.then(function () {
|
||||
google.load("maps", "3",
|
||||
{
|
||||
callback: initMap,
|
||||
other_params: "sensor=false"
|
||||
});
|
||||
});
|
||||
|
||||
function initMap() {
|
||||
//Google maps is available and all components are ready to use.
|
||||
var valueArray = $scope.model.value.split(',');
|
||||
var latLng = new google.maps.LatLng(valueArray[0], valueArray[1]);
|
||||
var mapDiv = document.getElementById($scope.model.alias + '_map');
|
||||
var mapOptions = {
|
||||
zoom: $scope.model.config.zoom,
|
||||
center: latLng,
|
||||
mapTypeId: google.maps.MapTypeId[$scope.model.config.mapType]
|
||||
};
|
||||
var geocoder = new google.maps.Geocoder();
|
||||
var map = new google.maps.Map(mapDiv, mapOptions);
|
||||
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
position: latLng,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
google.maps.event.addListener(map, 'click', function (event) {
|
||||
|
||||
dialogService.mediaPicker({
|
||||
scope: $scope, callback: function (data) {
|
||||
var image = data.selection[0].src;
|
||||
|
||||
var latLng = event.latLng;
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
icon: image,
|
||||
position: latLng,
|
||||
draggable: true
|
||||
});
|
||||
});
|
||||
|
||||
function initMap(){
|
||||
//Google maps is available and all components are ready to use.
|
||||
var valueArray = $scope.model.value.split(',');
|
||||
var latLng = new google.maps.LatLng(valueArray[0], valueArray[1]);
|
||||
var mapDiv = document.getElementById($scope.model.alias + '_map');
|
||||
var mapOptions = {
|
||||
zoom: $scope.model.config.zoom,
|
||||
center: latLng,
|
||||
mapTypeId: google.maps.MapTypeId[$scope.model.config.mapType]
|
||||
};
|
||||
var geocoder = new google.maps.Geocoder();
|
||||
var map = new google.maps.Map(mapDiv, mapOptions);
|
||||
google.maps.event.addListener(marker, "dragend", function (e) {
|
||||
var newLat = marker.getPosition().lat();
|
||||
var newLng = marker.getPosition().lng();
|
||||
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
position: latLng,
|
||||
draggable: true
|
||||
});
|
||||
codeLatLng(marker.getPosition(), geocoder);
|
||||
|
||||
google.maps.event.addListener(map, 'click', function(event) {
|
||||
//set the model value
|
||||
$scope.model.vvalue = newLat + "," + newLng;
|
||||
});
|
||||
|
||||
dialogService.mediaPicker({scope: $scope, callback: function(data){
|
||||
var image = data.selection[0].src;
|
||||
|
||||
var latLng = event.latLng;
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
icon: image,
|
||||
position: latLng,
|
||||
draggable: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
google.maps.event.addListener(marker, "dragend", function(e){
|
||||
var newLat = marker.getPosition().lat();
|
||||
var newLng = marker.getPosition().lng();
|
||||
$('a[data-toggle="tab"]').on('shown', function (e) {
|
||||
google.maps.event.trigger(map, 'resize');
|
||||
});
|
||||
}
|
||||
|
||||
codeLatLng(marker.getPosition(), geocoder);
|
||||
|
||||
//set the model value
|
||||
$scope.model.vvalue = newLat + "," + newLng;
|
||||
});
|
||||
|
||||
}});
|
||||
});
|
||||
|
||||
$('a[data-toggle="tab"]').on('shown', function (e) {
|
||||
google.maps.event.trigger(map, 'resize');
|
||||
});
|
||||
}
|
||||
|
||||
function codeLatLng(latLng, geocoder) {
|
||||
geocoder.geocode({'latLng': latLng},
|
||||
function(results, status) {
|
||||
if (status == google.maps.GeocoderStatus.OK) {
|
||||
var location = results[0].formatted_address;
|
||||
function codeLatLng(latLng, geocoder) {
|
||||
geocoder.geocode({ 'latLng': latLng },
|
||||
function (results, status) {
|
||||
if (status == google.maps.GeocoderStatus.OK) {
|
||||
var location = results[0].formatted_address;
|
||||
$rootScope.$apply(function () {
|
||||
notificationsService.success("Peter just went to: ", location);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
initMap();
|
||||
};
|
||||
});
|
||||
@@ -1,54 +1,68 @@
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
angular.module('umbraco').controller("Umbraco.Editors.MediaPickerController",
|
||||
function($rootScope, $scope, dialogService, mediaResource, imageHelper, $log){
|
||||
|
||||
|
||||
$scope.images = [];
|
||||
$scope.ids = [];
|
||||
angular.module('umbraco').controller("Umbraco.Editors.MediaPickerController",
|
||||
function($rootScope, $scope, dialogService, mediaResource, imageHelper, $log) {
|
||||
|
||||
if($scope.model.value){
|
||||
$scope.ids = $scope.model.value.split(',');
|
||||
|
||||
mediaResource.getByIds($scope.ids).then(function(medias){
|
||||
//img.media = media;
|
||||
$(medias).each(function(i, media){
|
||||
//shortcuts
|
||||
//TODO, do something better then this for searching
|
||||
var img = {};
|
||||
img.src = imageHelper.getImagePropertyValue({imageModel: media});
|
||||
img.thumbnail = imageHelper.getThumbnailFromPath(img.src);
|
||||
$scope.images.push(img);
|
||||
});
|
||||
});
|
||||
}
|
||||
function setupViewModel() {
|
||||
$scope.images = [];
|
||||
$scope.ids = [];
|
||||
|
||||
$scope.remove = function(index){
|
||||
$scope.images.splice(index, 1);
|
||||
$scope.ids.splice(index, 1);
|
||||
$scope.sync();
|
||||
};
|
||||
if ($scope.model.value) {
|
||||
$scope.ids = $scope.model.value.split(',');
|
||||
|
||||
$scope.add = function(){
|
||||
dialogService.mediaPicker({multipicker:true, callback: function(data){
|
||||
$(data.selection).each(function(i, media){
|
||||
//shortcuts
|
||||
//TODO, do something better then this for searching
|
||||
mediaResource.getByIds($scope.ids).then(function (medias) {
|
||||
//img.media = media;
|
||||
_.each(medias, function (media, i) {
|
||||
//shortcuts
|
||||
//TODO, do something better then this for searching
|
||||
var img = {};
|
||||
img.src = imageHelper.getImagePropertyValue({ imageModel: media });
|
||||
img.thumbnail = imageHelper.getThumbnailFromPath(img.src);
|
||||
$scope.images.push(img);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var img = {};
|
||||
img.id = media.id;
|
||||
img.src = imageHelper.getImagePropertyValue({imageModel: media});
|
||||
img.thumbnail = imageHelper.getThumbnailFromPath(img.src);
|
||||
$scope.images.push(img);
|
||||
$scope.ids.push(img.id);
|
||||
});
|
||||
setupViewModel();
|
||||
|
||||
$scope.sync();
|
||||
}});
|
||||
};
|
||||
$scope.remove = function(index) {
|
||||
$scope.images.splice(index, 1);
|
||||
$scope.ids.splice(index, 1);
|
||||
$scope.sync();
|
||||
};
|
||||
|
||||
$scope.sync = function(){
|
||||
$scope.model.value = $scope.ids.join();
|
||||
};
|
||||
$scope.add = function() {
|
||||
dialogService.mediaPicker({
|
||||
multipicker: true,
|
||||
callback: function(data) {
|
||||
_.each(data.selection, function(media, i) {
|
||||
//shortcuts
|
||||
//TODO, do something better then this for searching
|
||||
|
||||
});
|
||||
var img = {};
|
||||
img.id = media.id;
|
||||
img.src = imageHelper.getImagePropertyValue({ imageModel: media });
|
||||
img.thumbnail = imageHelper.getThumbnailFromPath(img.src);
|
||||
$scope.images.push(img);
|
||||
$scope.ids.push(img.id);
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.sync = function() {
|
||||
$scope.model.value = $scope.ids.join();
|
||||
};
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
setupViewModel();
|
||||
};
|
||||
|
||||
});
|
||||
@@ -32,65 +32,79 @@ angular.module("umbraco")
|
||||
var plugins = "code";
|
||||
|
||||
assetsService.loadJs("lib/tinymce/tinymce.min.js", $scope).then(function () {
|
||||
//we need to add a timeout here, to force a redraw so TinyMCE can find
|
||||
//the elements needed
|
||||
$timeout(function () {
|
||||
tinymce.DOM.events.domLoaded = true;
|
||||
tinymce.init({
|
||||
mode: "exact",
|
||||
elements: $scope.model.alias + "_rte",
|
||||
skin: "umbraco",
|
||||
plugins: plugins,
|
||||
valid_elements: validElements,
|
||||
menubar: false,
|
||||
statusbar: false,
|
||||
height: 340,
|
||||
toolbar: toolbar,
|
||||
setup: function (editor) {
|
||||
|
||||
//We need to listen on multiple things here because of the nature of tinymce, it doesn't
|
||||
//fire events when you think!
|
||||
//The change event doesn't fire when content changes, only when cursor points are changed and undo points
|
||||
//are created. the blur event doesn't fire if you insert content into the editor with a button and then
|
||||
//press save.
|
||||
//We have a couple of options, one is to do a set timeout and check for isDirty on the editor, or we can
|
||||
//listen to both change and blur and also on our own 'saving' event. I think this will be best because a
|
||||
//timer might end up using unwanted cpu and we'd still have to listen to our saving event in case they clicked
|
||||
//save before the timeout elapsed.
|
||||
editor.on('change', function (e) {
|
||||
angularHelper.safeApply($scope, function() {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
});
|
||||
editor.on('blur', function (e) {
|
||||
angularHelper.safeApply($scope, function () {
|
||||
|
||||
/** Loads in the editor */
|
||||
function loadTinyMce() {
|
||||
|
||||
//we need to add a timeout here, to force a redraw so TinyMCE can find
|
||||
//the elements needed
|
||||
$timeout(function () {
|
||||
tinymce.DOM.events.domLoaded = true;
|
||||
tinymce.init({
|
||||
mode: "exact",
|
||||
elements: $scope.model.alias + "_rte",
|
||||
skin: "umbraco",
|
||||
plugins: plugins,
|
||||
valid_elements: validElements,
|
||||
menubar: false,
|
||||
statusbar: false,
|
||||
height: 340,
|
||||
toolbar: toolbar,
|
||||
setup: function (editor) {
|
||||
|
||||
//We need to listen on multiple things here because of the nature of tinymce, it doesn't
|
||||
//fire events when you think!
|
||||
//The change event doesn't fire when content changes, only when cursor points are changed and undo points
|
||||
//are created. the blur event doesn't fire if you insert content into the editor with a button and then
|
||||
//press save.
|
||||
//We have a couple of options, one is to do a set timeout and check for isDirty on the editor, or we can
|
||||
//listen to both change and blur and also on our own 'saving' event. I think this will be best because a
|
||||
//timer might end up using unwanted cpu and we'd still have to listen to our saving event in case they clicked
|
||||
//save before the timeout elapsed.
|
||||
editor.on('change', function (e) {
|
||||
angularHelper.safeApply($scope, function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
});
|
||||
editor.on('blur', function (e) {
|
||||
angularHelper.safeApply($scope, function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
});
|
||||
var unsubscribe = $scope.$on("saving", function () {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
});
|
||||
var unsubscribe = $scope.$on("saving", function() {
|
||||
$scope.model.value = editor.getContent();
|
||||
});
|
||||
|
||||
//when the element is disposed we need to unsubscribe!
|
||||
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
|
||||
// element might still be there even after the modal has been hidden.
|
||||
$element.bind('$destroy', function () {
|
||||
unsubscribe();
|
||||
});
|
||||
//when the element is disposed we need to unsubscribe!
|
||||
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
|
||||
// element might still be there even after the modal has been hidden.
|
||||
$element.bind('$destroy', function () {
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
//Create the insert media plugin
|
||||
tinyMceService.createMediaPicker(editor, $scope);
|
||||
//Create the insert media plugin
|
||||
tinyMceService.createMediaPicker(editor, $scope);
|
||||
|
||||
//Create the insert icon plugin
|
||||
tinyMceService.createInsertEmbeddedMedia(editor, $scope);
|
||||
//Create the insert icon plugin
|
||||
tinyMceService.createInsertEmbeddedMedia(editor, $scope);
|
||||
|
||||
//Create the insert macro plugin
|
||||
tinyMceService.createInsertMacro(editor, $scope);
|
||||
//Create the insert macro plugin
|
||||
tinyMceService.createInsertMacro(editor, $scope);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
}, 1);
|
||||
}
|
||||
|
||||
loadTinyMce();
|
||||
|
||||
//here we declare a special method which will be called whenever the value has changed from the server
|
||||
//this is instead of doing a watch on the model.value = faster
|
||||
$scope.model.onValueChanged = function (newVal, oldVal) {
|
||||
//update the display val again if it has changed from the server
|
||||
loadTinyMce();
|
||||
};
|
||||
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user