mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-08-31 19:27:18 +00:00
Initial component editor in Scheduler module
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
function Component(futureComponentData) {
|
||||
// Data is immediately available
|
||||
if (typeof futureComponentData.then !== 'function') {
|
||||
angular.extend(this, futureComponentData);
|
||||
this.init(futureComponentData);
|
||||
}
|
||||
else {
|
||||
// The promise will be unwrapped first
|
||||
@@ -29,7 +29,8 @@
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
$$resource: new Resource(Settings.baseURL, Settings.activeUser)
|
||||
$$resource: new Resource(Settings.baseURL, Settings.activeUser),
|
||||
$categories: window.UserDefaults.SOGoCalendarCategoriesColors
|
||||
});
|
||||
|
||||
return Component; // return constructor
|
||||
@@ -73,6 +74,33 @@
|
||||
return this.$unwrapCollection(type, futureComponentData);
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Card
|
||||
* @desc Fetch a card from a specific addressbook.
|
||||
* @param {string} addressbook_id - the addressbook ID
|
||||
* @param {string} card_id - the card ID
|
||||
* @see {@link AddressBook.$getCard}
|
||||
*/
|
||||
Component.$find = function(calendarId, componentId) {
|
||||
var futureComponentData = this.$$resource.fetch([calendarId, componentId].join('/'), 'view');
|
||||
|
||||
return new Component(futureComponentData);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function filterCategories
|
||||
* @memberof Component.prototype
|
||||
* @desc Search for categories matching some criterias
|
||||
* @param {string} search - the search string to match
|
||||
* @returns a collection of strings
|
||||
*/
|
||||
Component.filterCategories = function(query) {
|
||||
var re = new RegExp(query, 'i');
|
||||
return _.filter(_.keys(Component.$categories), function(category) {
|
||||
return category.search(re) != -1;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $eventsBlocksForView
|
||||
* @memberof Component.prototype
|
||||
@@ -198,6 +226,56 @@
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
Component.prototype.init = function(data) {
|
||||
this.categories = [];
|
||||
angular.extend(this, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function getClassName
|
||||
* @memberof Component.prototype
|
||||
* @desc Return the component CSS class name based on its container (calendar) ID.
|
||||
* @param {string} [base] - the prefix to add to the class name (defaults to "fg")
|
||||
* @returns a string representing the foreground CSS class name
|
||||
*/
|
||||
Component.prototype.getClassName = function(base) {
|
||||
if (angular.isUndefined(base))
|
||||
base = 'fg';
|
||||
return base + '-folder' + (this.pid || this.c_folder);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $reset
|
||||
* @memberof Card.prototype
|
||||
* @desc Reset the original state the card's data.
|
||||
*/
|
||||
Component.prototype.$reset = function() {
|
||||
var _this = this;
|
||||
angular.forEach(this, function(value, key) {
|
||||
if (key != 'constructor' && key[0] != '$') {
|
||||
delete _this[key];
|
||||
}
|
||||
});
|
||||
angular.extend(this, this.$shadowData);
|
||||
this.$shadowData = this.$omit(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $save
|
||||
* @memberof Component.prototype
|
||||
* @desc Save the component to the server.
|
||||
*/
|
||||
Component.prototype.$save = function() {
|
||||
var _this = this;
|
||||
|
||||
return Component.$$resource.save([this.pid, this.id].join('/'), this.$omit())
|
||||
.then(function(data) {
|
||||
// Make a copy of the data for an eventual reset
|
||||
_this.$shadowData = _this.$omit(true);
|
||||
return data;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $unwrap
|
||||
* @memberof Component.prototype
|
||||
@@ -215,7 +293,9 @@
|
||||
this.$futureComponentData.then(function(data) {
|
||||
// Calling $timeout will force Angular to refresh the view
|
||||
Component.$timeout(function() {
|
||||
angular.extend(_this, data);
|
||||
_this.init(data);
|
||||
// Make a copy of the data for an eventual reset
|
||||
_this.$shadowData = _this.$omit();
|
||||
deferred.resolve(_this);
|
||||
});
|
||||
}, function(data) {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
template:
|
||||
'<h2 data-ng-bind-html="title"></h2>' +
|
||||
'<p data-ng-bind-html="content"></p>' +
|
||||
'<a class="button button-primary" ng-click="closeModal()">' + l('OK') + '</a>' +
|
||||
'<a class="button md-primary" ng-click="closeModal()">' + l('OK') + '</a>' +
|
||||
'<span class="close-reveal-modal" ng-click="closeModal()"><i class="icon-close"></i></span>',
|
||||
windowClass: 'small',
|
||||
controller: function($scope, $modalInstance) {
|
||||
@@ -455,7 +455,7 @@
|
||||
* @param {Function} sgSubscribeOnSelect - the function to call when subscribing to a folder
|
||||
* @example:
|
||||
|
||||
<div sg-subscribe="contact" sg-subscribe-on-select="subscribeToFolder"></div>
|
||||
<md-button sg-subscribe="contact" sg-subscribe-on-select="subscribeToFolder">Subscribe ..</md-button>
|
||||
*/
|
||||
.directive('sgSubscribe', [function() {
|
||||
console.debug('registering sgSubscribe');
|
||||
@@ -466,11 +466,8 @@
|
||||
onFolderSelect: '&sgSubscribeOnSelect'
|
||||
},
|
||||
replace: false,
|
||||
link: function(scope, element, attrs, controller) {
|
||||
element.on('click', controller.showDialog);
|
||||
},
|
||||
controllerAs: 'vm',
|
||||
bindToController: true,
|
||||
controllerAs: 'vm',
|
||||
controller: ['$scope', '$mdDialog', function($scope, $mdDialog) {
|
||||
var vm = this;
|
||||
vm.showDialog = function() {
|
||||
@@ -495,6 +492,9 @@
|
||||
});
|
||||
};
|
||||
}],
|
||||
link: function(scope, element, attrs, controller) {
|
||||
element.on('click', controller.showDialog);
|
||||
}
|
||||
};
|
||||
}])
|
||||
|
||||
@@ -704,9 +704,12 @@
|
||||
},
|
||||
template:
|
||||
'<style type="text/css">' +
|
||||
' .folder{{ ngModel.id }} {' +
|
||||
' .bg-folder{{ ngModel.id }} {' +
|
||||
' background-color: {{ ngModel.color }} !important;' +
|
||||
' }' +
|
||||
' .fg-folder{{ ngModel.id }} {' +
|
||||
' color: {{ ngModel.color }} !important;' +
|
||||
' }' +
|
||||
'</style>'
|
||||
}
|
||||
}])
|
||||
@@ -755,16 +758,22 @@
|
||||
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"></span></div>' +
|
||||
' </div>' +
|
||||
' <div class="topDragGrip"></div>' +
|
||||
' <div class="bottomDragGrip"></div>' +
|
||||
'</div>',
|
||||
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
|
||||
};
|
||||
|
||||
@@ -786,7 +795,7 @@
|
||||
iElement.css('right', right + '%');
|
||||
iElement.addClass('starts' + scope.block.start);
|
||||
iElement.addClass('lasts' + scope.block.length);
|
||||
iElement.addClass('folder' + scope.block.component.c_folder);
|
||||
iElement.addClass('bg-folder' + scope.block.component.c_folder);
|
||||
}
|
||||
}])
|
||||
|
||||
@@ -852,7 +861,7 @@
|
||||
};
|
||||
|
||||
function link(scope, iElement, attrs) {
|
||||
iElement.addClass('folder' + scope.block.component.c_folder);
|
||||
iElement.addClass('bg-folder' + scope.block.component.c_folder);
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
angular.module('SOGo.Common', []);
|
||||
angular.module('SOGo.ContactsUI', []);
|
||||
|
||||
angular.module('SOGo.SchedulerUI', ['ngSanitize', 'ui.router', 'vs-repeat', 'SOGo.Common', 'SOGo.UI', 'SOGo.UIDesktop', 'SOGo.ContactsUI'])
|
||||
angular.module('SOGo.SchedulerUI', ['ngSanitize', 'ui.router', 'ct.ui.router.extras.sticky', 'ct.ui.router.extras.previous', 'vs-repeat', 'SOGo.Common', 'SOGo.UI', 'SOGo.UIDesktop', 'SOGo.ContactsUI'])
|
||||
|
||||
.constant('sgSettings', {
|
||||
baseURL: ApplicationBaseURL,
|
||||
@@ -39,6 +39,8 @@
|
||||
})
|
||||
.state('calendars.view', {
|
||||
url: '/{view:(?:day|week|month)}/:day',
|
||||
sticky: true,
|
||||
deepStateRedirect: true,
|
||||
views: {
|
||||
calendarView: {
|
||||
templateUrl: function($stateParams) {
|
||||
@@ -56,6 +58,21 @@
|
||||
return Component.$eventsBlocksForView($stateParams.view, $stateParams.day.asDate());
|
||||
}]
|
||||
}
|
||||
})
|
||||
.state('calendars.component', {
|
||||
url: '/:calendarId/event/:componentId',
|
||||
views: {
|
||||
componentEditor: {
|
||||
templateUrl: 'UIxAppointmentEditorTemplate',
|
||||
controller: 'ComponentController',
|
||||
controllerAs: 'editor'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
stateComponent: ['$stateParams', 'sgCalendar', function($stateParams, Calendar) {
|
||||
return Calendar.$get($stateParams.calendarId).$getComponent($stateParams.componentId);
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
$urlRouterProvider.when('/calendar/day', function() {
|
||||
@@ -198,7 +215,7 @@
|
||||
};
|
||||
}])
|
||||
|
||||
.controller('CalendarListController', ['$scope', '$rootScope', '$timeout', 'sgFocus', 'encodeUriFilter', 'sgDialog', 'sgSettings', 'sgCalendar', 'sgComponent', function($scope, $rootScope, $timeout, focus, encodeUriFilter, Dialog, Settings, Calendar, Component) {
|
||||
.controller('CalendarListController', ['$scope', '$rootScope', '$timeout', 'sgFocus', 'encodeUriFilter', 'sgDialog', 'sgSettings', 'sgCalendar', 'sgComponent', '$mdSidenav', function($scope, $rootScope, $timeout, focus, encodeUriFilter, Dialog, Settings, Calendar, Component, $mdSidenav) {
|
||||
// Scope variables
|
||||
this.component = Component;
|
||||
this.componentType = null;
|
||||
@@ -241,6 +258,64 @@
|
||||
ctrl.blocks = data;
|
||||
});
|
||||
}));
|
||||
}])
|
||||
|
||||
.controller('ComponentController', ['$scope', '$log', '$timeout', '$state', '$previousState', '$mdSidenav', '$mdDialog', 'sgCalendar', 'sgComponent', 'stateCalendars', 'stateComponent', function($scope, $log, $timeout, $state, $previousState, $mdSidenav, $mdDialog, Calendar, Component, stateCalendars, stateComponent) {
|
||||
var vm = this;
|
||||
|
||||
vm.calendars = stateCalendars;
|
||||
vm.event = stateComponent;
|
||||
vm.categories = {};
|
||||
vm.editRecurrence = editRecurrence;
|
||||
vm.cancel = cancel;
|
||||
vm.save = save;
|
||||
|
||||
$scope.$on('$viewContentLoaded', function(event) {
|
||||
$timeout(function() {
|
||||
$mdSidenav('right').open()
|
||||
.then(function() {
|
||||
$scope.$watch($mdSidenav('right').isOpen, function(isOpen, wasOpen) {
|
||||
if (!isOpen) {
|
||||
if ($previousState.get())
|
||||
$previousState.go()
|
||||
else
|
||||
$state.go('calendars');
|
||||
}
|
||||
});
|
||||
});
|
||||
}, 100); // don't ask why
|
||||
});
|
||||
|
||||
function editRecurrence($event) {
|
||||
$mdDialog.show({
|
||||
templateUrl: 'editRecurrence', // UI/Templates/SchedulerUI/UIxRecurrenceEditor.wox
|
||||
controller: RecurrenceController
|
||||
});
|
||||
function RecurrenceController() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function save(form) {
|
||||
if (form.$valid) {
|
||||
vm.event.$save()
|
||||
.then(function(data) {
|
||||
$scope.$emit('calendars:list');
|
||||
$mdSidenav('right').close();
|
||||
}, function(data, status) {
|
||||
console.debug('failed');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
vm.event.$reset();
|
||||
if (vm.event.isNew) {
|
||||
// Cancelling the creation of a card
|
||||
vm.event = null;
|
||||
}
|
||||
$mdSidenav('right').close();
|
||||
}
|
||||
}]);
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user