384 lines
12 KiB
JavaScript
384 lines
12 KiB
JavaScript
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
angular.module('SOGo.Common', ['ngAnimate', 'ngMessages', 'ngSanitize', 'ngMaterial', 'mdColors'])
|
|
.value('sgSettings', {
|
|
isPopup: document.body.classList.contains('popup'),
|
|
baseURL: function() {
|
|
return ApplicationBaseURL || null;
|
|
},
|
|
resourcesURL: function() {
|
|
return ResourcesURL || null;
|
|
},
|
|
activeUser: function(param) {
|
|
var settings = {
|
|
login: UserLogin || null,
|
|
identification: UserIdentification || null,
|
|
email: UserEmail || null,
|
|
language: UserLanguage || null,
|
|
folderURL: UserFolderURL || null,
|
|
isSuperUser: IsSuperUser || null,
|
|
path: {
|
|
calendar: UserCalendarPath || null,
|
|
contacts: UserContactsPath || null,
|
|
mail: UserMailPath || null,
|
|
preferences: UserPreferencesPath || null,
|
|
administration: (IsSuperUser ? UserAdministrationPath : null),
|
|
help: HelpURL || null,
|
|
logoff: UserLogoffPath || null
|
|
}
|
|
};
|
|
if (param)
|
|
return settings[param];
|
|
else
|
|
return settings;
|
|
},
|
|
minimumSearchLength: function() {
|
|
return angular.isNumber(minimumSearchLength)? minimumSearchLength : 2;
|
|
}
|
|
})
|
|
|
|
.constant('sgColors', {
|
|
selection: [
|
|
'#FFFFFF',
|
|
'#330033',
|
|
'#C0C0C0',
|
|
'#999999',
|
|
'#666666',
|
|
'#333333',
|
|
'#000000',
|
|
'#FFCCCC',
|
|
'#FF6666',
|
|
'#FF0000',
|
|
'#CC0000',
|
|
'#990000',
|
|
'#660000',
|
|
'#330000',
|
|
'#FFCC99',
|
|
'#FF9966',
|
|
'#FF9900',
|
|
'#FF6600',
|
|
'#CC6600',
|
|
'#993300',
|
|
'#663300',
|
|
'#FFFF99',
|
|
'#FFFF66',
|
|
'#FFCC66',
|
|
'#FFCC33',
|
|
'#CC9933',
|
|
'#996633',
|
|
'#663333',
|
|
'#FFFFCC',
|
|
'#FFFF33',
|
|
'#FFFF00',
|
|
'#FFCC00',
|
|
'#999900',
|
|
'#666600',
|
|
'#333300',
|
|
'#CCCCCC',
|
|
'#66FF99',
|
|
'#33FF33',
|
|
'#33CC00',
|
|
'#009900',
|
|
'#006600',
|
|
'#003300',
|
|
'#99FFFF',
|
|
'#33FFFF',
|
|
'#66CCCC',
|
|
'#00CCCC',
|
|
'#339999',
|
|
'#336666',
|
|
'#003333',
|
|
'#CCFFFF',
|
|
'#66FFFF',
|
|
'#33CCFF',
|
|
'#3366FF',
|
|
'#3333FF',
|
|
'#000099',
|
|
'#000066',
|
|
'#CCCCFF',
|
|
'#9999FF',
|
|
'#6666CC',
|
|
'#6633FF',
|
|
'#6600CC',
|
|
'#333399',
|
|
'#330099',
|
|
'#FFCCFF',
|
|
'#FF99FF',
|
|
'#CC66CC',
|
|
'#CC33CC',
|
|
'#993399',
|
|
'#663366',
|
|
'#99FF99'
|
|
]
|
|
})
|
|
|
|
// md break-points values are hard-coded in angular-material/src/core/util/constant.js
|
|
// $mdMedia has a built-in support for those values but can also evaluate others.
|
|
// The following breakpoints match our CSS breakpoints in scss/core/variables.scss
|
|
.constant('sgConstant', {
|
|
'xs' : '(max-width: 599px)' ,
|
|
'gt-xs' : '(min-width: 600px)' ,
|
|
'sm' : '(min-width: 600px) and (max-width: 959px)' ,
|
|
'gt-sm' : '(min-width: 960px)' ,
|
|
'md' : '(min-width: 960px) and (max-width: 1023px)' ,
|
|
'gt-md' : '(min-width: 1024px)' ,
|
|
'lg' : '(min-width: 1024px) and (max-width: 1279px)',
|
|
'gt-lg' : '(min-width: 1280px)' ,
|
|
'xl' : '(min-width: 1920px)' ,
|
|
'print' : 'print'
|
|
})
|
|
|
|
.config(configure)
|
|
|
|
.factory('AuthInterceptor', AuthInterceptor)
|
|
.factory('ErrorInterceptor', ErrorInterceptor);
|
|
|
|
/**
|
|
* @ngInject
|
|
*/
|
|
configure.$inject = ['$animateProvider', '$logProvider', '$compileProvider', '$httpProvider', '$mdThemingProvider', '$mdAriaProvider', '$qProvider'];
|
|
function configure($animateProvider, $logProvider, $compileProvider, $httpProvider, $mdThemingProvider, $mdAriaProvider, $qProvider) {
|
|
// Disabled animation for elements with class ng-animate-disabled
|
|
$animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/);
|
|
|
|
// Accent palette
|
|
$mdThemingProvider.definePalette('sogo-green', {
|
|
'50': 'eaf5e9',
|
|
'100': 'cbe5c8',
|
|
'200': 'aad6a5',
|
|
'300': '88c781',
|
|
'400': '66b86a',
|
|
'500': '56b04c',
|
|
'600': '4da143',
|
|
'700': '388e3c',
|
|
'800': '367d2e',
|
|
'900': '225e1b',
|
|
// 'A100': 'b9f6ca',
|
|
'A100': 'fafafa', // assigned to md-hue-1, equivalent to grey-50 (default background palette)
|
|
'A200': '69f0ae',
|
|
'A400': '00e676',
|
|
'A700': '00c853',
|
|
'contrastDefaultColor': 'dark',
|
|
// 'contrastDarkColors': ['50', '100', '200', 'A100'],
|
|
'contrastLightColors': ['300', '400', '500', '600', '700', '800', '900']
|
|
});
|
|
// Primary palette
|
|
$mdThemingProvider.definePalette('sogo-blue', {
|
|
'50': 'f0faf9',
|
|
'100': 'e1f5f3',
|
|
'200': 'ceebe8',
|
|
'300': 'bfe0dd',
|
|
'400': 'b2d6d3',
|
|
'500': 'a1ccc8',
|
|
'600': '8ebfbb',
|
|
'700': '7db3b0',
|
|
'800': '639997',
|
|
'900': '4d8080',
|
|
'A100': 'd4f7fa',
|
|
'A200': 'c3f5fa',
|
|
'A400': '53e3f0',
|
|
'A700': '00b0c0',
|
|
'contrastDefaultColor': 'light',
|
|
'contrastDarkColors': ['50', '100', '200'],
|
|
// 'contrastLightColors': ['300', '400', '500', '600', '700', '800', '900', 'A100', 'A200', 'A400', 'A700']
|
|
});
|
|
// Background palette
|
|
$mdThemingProvider.definePalette('sogo-paper', {
|
|
'50': 'fcf7f8',
|
|
'100': 'f7f1dc',
|
|
'200': 'ede5ca',
|
|
'300': 'e6d8ba',
|
|
'400': 'e2d2a3',
|
|
'500': 'd6c48d',
|
|
'600': 'baa870',
|
|
'700': '857545',
|
|
'800': '524517',
|
|
'900': '433809',
|
|
'1000': '000000',
|
|
'A100': 'ffffff',
|
|
'A200': 'eeeeee',
|
|
'A400': 'bdbdbd',
|
|
'A700': '616161',
|
|
'contrastDefaultColor': 'dark',
|
|
'contrastLightColors': ['800', '900']
|
|
});
|
|
var greyMap = $mdThemingProvider.extendPalette('grey', {
|
|
'1000': 'baa870' // used as the background color of the busy periods of the attendees editor
|
|
});
|
|
$mdThemingProvider.definePalette('sogo-grey', greyMap);
|
|
// Default theme definition
|
|
$mdThemingProvider.theme('default')
|
|
.primaryPalette('sogo-blue', {
|
|
'default': '900',
|
|
'hue-1': '400',
|
|
'hue-2': '800',
|
|
'hue-3': 'A700'
|
|
})
|
|
.accentPalette('sogo-green', {
|
|
'default': '500',
|
|
// 'hue-1': '200',
|
|
'hue-1': 'A100', // grey-50
|
|
'hue-2': '300',
|
|
'hue-3': 'A700'
|
|
})
|
|
.backgroundPalette('sogo-grey');
|
|
|
|
|
|
// Register custom stylesheet for md-autocomplete
|
|
$mdThemingProvider.registerStyles([
|
|
'.md-autocomplete-suggestions.md-3-line li p {',
|
|
' color: \'{{foreground-2}}\';',
|
|
'}',
|
|
].join(''));
|
|
|
|
// Register custom stylesheet for sgTimepicker
|
|
$mdThemingProvider.registerStyles([
|
|
'.sg-time-selection-indicator.sg-time-selected,',
|
|
'.sg-time-selection-indicator:hover.sg-time-selected,',
|
|
'.sg-time-selection-indicator.md-focus.sg-time-selected {',
|
|
' background: \'{{primary-500}}\';',
|
|
'}',
|
|
'.sg-timepicker-open .sg-timepicker-icon {',
|
|
' color: \'{{primary-900}}\';',
|
|
'}',
|
|
'.sg-timepicker-time,',
|
|
'.sg-timepicker-open .sg-timepicker-input-container {',
|
|
' background: \'{{background-hue-1}}\';',
|
|
'}',
|
|
'.sg-timepicker-input-mask-opaque {',
|
|
' box-shadow: 0 0 0 9999px \'{{background-hue-1}}\';',
|
|
'}',
|
|
].join(''));
|
|
|
|
// Register custom stylesheet for Calendar module
|
|
$mdThemingProvider.registerStyles([
|
|
'[ui-view=calendars] .hours {',
|
|
' color: \'{{primary-700}}\';',
|
|
'}',
|
|
'.attendees .busy {',
|
|
' background-color: \'{{background-1000}}\';',
|
|
'}',
|
|
'.attendees .event {',
|
|
' background-color: \'{{primary-300}}\';',
|
|
'}'
|
|
].join(''));
|
|
|
|
// Register custom stylesheet for Mail module
|
|
$mdThemingProvider.registerStyles([
|
|
'.sg-message-thread {',
|
|
' background-color: \'{{primary-100}}\';',
|
|
'}',
|
|
'.sg-message-thread-first {',
|
|
' background-color: \'{{primary-200}}\';',
|
|
'}',
|
|
].join(''));
|
|
|
|
if (!window.DebugEnabled) {
|
|
// Disable debugging information
|
|
$logProvider.debugEnabled(false);
|
|
$compileProvider.debugInfoEnabled(false);
|
|
// Disable warnings
|
|
$mdAriaProvider.disableWarnings();
|
|
$qProvider.errorOnUnhandledRejections(false);
|
|
// Disable theme generation but keep definition in config (required by mdColors)
|
|
$mdThemingProvider.generateThemesOnDemand(true);
|
|
// Disable theming completely
|
|
//$mdThemingProvider.disableTheming();
|
|
}
|
|
|
|
$httpProvider.interceptors.push('AuthInterceptor');
|
|
$httpProvider.interceptors.push('ErrorInterceptor');
|
|
}
|
|
|
|
function renewTicket($window, $q, $timeout, $injector, response) {
|
|
var deferred, iframe;
|
|
|
|
deferred = $q.defer();
|
|
iframe = angular.element('<iframe class="ng-hide" src="' + $window.UserFolderURL + 'recover"></iframe>');
|
|
|
|
iframe.on('load', function() {
|
|
var $state = $injector.get('$state');
|
|
if (response.config.attempt) {
|
|
// Already attempted once -- reload page
|
|
angular.element($window).off('beforeunload');
|
|
$window.location.href = $window.ApplicationBaseURL + $state.href($state.current);
|
|
deferred.reject();
|
|
}
|
|
else {
|
|
// Once the browser has followed the redirection, send the initial request
|
|
$timeout(function() {
|
|
var $http = $injector.get('$http');
|
|
response.config.attempt = 1;
|
|
$http(response.config).then(function(response) {
|
|
deferred.resolve(response);
|
|
});
|
|
$timeout(iframe.remove, 500);
|
|
}, 100); // Wait before replaying the request
|
|
}
|
|
});
|
|
|
|
document.body.appendChild(iframe[0]);
|
|
|
|
return deferred.promise;
|
|
}
|
|
|
|
/**
|
|
* @ngInject
|
|
*/
|
|
AuthInterceptor.$inject = ['$window', '$q', '$timeout', '$injector'];
|
|
function AuthInterceptor($window, $q, $timeout, $injector) {
|
|
return {
|
|
response: function(response) {
|
|
// When expecting JSON but receiving HTML, assume session has expired and reload page
|
|
var $state;
|
|
if (response && /^application\/json/.test(response.config.headers.Accept) &&
|
|
/^[\n\r ]*<!DOCTYPE html/.test(response.data)) {
|
|
if ($window.usesCASAuthentication) {
|
|
return renewTicket($window, $q, $timeout, $injector, response);
|
|
}
|
|
else {
|
|
$state = $injector.get('$state');
|
|
angular.element($window).off('beforeunload');
|
|
$window.location.href = $window.ApplicationBaseURL + $state.href($state.current);
|
|
return $q.reject();
|
|
}
|
|
}
|
|
return response;
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @ngInject
|
|
*/
|
|
ErrorInterceptor.$inject = ['$rootScope', '$window', '$q', '$timeout', '$injector'];
|
|
function ErrorInterceptor($rootScope, $window, $q, $timeout, $injector) {
|
|
return {
|
|
responseError: function(rejection) {
|
|
var $state;
|
|
if (/^application\/json/.test(rejection.config.headers.Accept)) {
|
|
// Handle CAS ticket renewal
|
|
if ($window.usesCASAuthentication && rejection.status == -1) {
|
|
return renewTicket($window, $q, $timeout, $injector, rejection);
|
|
}
|
|
else if ($window.usesSAML2Authentication && rejection.status == 401 && !$window.recovered) {
|
|
$state = $injector.get('$state');
|
|
angular.element($window).off('beforeunload');
|
|
$window.recovered = true;
|
|
$window.location.href = $window.ApplicationBaseURL + $state.href($state.current);
|
|
}
|
|
else {
|
|
// Broadcast the response error
|
|
$rootScope.$broadcast('http:Error', rejection);
|
|
}
|
|
}
|
|
return $q.reject(rejection);
|
|
}
|
|
};
|
|
}
|
|
|
|
})();
|