mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-08-28 17:57:38 +00:00
(js) New file structure for Angular modules
JavaScript files are now merged by the 'js' Grunt task.
This commit is contained in:
+2
-2
@@ -15,7 +15,7 @@
|
||||
* @desc The factory we'll use to register with Angular.
|
||||
* @return the Acl constructor
|
||||
*/
|
||||
Acl.factory = ['$q', '$timeout', 'sgSettings', 'sgResource', 'sgUser', function($q, $timeout, Settings, Resource, User) {
|
||||
Acl.factory = ['$q', '$timeout', 'sgSettings', 'Resource', 'User', function($q, $timeout, Settings, Resource, User) {
|
||||
angular.extend(Acl, {
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
@@ -30,7 +30,7 @@
|
||||
* @module SOGo.Common
|
||||
* @desc Factory registration of User in Angular module.
|
||||
*/
|
||||
angular.module('SOGo.Common').factory('sgAcl', Acl.factory);
|
||||
angular.module('SOGo.Common').factory('Acl', Acl.factory);
|
||||
|
||||
/**
|
||||
* @function $users
|
||||
+6
-6
@@ -81,12 +81,12 @@
|
||||
newAddress = baseAddress;
|
||||
}
|
||||
|
||||
if (/theme=mobile/.test(window.location.search)) {
|
||||
newAddress = baseAddress + '/Contacts' + '?theme=mobile';
|
||||
}
|
||||
else {
|
||||
newAddress = baseAddress + '/Contacts';
|
||||
}
|
||||
// if (/theme=mobile/.test(window.location.search)) {
|
||||
// newAddress = baseAddress + '/Contacts' + '?theme=mobile';
|
||||
// }
|
||||
// else {
|
||||
// newAddress = baseAddress + '/Contacts';
|
||||
// }
|
||||
|
||||
return newAddress;
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('SOGo.Common', ['ngMaterial', 'RecursionHelper'])
|
||||
// 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
|
||||
// For some reasons, angular-material's break-points don't match the specs
|
||||
// Here we define values according to specs
|
||||
.constant('sgConstant', {
|
||||
'sm': '(max-width: 600px)',
|
||||
'gt-sm': '(min-width: 600px)',
|
||||
'md': '(min-width: 600px) and (max-width: 1024px)',
|
||||
'gt-md': '(min-width: 1025px)',
|
||||
'lg': '(min-width: 1024px) and (max-width: 1280px)',
|
||||
'gt-lg': '(min-width: 1280px)'
|
||||
})
|
||||
|
||||
.config(configure);
|
||||
|
||||
configure.$inject = ['$mdThemingProvider'];
|
||||
function configure($mdThemingProvider) {
|
||||
$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',
|
||||
'A200': '69f0ae',
|
||||
'A400': '00e676',
|
||||
'A700': '00c853',
|
||||
'contrastDefaultColor': 'dark',
|
||||
'contrastDarkColors': '50 100 200',
|
||||
'contrastLightColors': '300 400 500 600 700 800 900'
|
||||
});
|
||||
$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']
|
||||
});
|
||||
$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'
|
||||
});
|
||||
// Default theme definition
|
||||
// .primaryColor will soon be deprecated in favor of primaryPalette (already on dev builds https://groups.google.com/forum/m/#!topic/ngmaterial/-sXR8CYBMPg)
|
||||
$mdThemingProvider.theme('default')
|
||||
.primaryPalette('sogo-blue', {
|
||||
'default': '300',
|
||||
'hue-1': '100',
|
||||
'hue-2': '400',
|
||||
'hue-3': 'A700'
|
||||
})
|
||||
.accentPalette('sogo-green', {
|
||||
'default': '500',
|
||||
'hue-1': '200',
|
||||
'hue-2': '300',
|
||||
'hue-3': 'A700'
|
||||
})
|
||||
.backgroundPalette('sogo-paper', {
|
||||
'default': '100',
|
||||
'hue-1': '200',
|
||||
'hue-2': '50',
|
||||
'hue-3': '500'
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,125 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Dialog
|
||||
* @constructor
|
||||
*/
|
||||
function Dialog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @name alert
|
||||
* @desc Show an alert dialog box with a single "OK" button
|
||||
* @param {string} title
|
||||
* @param {string} content
|
||||
*/
|
||||
Dialog.alert = function(title, content) {
|
||||
var alert = this.$modal.alert()
|
||||
.title(title)
|
||||
.content(content)
|
||||
.ok(l('OK'));
|
||||
this.$modal.show(alert);
|
||||
};
|
||||
|
||||
/**
|
||||
* @name confirm
|
||||
* @desc Show a confirmation dialog box with buttons 'Cancel' and 'OK'
|
||||
* @param {string} title
|
||||
* @param {string} content
|
||||
* @returns a promise that resolves if the user has clicked on the 'OK' button
|
||||
*/
|
||||
Dialog.confirm = function(title, content) {
|
||||
var d = this.$q.defer(),
|
||||
confirm = this.$modal.confirm()
|
||||
.title(title)
|
||||
.content(content)
|
||||
.ok(l('OK'))
|
||||
.cancel(l('Cancel'));
|
||||
this.$modal.show(confirm).then(function() {
|
||||
d.resolve();
|
||||
}, function() {
|
||||
d.reject();
|
||||
});
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @name prompt
|
||||
* @desc Show a primpt dialog box with a input text field and the 'Cancel' and 'OK' buttons
|
||||
* @param {string} title
|
||||
* @param {string} label
|
||||
* @param {object} [options] - use a different input type by setting 'inputType'
|
||||
* @returns a promise that resolves with the input field value
|
||||
*/
|
||||
Dialog.prompt = function(title, label, options) {
|
||||
var o = options || {},
|
||||
d = this.$q.defer();
|
||||
|
||||
this.$modal.show({
|
||||
parent: angular.element(document.body),
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
template: [
|
||||
'<md-dialog flex="50" flex-sm="100">',
|
||||
' <md-dialog-content layout="column">',
|
||||
' <h2 class="md-title" ng-bind="title"></h2>',
|
||||
' <md-input-container>',
|
||||
' <label>' + label + '</label>',
|
||||
' <input type="' + (o.inputType || 'text') + '"',
|
||||
' aria-label="' + title + '"',
|
||||
' ng-model="name" required="required"/>',
|
||||
' </md-input-container>',
|
||||
' </md-dialog-content>',
|
||||
' <div class="md-actions">',
|
||||
' <md-button ng-click="cancel()">',
|
||||
' ' + l('Cancel'),
|
||||
' </md-button>',
|
||||
' <md-button class="md-primary" ng-click="ok()" ng-disabled="!name.length">',
|
||||
' ' + l('OK'),
|
||||
' </md-button>',
|
||||
' </div>',
|
||||
'</md-dialog>'
|
||||
].join(''),
|
||||
controller: PromptDialogController
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function PromptDialogController(scope, $mdDialog) {
|
||||
scope.title = title;
|
||||
scope.name = "";
|
||||
scope.cancel = function() {
|
||||
d.reject();
|
||||
$mdDialog.hide();
|
||||
}
|
||||
scope.ok = function() {
|
||||
d.resolve(scope.name);
|
||||
$mdDialog.hide();
|
||||
}
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Dialog
|
||||
* @desc The factory we'll register as Dialog in the Angular module SOGo.Common
|
||||
* @ngInject
|
||||
*/
|
||||
DialogService.$inject = ['$q', '$mdDialog'];
|
||||
function DialogService($q, $mdDialog) {
|
||||
angular.extend(Dialog, { $q: $q , $modal: $mdDialog });
|
||||
|
||||
return Dialog; // return constructor
|
||||
};
|
||||
|
||||
/* Factory registration in Angular module */
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.factory('Dialog', DialogService);
|
||||
|
||||
})();
|
||||
+1
-1
@@ -38,7 +38,7 @@
|
||||
* @module SOGo.Common
|
||||
* @desc Factory registration of Resource in Angular module.
|
||||
*/
|
||||
angular.module('SOGo.Common').factory('sgResource', Resource.$factory);
|
||||
angular.module('SOGo.Common').factory('Resource', Resource.$factory);
|
||||
|
||||
/**
|
||||
* @function userResource
|
||||
+5
-2
@@ -23,7 +23,7 @@
|
||||
* @desc The factory we'll use to register with Angular.
|
||||
* @return the User constructor
|
||||
*/
|
||||
User.factory = ['$q', 'sgSettings', 'sgResource', function($q, Settings, Resource) {
|
||||
User.factory = ['$q', 'sgSettings', 'Resource', function($q, Settings, Resource) {
|
||||
angular.extend(User, {
|
||||
$q: $q,
|
||||
$$resource: new Resource(Settings.activeUser.folderURL, Settings.activeUser)
|
||||
@@ -36,7 +36,7 @@
|
||||
* @module SOGo.Common
|
||||
* @desc Factory registration of User in Angular module.
|
||||
*/
|
||||
angular.module('SOGo.Common').factory('sgUser', User.factory);
|
||||
angular.module('SOGo.Common').factory('User', User.factory);
|
||||
|
||||
/**
|
||||
* @memberof User
|
||||
@@ -46,6 +46,8 @@
|
||||
*/
|
||||
User.$filter = function(search) {
|
||||
var param = {search: search};
|
||||
if (!search)
|
||||
return User.$q.when([]);
|
||||
return User.$$resource.fetch(null, 'usersSearch', param).then(function(response) {
|
||||
var results = [];
|
||||
angular.forEach(response.users, function(data) {
|
||||
@@ -53,6 +55,7 @@
|
||||
var user = new User(data);
|
||||
results.push(user);
|
||||
});
|
||||
User.$users = results;
|
||||
return results;
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/**
|
||||
* @type {angular.Module}
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
decodeUri.$inject = ['$window'];
|
||||
function decodeUri($window) {
|
||||
return $window.decodeURIComponent;
|
||||
}
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.filter('decodeUri', decodeUri);
|
||||
})();
|
||||
@@ -0,0 +1,19 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/**
|
||||
* @type {angular.Module}
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
encodeUri.$inject = ['$window'];
|
||||
function encodeUri($window) {
|
||||
return $window.encodeURIComponent;
|
||||
}
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.filter('encodeUri', encodeUri);
|
||||
})();
|
||||
@@ -0,0 +1,18 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/**
|
||||
* @type {angular.Module}
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function loc() {
|
||||
return l;
|
||||
}
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.filter('loc', loc);
|
||||
})();
|
||||
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/**
|
||||
* @type {angular.Module}
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
navController.$inject = ['$scope', '$timeout', '$interval', '$http', '$mdSidenav', '$mdBottomSheet', '$mdMedia', '$log', 'sgConstant'];
|
||||
function navController($scope, $timeout, $interval, $http, $mdSidenav, $mdBottomSheet, $mdMedia, $log, sgConstant) {
|
||||
|
||||
// Show current day in top bar
|
||||
$scope.currentDay = window.currentDay;
|
||||
$timeout(function() {
|
||||
// Update date when day ends
|
||||
$interval(function() {
|
||||
$http.get('../date').success(function(data) {
|
||||
$scope.currentDay = data;
|
||||
});
|
||||
}, 24 * 3600 * 1000);
|
||||
}, window.secondsBeforeTomorrow * 1000);
|
||||
|
||||
$scope.toggleLeft = function () {
|
||||
$mdSidenav('left').toggle()
|
||||
.then(function () {
|
||||
$log.debug("toggle left is done");
|
||||
});
|
||||
};
|
||||
$scope.toggleRight = function () {
|
||||
$mdSidenav('right').toggle()
|
||||
.then(function () {
|
||||
$log.debug("toggle RIGHT is done");
|
||||
});
|
||||
};
|
||||
$scope.openBottomSheet = function() {
|
||||
$mdBottomSheet.show({
|
||||
parent: angular.element(document.getElementById('left-sidenav')),
|
||||
templateUrl: 'bottomSheetTemplate.html'
|
||||
});
|
||||
};
|
||||
$scope.toggleDetailView = function() {
|
||||
var detail = angular.element(document.getElementById('detailView'));
|
||||
detail.toggleClass('sg-close');
|
||||
};
|
||||
$scope.$watch(function() {
|
||||
return $mdMedia(sgConstant['gt-md']);
|
||||
}, function(newVal) {
|
||||
$scope.isGtMedium = newVal;
|
||||
});
|
||||
}
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.controller('navController', navController);
|
||||
})();
|
||||
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* sgEnter - A directive evaluated when the enter key is pressed
|
||||
* @memberof SOGo.Common
|
||||
* @ngInject
|
||||
* @example:
|
||||
|
||||
<input type="text"
|
||||
sg-enter="save($index)" />
|
||||
*/
|
||||
function sgEnter() {
|
||||
var ENTER_KEY = 13;
|
||||
return function(scope, element, attrs) {
|
||||
element.bind("keydown keypress", function(event) {
|
||||
if (event.which === ENTER_KEY) {
|
||||
scope.$apply(function() {
|
||||
scope.$eval(attrs.sgEnter);
|
||||
});
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgEnter', sgEnter);
|
||||
})();
|
||||
@@ -0,0 +1,29 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* sgEscape - A directive evaluated when the escape key is pressed
|
||||
* @memberof SOGo.Common
|
||||
* @ngInject
|
||||
* @example:
|
||||
|
||||
<input type="text"
|
||||
sg-escape="revertEditing($index)" />
|
||||
*/
|
||||
function sgEscape() {
|
||||
var ESCAPE_KEY = 27;
|
||||
return function(scope, elem, attrs) {
|
||||
elem.bind('keydown', function(event) {
|
||||
if (event.keyCode === ESCAPE_KEY) {
|
||||
scope.$apply(attrs.sgEscape);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgEscape', sgEscape);
|
||||
})();
|
||||
@@ -0,0 +1,30 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* sgFocusOn - A directive that sets the focus on its element when the specified string is broadcasted
|
||||
* @memberof SOGo.Common
|
||||
* @see {@link SOGo.Common.sgFocus}
|
||||
* @ngInject
|
||||
* @example:
|
||||
|
||||
<input type="text"
|
||||
sg-focus-on="username" />
|
||||
*/
|
||||
function sgFocusOn() {
|
||||
return function(scope, elem, attr) {
|
||||
scope.$on('sgFocusOn', function(e, name) {
|
||||
if (name === attr.sgFocusOn) {
|
||||
elem[0].focus();
|
||||
elem[0].select();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgFocusOn', sgFocusOn);
|
||||
})();
|
||||
@@ -0,0 +1,25 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* sgFocus - A service to set the focus on the element associated to a specific string
|
||||
* @memberof SOGo.Common
|
||||
* @param {string} name - the string identifier of the element
|
||||
* @see {@link SOGo.Common.sgFocusOn}
|
||||
* @ngInject
|
||||
*/
|
||||
sgFocus.$inject = ['$rootScope', '$timeout'];
|
||||
function sgFocus($rootScope, $timeout) {
|
||||
return function(name) {
|
||||
$timeout(function() {
|
||||
$rootScope.$broadcast('sgFocusOn', name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.factory('sgFocus', sgFocus);
|
||||
})();
|
||||
@@ -0,0 +1,44 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* sgFolderStylesheet - Add CSS stylesheet for folder (addressbook or calendar)
|
||||
* @memberof SOGo.Common
|
||||
* @restrict attribute
|
||||
* @param {object} ngModel - the object literal describing the folder (an Addressbook or Calendar instance)
|
||||
* @example:
|
||||
|
||||
<div sg-folder-stylesheet="true"
|
||||
ng-repeat="calendar in calendars.list"
|
||||
ng-model="calendar" />
|
||||
</div>
|
||||
*/
|
||||
function sgFolderStylesheet() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
scope: {
|
||||
ngModel: '='
|
||||
},
|
||||
template: [
|
||||
'<style type="text/css">',
|
||||
' .bg-folder{{ ngModel.id }} {',
|
||||
' background-color: {{ ngModel.color }} !important;',
|
||||
' }',
|
||||
' .fg-folder{{ ngModel.id }} {',
|
||||
' color: {{ ngModel.color }} !important;',
|
||||
' }',
|
||||
' .checkbox-folder{{ ngModel.id }}.md-checked .md-icon {',
|
||||
' background-color: {{ ngModel.color }} !important;',
|
||||
' }',
|
||||
'</style>'
|
||||
].join('')
|
||||
}
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgFolderStylesheet', sgFolderStylesheet);
|
||||
})();
|
||||
@@ -0,0 +1,40 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* sgGravatarImage - A simple Gravatar directive (based on http://blog.lingohub.com/2014/08/better-ux-with-angularjs-directives/)
|
||||
* @memberof SOGo.Common
|
||||
* @example:
|
||||
<sg-gravatar-image email="test@email.com" size="50"></sg-gravatar-image>
|
||||
*/
|
||||
|
||||
function sgGravatarImage() {
|
||||
return {
|
||||
restrict: 'AE',
|
||||
replace: true,
|
||||
required: 'email',
|
||||
template: '<img ng-src="https://www.gravatar.com/avatar/{{hash}}?s={{size}}&d=wavatar" />',
|
||||
link: function(scope, element, attrs) {
|
||||
attrs.$observe('email', function(value) {
|
||||
if (!value) { return; }
|
||||
|
||||
// MD5 (Message-Digest Algorithm) by WebToolkit
|
||||
var md5=function(s){function L(k,d){return(k<<d)|(k>>>(32-d));}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H);}if(I|d){if(x&1073741824){return(x^3221225472^F^H);}else{return(x^1073741824^F^H);}}else{return(x^F^H);}}function r(d,F,k){return(d&F)|((~d)&k);}function q(d,F,k){return(d&k)|(F&(~k));}function p(d,F,k){return(d^F^k);}function n(d,F,k){return(F^(d|(~k)));}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F);}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F);}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F);}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F);}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H<F){Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=(aa[Z]|(G.charCodeAt(H)<<d));H++;}Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=aa[Z]|(128<<d);aa[I-2]=F<<3;aa[I-1]=F>>>29;return aa;}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2);}return k;}function J(k){k=k.replace(/rn/g,"n");var d="";for(var F=0;F<k.length;F++){var x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x);}else{if((x>127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128);}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128);}}}return d;}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g);}var i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};
|
||||
|
||||
scope.hash = md5(value.toLowerCase());
|
||||
scope.size = attrs.size;
|
||||
|
||||
if (angular.isUndefined(scope.size)) {
|
||||
scope.size = 60; // default to 60 pixels
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgGravatarImage', sgGravatarImage);
|
||||
})();
|
||||
@@ -0,0 +1,101 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* sgSearch - Search within a list of items
|
||||
* @memberof SOGo.Common
|
||||
* @restrict attribute
|
||||
* @param {function} sgSearch - the function to call when performing a search.
|
||||
* Two variables are available: searchField and searchText.
|
||||
* @example:
|
||||
|
||||
<div sg-search="mailbox.$filter({ sort: 'date', asc: false }, [{ searchBy: searchField, searchInput: searchText }])">
|
||||
<md-input-container>
|
||||
<input name="search" type="search"/>
|
||||
</md-input-container>
|
||||
<md-select class="sg-toolbar-sort md-contrast-light">
|
||||
<md-option value="subject">Subject</md-option>
|
||||
<md-option value="sender">sender</md-option>
|
||||
</md-select>
|
||||
</div>
|
||||
*/
|
||||
sgSearch.$inject = ['$compile'];
|
||||
function sgSearch($compile) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
controller: 'sgSearchController',
|
||||
controllerAs: '$sgSearchController',
|
||||
// See http://stackoverflow.com/questions/19224028/add-directives-from-directive-in-angularjs
|
||||
// for reasons of using terminal and priority
|
||||
terminal: true,
|
||||
priority: 1000,
|
||||
scope: {
|
||||
doSearch: '&sgSearch'
|
||||
},
|
||||
compile: compile
|
||||
};
|
||||
|
||||
function compile(tElement, tAttr) {
|
||||
var mdInputEl = tElement.find('md-input-container'),
|
||||
inputEl = tElement.find('input'),
|
||||
selectEl = tElement.find('md-select');
|
||||
|
||||
inputEl.attr('ng-model', '$sgSearchController.searchText');
|
||||
inputEl.attr('ng-model-options', '$sgSearchController.searchTextOptions');
|
||||
if (selectEl) {
|
||||
selectEl.attr('ng-model', '$sgSearchController.searchField');
|
||||
selectEl.attr('ng-change', '$sgSearchController.onChange()');
|
||||
}
|
||||
|
||||
return function postLink(scope, iElement, iAttr, controller) {
|
||||
$compile(mdInputEl)(scope);
|
||||
if (selectEl)
|
||||
$compile(selectEl)(scope);
|
||||
$compile(tElement.find('md-button'))(scope.$parent);
|
||||
|
||||
scope.$watch('$sgSearchController.searchText', angular.bind(controller, controller.onChange));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
sgSearchController.$inject = ['$scope', '$element'];
|
||||
function sgSearchController($scope, $element) {
|
||||
// Controller variables
|
||||
this.previous = { searchText: '', searchField: '' };
|
||||
this.searchText = '';
|
||||
this.searchField = $element.find('md-option').attr('value'); // defaults to first option
|
||||
|
||||
// Model options
|
||||
this.searchTextOptions = {
|
||||
updateOn: 'default blur',
|
||||
debounce: {
|
||||
default: 300,
|
||||
blur: 0
|
||||
}
|
||||
};
|
||||
|
||||
// Method to call on data changes
|
||||
this.onChange = function(value) {
|
||||
if (typeof this.searchText != 'undefined') {
|
||||
if (this.searchText != this.previous.searchText || this.searchField != this.previous.searchField) {
|
||||
if (this.searchText.length > 2 || this.searchText.length == 0) {
|
||||
// See https://github.com/angular/angular.js/issues/7635
|
||||
// for why we need to use $scope here
|
||||
$scope.doSearch({ searchText: this.searchText, searchField: this.searchField });
|
||||
}
|
||||
this.previous = { searchText: this.searchText, searchField: this.searchField };
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.controller('sgSearchController', sgSearchController)
|
||||
.directive('sgSearch', sgSearch);
|
||||
})();
|
||||
@@ -0,0 +1,93 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* sgSubscribe - Common subscription widget
|
||||
* @restrict class or attribute
|
||||
* @param {string} sgSubscribe - the folder type
|
||||
* @param {function} sgSubscribeOnSelect - the function to call when subscribing to a folder.
|
||||
* One variable is available: folderData.
|
||||
* @ngInject
|
||||
* @example:
|
||||
|
||||
<md-button sg-subscribe="contact" sg-subscribe-on-select="subscribeToFolder">Subscribe ..</md-button>
|
||||
*/
|
||||
sgSubscribe.$inject = ['User'];
|
||||
function sgSubscribe(User) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
folderType: '@sgSubscribe',
|
||||
onFolderSelect: '&sgSubscribeOnSelect'
|
||||
},
|
||||
replace: false,
|
||||
bindToController: true,
|
||||
controller: sgSubscribeDialogController,
|
||||
controllerAs: 'vm',
|
||||
link: link
|
||||
}
|
||||
sgSubscribeDialogController.$inject = ['$mdDialog'];
|
||||
function sgSubscribeDialogController($mdDialog) {
|
||||
var vm = this;
|
||||
vm.showDialog = function() {
|
||||
$mdDialog.show({
|
||||
templateUrl: '../Contacts/UIxContactsUserFolders',
|
||||
clickOutsideToClose: true,
|
||||
//scope: vm,
|
||||
//preserveScope: true,
|
||||
locals: {
|
||||
folderType: vm.folderType,
|
||||
onFolderSelect: vm.onFolderSelect
|
||||
//User: User
|
||||
},
|
||||
controller: sgSubscribeController,
|
||||
controllerAs: 'vm'
|
||||
});
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
sgSubscribeController.$inject = ['folderType', 'onFolderSelect', 'User'];
|
||||
function sgSubscribeController(folderType, onFolderSelect, User) {
|
||||
var vm = this;
|
||||
vm.selectedUser = null;
|
||||
|
||||
vm.searchTextOptions = {
|
||||
updateOn: 'default blur',
|
||||
debounce: {
|
||||
default: 300,
|
||||
blur: 0
|
||||
}
|
||||
};
|
||||
|
||||
vm.onChange = function() {
|
||||
User.$filter(vm.searchText).then(function(matches) {
|
||||
vm.users = matches;
|
||||
});
|
||||
};
|
||||
|
||||
vm.selectUser = function(i) {
|
||||
// Fetch folders of specific type for selected user
|
||||
vm.users[i].$folders(folderType).then(function() {
|
||||
vm.selectedUser = vm.users[i];
|
||||
});
|
||||
};
|
||||
|
||||
// Callback upon subscription to a folder
|
||||
vm.selectFolder = function(folder) {
|
||||
onFolderSelect({folderData: folder});
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
function link(scope, element, attrs, controller) {
|
||||
var inputEl = element.find('input');
|
||||
element.on('click', controller.showDialog);
|
||||
}
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgSubscribe', sgSubscribe);
|
||||
})();
|
||||
@@ -4,234 +4,15 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Dialog
|
||||
* @constructor
|
||||
*/
|
||||
function Dialog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @name alert
|
||||
* @desc Show an alert dialog box with a single "OK" button
|
||||
* @param {string} title
|
||||
* @param {string} content
|
||||
*/
|
||||
Dialog.alert = function(title, content) {
|
||||
var alert = this.$modal.alert()
|
||||
.title(title)
|
||||
.content(content)
|
||||
.ok(l('OK'));
|
||||
this.$modal.show(alert);
|
||||
};
|
||||
|
||||
/**
|
||||
* @name confirm
|
||||
* @desc Show a confirmation dialog box with buttons 'Cancel' and 'OK'
|
||||
* @param {string} title
|
||||
* @param {string} content
|
||||
* @returns a promise that resolves if the user has clicked on the 'OK' button
|
||||
*/
|
||||
Dialog.confirm = function(title, content) {
|
||||
var d = this.$q.defer(),
|
||||
confirm = this.$modal.confirm()
|
||||
.title(title)
|
||||
.content(content)
|
||||
.ok(l('OK'))
|
||||
.cancel(l('Cancel'));
|
||||
this.$modal.show(confirm).then(function() {
|
||||
d.resolve();
|
||||
}, function() {
|
||||
d.reject();
|
||||
});
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @name prompt
|
||||
* @desc Show a primpt dialog box with a input text field and the 'Cancel' and 'OK' buttons
|
||||
* @param {string} title
|
||||
* @param {string} label
|
||||
* @param {object} [options] - use a different input type by setting 'inputType'
|
||||
* @returns a promise that resolves with the input field value
|
||||
*/
|
||||
Dialog.prompt = function(title, label, options) {
|
||||
var o = options || {},
|
||||
d = this.$q.defer();
|
||||
|
||||
this.$modal.show({
|
||||
parent: angular.element(document.body),
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
template: [
|
||||
'<md-dialog flex="30" flex-sm="100">',
|
||||
' <md-dialog-content layout="column">',
|
||||
' <h2 class="md-title" ng-bind="title"></h2>',
|
||||
' <md-input-container>',
|
||||
' <label>' + label + '</label>',
|
||||
' <input type="' + (o.inputType || 'text') + '"',
|
||||
' aria-label="' + title + '"',
|
||||
' ng-model="name" required="required"/>',
|
||||
' </md-input-container>',
|
||||
' </md-dialog-content>',
|
||||
' <div class="md-actions">',
|
||||
' <md-button ng-click="cancel()">',
|
||||
' ' + l('Cancel'),
|
||||
' </md-button>',
|
||||
' <md-button class="md-primary" ng-click="ok()" ng-disabled="!name.length">',
|
||||
' ' + l('OK'),
|
||||
' </md-button>',
|
||||
' </div>',
|
||||
'</md-dialog>'
|
||||
].join(''),
|
||||
controller: PromptDialogController
|
||||
});
|
||||
|
||||
function PromptDialogController(scope, $mdDialog) {
|
||||
scope.title = title;
|
||||
scope.name = "";
|
||||
scope.cancel = function() {
|
||||
d.reject();
|
||||
$mdDialog.hide();
|
||||
}
|
||||
scope.ok = function() {
|
||||
d.resolve(scope.name);
|
||||
$mdDialog.hide();
|
||||
}
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Dialog
|
||||
* @desc The factory we'll register as sgDialog in the Angular module SOGo.UIDesktop
|
||||
*/
|
||||
Dialog.$factory = ['$q', '$mdDialog', function($q, $mdDialog) {
|
||||
angular.extend(Dialog, { $q: $q , $modal: $mdDialog });
|
||||
|
||||
return Dialog; // return constructor
|
||||
}];
|
||||
|
||||
/* Angular module instanciation */
|
||||
angular.module('SOGo.UIDesktop', ['ngMaterial', 'RecursionHelper'])
|
||||
|
||||
/* Factory registration in Angular module */
|
||||
.factory('sgDialog', Dialog.$factory)
|
||||
|
||||
/**
|
||||
* sgEnter - A directive evaluated when the enter key is pressed
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @example:
|
||||
|
||||
<input type="text"
|
||||
sg-enter="save($index)" />
|
||||
*/
|
||||
.directive('sgEnter', function() {
|
||||
var ENTER_KEY = 13;
|
||||
return function(scope, element, attrs) {
|
||||
element.bind("keydown keypress", function(event) {
|
||||
if (event.which === ENTER_KEY) {
|
||||
scope.$apply(function() {
|
||||
scope.$eval(attrs.sgEnter);
|
||||
});
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
/**
|
||||
* sgEscape - A directive evaluated when the escape key is pressed
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @example:
|
||||
|
||||
<input type="text"
|
||||
sg-escape="revertEditing($index)" />
|
||||
*/
|
||||
.directive('sgEscape', function() {
|
||||
var ESCAPE_KEY = 27;
|
||||
return function(scope, elem, attrs) {
|
||||
elem.bind('keydown', function(event) {
|
||||
if (event.keyCode === ESCAPE_KEY) {
|
||||
scope.$apply(attrs.sgEscape);
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
/**
|
||||
* sgFocusOn - A directive that sets the focus on its element when the specified string is broadcasted
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @see {@link SOGo.UIDesktop.sgFocus}
|
||||
* @example:
|
||||
|
||||
<input type="text"
|
||||
sg-focus-on="username" />
|
||||
*/
|
||||
.directive('sgFocusOn', function() {
|
||||
return function(scope, elem, attr) {
|
||||
scope.$on('sgFocusOn', function(e, name) {
|
||||
if (name === attr.sgFocusOn) {
|
||||
elem[0].focus();
|
||||
elem[0].select();
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
/**
|
||||
* sgGravatarImage - A simple Gravatar directive (based on http://blog.lingohub.com/2014/08/better-ux-with-angularjs-directives/)
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @example:
|
||||
|
||||
<sg-gravatar-image email="test@email.com" size="50"></sg-gravatar-image>
|
||||
*/
|
||||
.directive('sgGravatarImage', function () {
|
||||
return {
|
||||
restrict: 'AE',
|
||||
replace: true,
|
||||
required: 'email',
|
||||
template: '<img ng-src="https://www.gravatar.com/avatar/{{hash}}?s={{size}}&d=wavatar" />',
|
||||
link: function (scope, element, attrs) {
|
||||
attrs.$observe('email', function (value) {
|
||||
if(!value) { return; }
|
||||
|
||||
// MD5 (Message-Digest Algorithm) by WebToolkit
|
||||
var md5=function(s){function L(k,d){return(k<<d)|(k>>>(32-d));}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H);}if(I|d){if(x&1073741824){return(x^3221225472^F^H);}else{return(x^1073741824^F^H);}}else{return(x^F^H);}}function r(d,F,k){return(d&F)|((~d)&k);}function q(d,F,k){return(d&k)|(F&(~k));}function p(d,F,k){return(d^F^k);}function n(d,F,k){return(F^(d|(~k)));}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F);}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F);}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F);}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F);}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H<F){Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=(aa[Z]|(G.charCodeAt(H)<<d));H++;}Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=aa[Z]|(128<<d);aa[I-2]=F<<3;aa[I-1]=F>>>29;return aa;}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2);}return k;}function J(k){k=k.replace(/rn/g,"n");var d="";for(var F=0;F<k.length;F++){var x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x);}else{if((x>127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128);}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128);}}}return d;}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g);}var i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};
|
||||
|
||||
scope.hash = md5(value.toLowerCase());
|
||||
scope.size = attrs.size;
|
||||
|
||||
if(angular.isUndefined(scope.size)) {
|
||||
scope.size = 60; // default to 60 pixels
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
/**
|
||||
* sgFocus - A service to set the focus on the element associated to a specific string
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @param {string} name - the string identifier of the element
|
||||
* @see {@link SOGo.UIDesktop.sgFocusOn}
|
||||
*/
|
||||
.factory('sgFocus', ['$rootScope', '$timeout', function($rootScope, $timeout) {
|
||||
return function(name) {
|
||||
$timeout(function() {
|
||||
$rootScope.$broadcast('sgFocusOn', name);
|
||||
});
|
||||
}
|
||||
}])
|
||||
angular.module('SOGo.Common')
|
||||
|
||||
/*
|
||||
* sgFolderTree - Provides hierarchical folders tree
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @memberof SOGo.Common
|
||||
* @restrict element
|
||||
* @param {object} sgRoot
|
||||
* @param {object} sgFolder
|
||||
* @param {function} sgSetFolder
|
||||
* @param {function} sgSelectFolder
|
||||
* @see https://github.com/marklagendijk/angular-recursion
|
||||
* @example:
|
||||
|
||||
@@ -248,29 +29,30 @@
|
||||
folder: '=sgFolder',
|
||||
selectFolder: '=sgSelectFolder'
|
||||
},
|
||||
template:
|
||||
'<md-list-item>' +
|
||||
' <md-item-content layout="row" layout-align="start center" flex>' +
|
||||
' <i class="md-icon-folder"></i>' +
|
||||
' <button class="md-button md-flex sg-item-name">{{folder.name}}</button>' +
|
||||
template: [
|
||||
'<md-list-item>',
|
||||
' <md-item-content layout="row" layout-align="start center" flex>',
|
||||
' <i class="md-icon-folder"></i>',
|
||||
' <button class="md-button md-flex sg-item-name">{{folder.name}}</button>',
|
||||
' <md-input-container class="md-flex md-tile-content ng-hide">'+
|
||||
' <input type="text"' +
|
||||
' ng-model="folder.name"' +
|
||||
' ng-blur="save()"' +
|
||||
' sg-enter="save()"' +
|
||||
' sg-escape="revert()"/>' +
|
||||
' </md-input-container>' +
|
||||
' <span class="icon ng-hide" ng-cloak="ng-cloak">' +
|
||||
' <a class="icon" href="#"' +
|
||||
' dropdown-toggle="#folderProperties"' +
|
||||
' options="align:right"><i class="md-icon-more-vert"></i></a>' +
|
||||
' </span>' +
|
||||
' </md-item-content>' +
|
||||
'</md-list-item>' +
|
||||
'<sg-folder-tree ng-repeat="child in folder.children track by child.path"' +
|
||||
' data-sg-root="root"' +
|
||||
' data-sg-folder="child"' +
|
||||
' data-sg-select-folder="selectFolder"></sg-folder-tree>',
|
||||
' <input type="text"',
|
||||
' ng-model="folder.name"',
|
||||
' ng-blur="save()"',
|
||||
' sg-enter="save()"',
|
||||
' sg-escape="revert()"/>',
|
||||
' </md-input-container>',
|
||||
' <span class="icon ng-hide" ng-cloak="ng-cloak">',
|
||||
' <a class="icon" href="#"',
|
||||
' dropdown-toggle="#folderProperties"',
|
||||
' options="align:right"><i class="md-icon-more-vert"></i></a>',
|
||||
' </span>',
|
||||
' </md-item-content>',
|
||||
'</md-list-item>',
|
||||
'<sg-folder-tree ng-repeat="child in folder.children track by child.path"',
|
||||
' sg-root="root"',
|
||||
' sg-folder="child"',
|
||||
' sg-select-folder="selectFolder"></sg-folder-tree>'
|
||||
].join(''),
|
||||
compile: function(element) {
|
||||
return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) {
|
||||
var level, link, inputContainer, input, edit;
|
||||
@@ -378,7 +160,7 @@
|
||||
|
||||
/*
|
||||
* sgDropdownContentToggle - Provides dropdown content functionality
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @memberof SOGo.Common
|
||||
* @restrict class or attribute
|
||||
* @see https://github.com/pineconellc/angular-foundation/blob/master/src/dropdownToggle/dropdownToggle.js
|
||||
* @example:
|
||||
@@ -496,57 +278,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* sgSubscribe - Common subscription widget
|
||||
* @restrict class or attribute
|
||||
* @param {String} sgSubscribe - the folder type
|
||||
* @param {Function} sgSubscribeOnSelect - the function to call when subscribing to a folder
|
||||
* @example:
|
||||
|
||||
<md-button sg-subscribe="contact" sg-subscribe-on-select="subscribeToFolder">Subscribe ..</md-button>
|
||||
*/
|
||||
.directive('sgSubscribe', [function() {
|
||||
console.debug('registering sgSubscribe');
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
folderType: '@sgSubscribe',
|
||||
onFolderSelect: '&sgSubscribeOnSelect'
|
||||
},
|
||||
replace: false,
|
||||
bindToController: true,
|
||||
controllerAs: 'vm',
|
||||
controller: ['$scope', '$mdDialog', function($scope, $mdDialog) {
|
||||
var vm = this;
|
||||
vm.showDialog = function() {
|
||||
$mdDialog.show({
|
||||
templateUrl: '../Contacts/UIxContactsUserFolders',
|
||||
clickOutsideToClose: true,
|
||||
locals: {
|
||||
folderType: vm.folderType,
|
||||
onFolderSelect: vm.onFolderSelect
|
||||
},
|
||||
controller: function($scope, folderType, onFolderSelect) {
|
||||
$scope.selectUser = function(i) {
|
||||
// Fetch folders of specific type for selected user
|
||||
$scope.users[i].$folders(folderType).then(function() {
|
||||
$scope.selectedUser = $scope.users[i];
|
||||
});
|
||||
};
|
||||
$scope.selectFolder = function(folder) {
|
||||
onFolderSelect({folderData: folder});
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
}],
|
||||
link: function(scope, element, attrs, controller) {
|
||||
element.on('click', controller.showDialog);
|
||||
}
|
||||
};
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgUserTypeahead - Typeahead of users, used internally by sgSubscribe
|
||||
* UserTypeahead - Typeahead of users, used internally by sgSubscribe
|
||||
* @restrict attribute
|
||||
* @param {String} sgModel - the folder type
|
||||
* @param {Function} sgSubscribeOnSelect - the function to call when subscribing to a folder
|
||||
@@ -555,7 +287,7 @@
|
||||
|
||||
<div sg-subscribe="contact" sg-subscribe-on-select="subscribeToFolder"></div>
|
||||
*/
|
||||
.directive('sgUserTypeahead', ['$parse', '$q', '$timeout', 'sgUser', function($parse, $q, $timeout, User) {
|
||||
.directive('sgUserTypeahead', ['$parse', '$q', '$timeout', 'User', function($parse, $q, $timeout, User) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
@@ -648,272 +380,4 @@
|
||||
};
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgSearch - Search within a list of items
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @restrict attribute
|
||||
* @param {function} sgSearch - the function to call when performing a search.
|
||||
* Two variables are available: searchField and searchText.
|
||||
* @example:
|
||||
|
||||
<div sg-search="mailbox.$filter({ sort: 'date', asc: false }, [{ searchBy: searchField, searchInput: searchText }])">
|
||||
<md-input-container>
|
||||
<input name="search" type="search"/>
|
||||
</md-input-container>
|
||||
<md-select class="sg-toolbar-sort md-contrast-light">
|
||||
<md-option value="subject">Subject</md-option>
|
||||
<md-option value="sender">sender</md-option>
|
||||
</md-select>
|
||||
</div>
|
||||
*/
|
||||
.directive('sgSearch', ['$compile', function($compile) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
controller: 'sgSearchController',
|
||||
controllerAs: '$sgSearchController',
|
||||
// See http://stackoverflow.com/questions/19224028/add-directives-from-directive-in-angularjs
|
||||
// for reasons of using terminal and priority
|
||||
terminal: true,
|
||||
priority: 1000,
|
||||
scope: {
|
||||
doSearch: '&sgSearch'
|
||||
},
|
||||
compile: compile
|
||||
};
|
||||
|
||||
function compile(tElement, tAttr) {
|
||||
var mdInputEl = tElement.find('md-input-container'),
|
||||
inputEl = tElement.find('input'),
|
||||
selectEl = tElement.find('md-select');
|
||||
|
||||
inputEl.attr('ng-model', '$sgSearchController.searchText');
|
||||
inputEl.attr('ng-model-options', '$sgSearchController.searchTextOptions');
|
||||
selectEl.attr('ng-model', '$sgSearchController.searchField');
|
||||
selectEl.attr('ng-change', '$sgSearchController.onChange()');
|
||||
|
||||
return function postLink(scope, iElement, iAttr, controller) {
|
||||
$compile(mdInputEl)(scope);
|
||||
$compile(selectEl)(scope);
|
||||
$compile(tElement.find('md-button'))(scope.$parent);
|
||||
|
||||
scope.$watch('$sgSearchController.searchText', angular.bind(controller, controller.onChange));
|
||||
}
|
||||
}
|
||||
}])
|
||||
.controller('sgSearchController', ['$scope', '$element', function($scope, $element) {
|
||||
// Controller variables
|
||||
this.previous = { searchText: '', searchField: '' };
|
||||
this.searchText = '';
|
||||
this.searchField = $element.find('md-option').attr('value'); // defaults to first option
|
||||
|
||||
// Model options
|
||||
this.searchTextOptions = {
|
||||
updateOn: 'default blur',
|
||||
debounce: {
|
||||
default: 300,
|
||||
blur: 0
|
||||
}
|
||||
};
|
||||
|
||||
// Method to call on data changes
|
||||
this.onChange = function(value) {
|
||||
if (typeof this.searchText != 'undefined') {
|
||||
if (this.searchText != this.previous.searchText || this.searchField != this.previous.searchField) {
|
||||
if (this.searchText.length > 2 || this.searchText.length == 0) {
|
||||
// See https://github.com/angular/angular.js/issues/7635
|
||||
// for why we need to use $scope here
|
||||
$scope.doSearch({ searchText: this.searchText, searchField: this.searchField });
|
||||
}
|
||||
this.previous = { searchText: this.searchText, searchField: this.searchField };
|
||||
}
|
||||
}
|
||||
};
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgFolderStylesheet - Add CSS stylesheet for folder (addressbook or calendar)
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @restrict attribute
|
||||
* @param {object} ngModel - the object literal describing the folder (an Addressbook or Calendar instance)
|
||||
* @example:
|
||||
|
||||
<div sg-folder-stylesheet="true"
|
||||
ng-repeat="calendar in calendars.list"
|
||||
ng-model="calendar" />
|
||||
</div>
|
||||
*/
|
||||
.directive('sgFolderStylesheet', [function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
scope: {
|
||||
ngModel: '='
|
||||
},
|
||||
template: [
|
||||
'<style type="text/css">',
|
||||
' .bg-folder{{ ngModel.id }} {',
|
||||
' background-color: {{ ngModel.color }} !important;',
|
||||
' }',
|
||||
' .fg-folder{{ ngModel.id }} {',
|
||||
' color: {{ ngModel.color }} !important;',
|
||||
' }',
|
||||
' .checkbox-folder{{ ngModel.id }}.md-checked .md-icon {',
|
||||
' background-color: {{ ngModel.color }} !important;',
|
||||
' }',
|
||||
'</style>'
|
||||
].join('')
|
||||
}
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgCalendarDayTable - Build list of blocks for a specific day
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @restrict element
|
||||
* @param {object} sgBlocks - the events blocks definitions for the current view
|
||||
* @param {string} sgDay - the day of the events to display
|
||||
* @example:
|
||||
|
||||
<sg-calendar-day-table
|
||||
sg-blocks="calendar.blocks"
|
||||
sg-day="20150330" />
|
||||
*/
|
||||
.directive('sgCalendarDayTable', [function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
blocks: '=sgBlocks',
|
||||
day: '@sgDay'
|
||||
},
|
||||
template:
|
||||
'<sg-calendar-day-block class="event draggable"' +
|
||||
' ng-repeat="block in blocks[day]"' +
|
||||
' sg-block="block"/>',
|
||||
};
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgCalendarDayBlock - An event block to be displayed in a week
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @restrict element
|
||||
* @param {object} sgBlock - the event block definition
|
||||
* @example:
|
||||
|
||||
<sg-calendar-day-block
|
||||
ng-repeat="block in blocks[day]"
|
||||
sg-block="block"/>
|
||||
*/
|
||||
.directive('sgCalendarDayBlock', [function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
block: '=sgBlock'
|
||||
},
|
||||
replace: true,
|
||||
template: [
|
||||
'<div class="event draggable">',
|
||||
' <div class="eventInside">',
|
||||
' <div class="gradient">',
|
||||
' </div>',
|
||||
' <div class="text">{{ block.component.c_title }}',
|
||||
' <span class="icons">',
|
||||
' <i ng-if="block.component.c_nextalarm" class="md-icon-alarm"></i>',
|
||||
' <i ng-if="block.component.c_classification == 1" class="md-icon-visibility-off"></i>',
|
||||
' <i ng-if="block.component.c_classification == 2" class="md-icon-vpn-key"></i>',
|
||||
' </span></div>',
|
||||
' </div>',
|
||||
' <div class="topDragGrip"></div>',
|
||||
' <div class="bottomDragGrip"></div>',
|
||||
'</div>'
|
||||
].join(''),
|
||||
link: link
|
||||
};
|
||||
|
||||
function link(scope, iElement, attrs) {
|
||||
// Compute overlapping (5%)
|
||||
var pc = 100 / scope.block.siblings,
|
||||
left = scope.block.position * pc,
|
||||
right = 100 - (scope.block.position + 1) * pc;
|
||||
|
||||
if (pc < 100) {
|
||||
if (left > 0)
|
||||
left -= 5;
|
||||
if (right > 0)
|
||||
right -= 5;
|
||||
}
|
||||
|
||||
// Set position
|
||||
iElement.css('left', left + '%');
|
||||
iElement.css('right', right + '%');
|
||||
iElement.addClass('starts' + scope.block.start);
|
||||
iElement.addClass('lasts' + scope.block.length);
|
||||
iElement.addClass('bg-folder' + scope.block.component.c_folder);
|
||||
}
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgCalendarMonthDay - Build list of blocks for a specific day in a month
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @restrict element
|
||||
* @param {object} sgBlocks - the events blocks definitions for the current view
|
||||
* @param {string} sgDay - the day of the events to display
|
||||
* @example:
|
||||
|
||||
<sg-calendar-monh-day
|
||||
sg-blocks="calendar.blocks"
|
||||
sg-day="20150408" />
|
||||
*/
|
||||
.directive('sgCalendarMonthDay', [function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
blocks: '=sgBlocks',
|
||||
day: '@sgDay'
|
||||
},
|
||||
replace: true,
|
||||
template:
|
||||
'<sg-calendar-month-event' +
|
||||
' ng-repeat="block in blocks[day]"' +
|
||||
' sg-block="block"/>',
|
||||
};
|
||||
}])
|
||||
|
||||
/*
|
||||
* sgCalendarMonthEvent - An event block to be displayed in a month
|
||||
* @memberof SOGo.UIDesktop
|
||||
* @restrict element
|
||||
* @param {object} sgBlock - the event block definition
|
||||
* @example:
|
||||
|
||||
<sg-calendar-month-event
|
||||
ng-repeat="block in blocks[day]"
|
||||
sg-block="block"/>
|
||||
*/
|
||||
.directive('sgCalendarMonthEvent', [function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
block: '=sgBlock'
|
||||
},
|
||||
replace: true,
|
||||
template:
|
||||
'<div class="sg-event">' +
|
||||
' <span ng-if="!block.component.c_isallday">{{ block.starthour }} - </span>' +
|
||||
' {{ block.component.c_title }}' +
|
||||
' <span class="icons">' +
|
||||
' <i ng-if="block.component.c_nextalarm" class="md-icon-alarm"></i>' +
|
||||
' <i ng-if="block.component.c_classification == 1" class="md-icon-visibility-off"></i>' +
|
||||
' <i ng-if="block.component.c_classification == 2" class="md-icon-vpn-key"></i>' +
|
||||
' </span>' +
|
||||
' <div class="leftDragGrip"></div>' +
|
||||
' <div class="rightDragGrip"></div>' +
|
||||
' </div>' +
|
||||
'</div>',
|
||||
link: link
|
||||
};
|
||||
|
||||
function link(scope, iElement, attrs) {
|
||||
iElement.addClass('bg-folder' + scope.block.component.c_folder);
|
||||
}
|
||||
}]);
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/**
|
||||
* The common SOGo UI, app module
|
||||
*
|
||||
* @type {angular.Module}
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular.module('SOGo.UI', ['ngMaterial', 'ngAnimate'])
|
||||
// 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
|
||||
// For some reasons, angular-material's break-points don't match the specs
|
||||
// Here we define values according to specs
|
||||
.constant('sgConstant', {
|
||||
'sm': '(max-width: 600px)',
|
||||
'gt-sm': '(min-width: 600px)',
|
||||
'md': '(min-width: 600px) and (max-width: 1024px)',
|
||||
'gt-md': '(min-width: 1025px)',
|
||||
'lg': '(min-width: 1024px) and (max-width: 1280px)',
|
||||
'gt-lg': '(min-width: 1280px)'
|
||||
})
|
||||
|
||||
.config(['$mdThemingProvider', function ($mdThemingProvider) {
|
||||
|
||||
$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',
|
||||
'A200': '69f0ae',
|
||||
'A400': '00e676',
|
||||
'A700': '00c853',
|
||||
'contrastDefaultColor': 'dark',
|
||||
'contrastDarkColors': '50 100 200',
|
||||
'contrastLightColors': '300 400 500 600 700 800 900'
|
||||
});
|
||||
$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']
|
||||
});
|
||||
$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'
|
||||
});
|
||||
// Default theme definition
|
||||
// .primaryColor will soon be deprecated in favor of primaryPalette (already on dev builds https://groups.google.com/forum/m/#!topic/ngmaterial/-sXR8CYBMPg)
|
||||
$mdThemingProvider.theme('default')
|
||||
.primaryPalette('sogo-blue', {
|
||||
'default': '300',
|
||||
'hue-1': '100',
|
||||
'hue-2': '400',
|
||||
'hue-3': 'A700'
|
||||
})
|
||||
.accentPalette('sogo-green', {
|
||||
'default': '500',
|
||||
'hue-1': '200',
|
||||
'hue-2': '300',
|
||||
'hue-3': 'A700'
|
||||
})
|
||||
.backgroundPalette('sogo-paper', {
|
||||
'default': '100',
|
||||
'hue-1': '200',
|
||||
'hue-2': '50',
|
||||
'hue-3': '500'
|
||||
});
|
||||
}])
|
||||
|
||||
.filter('encodeUri', function ($window) {
|
||||
return $window.encodeURIComponent;
|
||||
})
|
||||
|
||||
.filter('decodeUri', function ($window) {
|
||||
return $window.decodeURIComponent;
|
||||
})
|
||||
|
||||
.filter('loc', function () {
|
||||
return l;
|
||||
})
|
||||
|
||||
.controller('navController', ['$scope', '$timeout', '$interval', '$http', '$mdSidenav', '$mdBottomSheet', '$mdMedia', '$log', 'sgConstant', function ($scope, $timeout, $interval, $http, $mdSidenav, $mdBottomSheet, $mdMedia, $log, sgConstant) {
|
||||
|
||||
// Show current day in top bar
|
||||
$scope.currentDay = window.currentDay;
|
||||
$timeout(function() {
|
||||
// Update date when day ends
|
||||
$interval(function() {
|
||||
$http.get('../date').success(function(data) {
|
||||
$scope.currentDay = data;
|
||||
});
|
||||
}, 24 * 3600 * 1000);
|
||||
}, window.secondsBeforeTomorrow * 1000);
|
||||
|
||||
$scope.toggleLeft = function () {
|
||||
$mdSidenav('left').toggle()
|
||||
.then(function () {
|
||||
$log.debug("toggle left is done");
|
||||
});
|
||||
};
|
||||
$scope.toggleRight = function () {
|
||||
$mdSidenav('right').toggle()
|
||||
.then(function () {
|
||||
$log.debug("toggle RIGHT is done");
|
||||
});
|
||||
};
|
||||
$scope.openBottomSheet = function() {
|
||||
$mdBottomSheet.show({
|
||||
parent: angular.element(document.getElementById('left-sidenav')),
|
||||
templateUrl: 'bottomSheetTemplate.html'
|
||||
});
|
||||
};
|
||||
$scope.toggleDetailView = function() {
|
||||
var detail = angular.element(document.getElementById('detailView'));
|
||||
detail.toggleClass('sg-close');
|
||||
};
|
||||
$scope.$watch(function() {
|
||||
return $mdMedia(sgConstant['gt-md']);
|
||||
},
|
||||
function(newVal) {
|
||||
$scope.isGtMedium = newVal;
|
||||
});
|
||||
}]);
|
||||
})();
|
||||
Reference in New Issue
Block a user