From a75524af9f671ef92316c8e6b4a229d5fc1c78d8 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 21 Jul 2015 08:26:50 -0400 Subject: [PATCH] Review task/event viewer/editor Components will now appear in dialogs instead of a right sidenav. This commit also introduces read-only viewers for tasks and events. --- UI/Scheduler/UIxCalMainView.m | 22 +++ UI/Scheduler/UIxTaskEditor.m | 3 +- .../ContactsUI/UIxContactViewTemplate.wox | 2 +- .../UIxAppointmentEditorTemplate.wox | 65 ++++---- .../UIxAppointmentViewTemplate.wox | 123 ++++++++++++++ UI/Templates/SchedulerUI/UIxCalMainView.wox | 150 +++++++++--------- .../SchedulerUI/UIxReminderEditor.wox | 3 +- .../SchedulerUI/UIxTaskEditorTemplate.wox | 90 ++++++----- .../SchedulerUI/UIxTaskViewTemplate.wox | 103 ++++++++++++ UI/WebServerResources/js/Scheduler.app.js | 63 -------- .../js/Scheduler/CalendarListController.js | 53 ++++++- .../js/Scheduler/ComponentController.js | 77 ++++++--- .../scss/components/chips/chips.scss | 7 +- .../scss/components/icon/icon.scss | 18 ++- .../scss/components/list/list.scss | 2 +- 15 files changed, 530 insertions(+), 251 deletions(-) create mode 100644 UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox create mode 100644 UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox diff --git a/UI/Scheduler/UIxCalMainView.m b/UI/Scheduler/UIxCalMainView.m index 49da84a8b..6a9839584 100644 --- a/UI/Scheduler/UIxCalMainView.m +++ b/UI/Scheduler/UIxCalMainView.m @@ -329,6 +329,24 @@ @end +/* Appointment Viewer */ + +@interface UIxAppointmentViewTemplate : UIxComponent +@end + +@implementation UIxAppointmentViewTemplate +@end + +/* Task Viewer */ + +@interface UIxTaskViewTemplate : UIxComponent +@end + +@implementation UIxTaskViewTemplate +@end + +/* Component Editor, parent class of Appointment Editor and Task Editor */ + @interface UIxComponentEditorTemplate : UIxComponent { id item; @@ -388,12 +406,16 @@ @end +/* Appointment Editor */ + @interface UIxAppointmentEditorTemplate : UIxComponentEditorTemplate @end @implementation UIxAppointmentEditorTemplate @end +/* Task Editor */ + @interface UIxTaskEditorTemplate : UIxComponentEditorTemplate @end diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index c83d5d7b9..1c0d38004 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -433,7 +433,8 @@ * @apiSuccess (Success 200) {String} location Location * @apiSuccess (Success 200) {String} comment Comment * @apiSuccess (Success 200) {String} createdBy Value of custom header X-SOGo-Component-Created-By or organizer's "SENT-BY" - * @apiSuccess (Success 200) {Number} priority Priority + * @apiSuccess (Success 200) {Number} priority Priority (0-9) + * @apiSuccess (Success 200) {NSString} [classification] Either public, confidential or private * @apiSuccess (Success 200) {String[]} [categories] Categories * @apiSuccess (Success 200) {String} status Status (needs-action, in-process, completed, or cancelled) * @apiSuccess (Success 200) {Object} [organizer] Appointment organizer diff --git a/UI/Templates/ContactsUI/UIxContactViewTemplate.wox b/UI/Templates/ContactsUI/UIxContactViewTemplate.wox index 92898c4e9..8f2a62a10 100644 --- a/UI/Templates/ContactsUI/UIxContactViewTemplate.wox +++ b/UI/Templates/ContactsUI/UIxContactViewTemplate.wox @@ -21,7 +21,7 @@

{{editor.card.$description()}}
+ class="sg-readonly" readonly="true"> {{$chip.value}} diff --git a/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox b/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox index 073716462..25376d9be 100644 --- a/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox +++ b/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox @@ -3,44 +3,48 @@ xmlns="http://www.w3.org/1999/xhtml" xmlns:var="http://www.skyrix.com/od/binding" xmlns:const="http://www.skyrix.com/od/constant" - xmlns:label="OGo:label" - > -
- - - - - + xmlns:label="OGo:label"> + + + +
+ + visibility_off + vpn_key + + + + + close + +
+
-
- + -
- - - {{category}} - - -
+ + + {{category}} + + - + {{calendar.name}} @@ -137,7 +141,7 @@
- + @@ -159,7 +163,7 @@
- + @@ -226,8 +230,9 @@ ng-show="editor.component.$hasAlarm">
+ -
+
@@ -238,6 +243,6 @@
- + diff --git a/UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox b/UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox new file mode 100644 index 000000000..0762df549 --- /dev/null +++ b/UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox @@ -0,0 +1,123 @@ + + + +
+ +
+ event +

+ + visibility_off + vpn_key + + {{viewer.component.summary}} + + star +

+ + close + +
+
+ + + + + + + {{$chip}} + + + + + + place +

{{viewer.component.location}}

+
+ + + event +

{{viewer.component.calendar}}

+
+ + + access_time +
+
+

+

+ {{viewer.component.localizedStartDate}} + {{viewer.component.localizedStartTime}} +

+
+
+

+

+ {{viewer.component.localizedEndDate}} + {{viewer.component.localizedEndTime}} +

+
+
+
+ + + event_available +

+
+ + + send +

+
+ + + link +

{{url.value}}

+
+ + + mode_comment +

{{viewer.component.comment}}

+
+ + + repeat +

+
+ + + alarm +

+
+ + +
+ +
+ + + +
+
+
+
+ +
+ +
+
+ +
+ + + +
+
+
+
diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index e7cab4389..b824ffd1b 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -180,29 +180,29 @@ md-menu-origin="md-menu-origin">more_vert - + - + - + - + - + @@ -238,19 +238,19 @@ md-menu-origin="md-menu-origin">more_vert - + - + - + @@ -285,19 +285,19 @@ md-menu-origin="md-menu-origin">more_vert - + - + - + @@ -321,7 +321,7 @@
-
+
@@ -383,25 +383,25 @@ - + - + - + - + @@ -410,7 +410,7 @@ + ng-false-value="0"> @@ -530,77 +530,71 @@
-
- - - - - - -
-

{{event.c_title}}

-

{{event.c_location}}

-

- {{event.formatted_startdate}} - - repeat - alarm - -

-
-
- -

-
-
-
- - - - -
-

{{task.c_title}}

-

- {{task.formatted_enddate}} - - repeat - alarm - -

-
-
- -

-
-
-
-
-
+ + + + + + + +
+

{{event.c_title}}

+

{{event.c_location}}

+

+ {{event.formatted_startdate}} + + repeat + alarm + +

+
+
+ +

+
+
+
+ + + + + +
+

{{task.c_title}}

+

+ {{task.formatted_enddate}} + + repeat + alarm + +

+
+
+ +

+
+
+
+
+ ng-click="list.newComponent($event)"> add -
+
- - diff --git a/UI/Templates/SchedulerUI/UIxReminderEditor.wox b/UI/Templates/SchedulerUI/UIxReminderEditor.wox index cd1585fa5..81e707b4e 100644 --- a/UI/Templates/SchedulerUI/UIxReminderEditor.wox +++ b/UI/Templates/SchedulerUI/UIxReminderEditor.wox @@ -3,8 +3,7 @@ xmlns="http://www.w3.org/1999/xhtml" xmlns:var="http://www.skyrix.com/od/binding" xmlns:const="http://www.skyrix.com/od/constant" - xmlns:label="OGo:label" - > + xmlns:label="OGo:label">
diff --git a/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox b/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox index 91d072be5..c5046dd4f 100644 --- a/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox +++ b/UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox @@ -3,40 +3,45 @@ xmlns="http://www.w3.org/1999/xhtml" xmlns:var="http://www.skyrix.com/od/binding" xmlns:const="http://www.skyrix.com/od/constant" - xmlns:label="OGo:label" - > -
- - - - - - - + xmlns:label="OGo:label"> + + + +
+ + visibility_off + vpn_key + + + + + close + +
+
+ -
- - - {{category}} - - -
+ + + {{category}} + + - + {{calendar.name}} @@ -86,14 +91,14 @@
-
- + + -
+ @@ -108,7 +113,7 @@ min="0" max="100" label:aria-label="% complete"> -
+
{{editor.component.percentComplete}}
@@ -192,18 +197,19 @@ ng-show="editor.component.$hasAlarm">
- -
- - - - - - - - - -
- + + +
+ + + + + + + + + +
+ diff --git a/UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox b/UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox new file mode 100644 index 000000000..a399aafea --- /dev/null +++ b/UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox @@ -0,0 +1,103 @@ + + + + +
+ assignment_turned_in +

+ + visibility_off + vpn_key + + {{viewer.component.summary}} + + star +

+ + close + +
+
+ + + + + + + {{$chip}} + + + + + + place +

{{viewer.component.location}}

+
+ + + event +

{{viewer.component.calendar}}

+
+ + + access_time +
+
+

+

+ {{viewer.component.localizedStartDate}} + {{viewer.component.localizedStartTime}} +

+
+
+

+

+ {{viewer.component.localizedDueDate}} + {{viewer.component.localizedDueTime}} +

+
+
+
+ + + check +

{{viewer.component.localizedCompletedDate}} {{viewer.component.localizedCompletedTime}}

+
+ + call_made +

{{viewer.component.percentComplete}} %

+
+ + + link +

{{url.value}}

+
+ + + mode_comment +

{{viewer.component.comment}}

+
+ + + repeat +

+
+ + + alarm +

+
+
+
+ +
+ + + +
+
+
diff --git a/UI/WebServerResources/js/Scheduler.app.js b/UI/WebServerResources/js/Scheduler.app.js index 208a0d491..e5fb1c7a9 100644 --- a/UI/WebServerResources/js/Scheduler.app.js +++ b/UI/WebServerResources/js/Scheduler.app.js @@ -61,46 +61,6 @@ resolve: { stateEventsBlocks: stateEventsBlocks } - }) - .state('calendars.newComponent', { - url: '/:calendarId/{componentType:(?:appointment|task)}/new', - views: { - componentEditor: { - templateUrl: function($stateParams) { - // UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or - // UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox - return 'UIx' + $stateParams.componentType.capitalize() + 'EditorTemplate'; - }, - controller: 'ComponentController', - controllerAs: 'editor' - } - }, - resolve: { - stateComponent: stateNewComponent - } - }) - .state('calendars.component', { - url: '/:calendarId/{componentType:(?:appointment|task)}/:componentId', - views: { - componentEditor: { - templateUrl: function($stateParams) { - // UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or - // UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox - return 'UIx' + $stateParams.componentType.capitalize() + 'EditorTemplate'; - }, - controller: 'ComponentController', - controllerAs: 'editor' - } - }, - // onEnter: ['$mdSidenav', function($mdSidenav) { - // $mdSidenav('right').open() - // .then(function() { - // console.debug("toggle RIGHT is done"); - // }); - // }], - resolve: { - stateComponent: stateComponent - } }); $urlRouterProvider.when('/calendar/day', function() { @@ -139,29 +99,6 @@ return Component.$eventsBlocksForView($stateParams.view, $stateParams.day.asDate()); } - /** - * @ngInject - */ - stateNewComponent.$inject = ['$stateParams', 'Component']; - function stateNewComponent($stateParams, Component) { - var component = new Component({ pid: $stateParams.calendarId, type: $stateParams.componentType }); - return component; - } - - /** - * @ngInject - */ - stateComponent.$inject = ['$q', '$stateParams', 'Calendar']; - function stateComponent($q, $stateParams, Calendar) { - var component = Calendar.$get($stateParams.calendarId).$getComponent($stateParams.componentId); - - return $q(function(resolve, reject) { - component.$futureComponentData.then(function() { - resolve(component); - }, reject); - }); - } - /** * @ngInject */ diff --git a/UI/WebServerResources/js/Scheduler/CalendarListController.js b/UI/WebServerResources/js/Scheduler/CalendarListController.js index c81fcbb06..900bfc602 100644 --- a/UI/WebServerResources/js/Scheduler/CalendarListController.js +++ b/UI/WebServerResources/js/Scheduler/CalendarListController.js @@ -6,14 +6,16 @@ /** * @ngInject */ - CalendarListController.$inject = ['$scope', '$rootScope', '$timeout', '$state', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'Preferences', 'Calendar', 'Component', '$mdSidenav']; - function CalendarListController($scope, $rootScope, $timeout, $state, focus, encodeUriFilter, Dialog, Settings, Preferences, Calendar, Component, $mdSidenav) { + CalendarListController.$inject = ['$scope', '$timeout', '$state', '$mdDialog', 'encodeUriFilter', 'Dialog', 'Preferences', 'Calendar', 'Component']; + function CalendarListController($scope, $timeout, $state, $mdDialog, encodeUriFilter, Dialog, Preferences, Calendar, Component) { var vm = this; vm.component = Component; vm.componentType = 'events'; vm.selectedList = 0; vm.selectComponentType = selectComponentType; + vm.openEvent = openEvent; + vm.openTask = openTask; vm.newComponent = newComponent; vm.filter = filter; vm.filteredBy = filteredBy; @@ -42,13 +44,54 @@ } } - function newComponent() { - var type = 'appointment'; + function openEvent($event, event) { + openComponent($event, event, 'appointment'); + } + + function openTask($event, task) { + openComponent($event, task, 'task'); + } + + function openComponent($event, component, type) { + // UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox or + // UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox + var templateUrl = 'UIx' + type.capitalize() + 'ViewTemplate'; + $mdDialog.show({ + parent: angular.element(document.body), + targetEvent: $event, + clickOutsideToClose: true, + escapeToClose: true, + templateUrl: templateUrl, + controller: 'ComponentController', + controllerAs: 'viewer', + locals: { + stateComponent: component + } + }); + } + + function newComponent($event) { + var type = 'appointment', component; if (vm.componentType == 'tasks') type = 'task'; + component = new Component({ pid: 'personal', type: type }); - $state.go('calendars.newComponent', { calendarId: 'personal', componentType: type }); + // UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or + // UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox + var templateUrl = 'UIx' + type.capitalize() + 'EditorTemplate'; + $mdDialog.show({ + parent: angular.element(document.body), + targetEvent: $event, + clickOutsideToClose: true, + escapeToClose: true, + templateUrl: templateUrl, + controller: 'ComponentEditorController', + controllerAs: 'editor', + locals: { + stateComponent: component + } + }); } function filter(filterpopup) { diff --git a/UI/WebServerResources/js/Scheduler/ComponentController.js b/UI/WebServerResources/js/Scheduler/ComponentController.js index 0b08c0fb3..30f256def 100644 --- a/UI/WebServerResources/js/Scheduler/ComponentController.js +++ b/UI/WebServerResources/js/Scheduler/ComponentController.js @@ -6,11 +6,55 @@ /** * @ngInject */ - ComponentController.$inject = ['$scope', '$log', '$q', '$timeout', '$state', '$previousState', '$mdSidenav', '$mdDialog', 'User', 'Calendar', 'Component', 'AddressBook', 'Card', 'stateCalendars', 'stateComponent']; - function ComponentController($scope, $log, $q, $timeout, $state, $previousState, $mdSidenav, $mdDialog, User, Calendar, Component, AddressBook, Card, stateCalendars, stateComponent) { - var vm = this; + ComponentController.$inject = ['$mdDialog', 'Calendar', 'stateComponent']; + function ComponentController($mdDialog, Calendar, stateComponent) { + var vm = this, component; - vm.calendars = stateCalendars; + vm.component = stateComponent; + vm.close = close; + vm.edit = edit; + + // Load all attributes of component + if (angular.isUndefined(vm.component.$futureComponentData)) { + component = Calendar.$get(vm.component.c_folder).$getComponent(vm.component.c_name); + component.$futureComponentData.then(function() { + vm.component = component; + }); + } + + function close() { + $mdDialog.hide(); + } + + function edit() { + var type = (vm.component.component == 'vevent')? 'Appointment':'Task'; + $mdDialog.hide().then(function() { + // UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or + // UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox + var templateUrl = 'UIx' + type + 'EditorTemplate'; + $mdDialog.show({ + parent: angular.element(document.body), + clickOutsideToClose: true, + escapeToClose: true, + templateUrl: templateUrl, + controller: 'ComponentEditorController', + controllerAs: 'editor', + locals: { + stateComponent: vm.component + } + }); + }); + } + } + + /** + * @ngInject + */ + ComponentEditorController.$inject = ['$scope', '$log', '$timeout', '$mdDialog', 'User', 'Calendar', 'Component', 'AddressBook', 'Card', 'stateComponent']; + function ComponentEditorController($scope, $log, $timeout, $mdDialog, User, Calendar, Component, AddressBook, Card, stateComponent) { + var vm = this, component; + + vm.calendars = Calendar.$calendars; vm.component = stateComponent; vm.categories = {}; vm.showRecurrenceEditor = vm.component.$hasCustomRepeat; @@ -30,24 +74,6 @@ hours: getHours() }; - // Open sidenav when loading the view; - // Return to previous state when closing the sidenav. - $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 - }); - $scope.$watch('editor.component.startDate', function(newStartDate, oldStartDate) { if (newStartDate) { $timeout(function() { @@ -130,7 +156,7 @@ vm.component.$save() .then(function(data) { $scope.$emit('calendars:list'); - $mdSidenav('right').close(); + $mdDialog.hide(); }, function(data, status) { $log.debug('failed'); }); @@ -143,7 +169,7 @@ // Cancelling the creation of a component vm.component = null; } - $mdSidenav('right').close(); + $mdDialog.hide(); } function getDays() { @@ -170,5 +196,6 @@ angular .module('SOGo.SchedulerUI') - .controller('ComponentController', ComponentController); + .controller('ComponentController', ComponentController) + .controller('ComponentEditorController', ComponentEditorController); })(); diff --git a/UI/WebServerResources/scss/components/chips/chips.scss b/UI/WebServerResources/scss/components/chips/chips.scss index 6a231b926..c7330a608 100644 --- a/UI/WebServerResources/scss/components/chips/chips.scss +++ b/UI/WebServerResources/scss/components/chips/chips.scss @@ -2,13 +2,16 @@ @import 'extends'; // Remove the line under the tags of the message viewer -.msg-header { - md-chips { +md-chips { + &.sg-readonly { .md-chips { box-shadow: none; &.md-focused { box-shadow: none; } + .md-chip-content { + max-width: initial; // fix bug in ng-material + } } } } \ No newline at end of file diff --git a/UI/WebServerResources/scss/components/icon/icon.scss b/UI/WebServerResources/scss/components/icon/icon.scss index 4e6c4e942..e3c03f619 100644 --- a/UI/WebServerResources/scss/components/icon/icon.scss +++ b/UI/WebServerResources/scss/components/icon/icon.scss @@ -45,6 +45,13 @@ // Define CSS styles to use ng-class with md-icon md-icon { transition: 240ms; + &.sg-icon-toolbar-bg { + font-size: 84px; + opacity: 0.2; + position: absolute; + right: $mg * 3; + transform: rotate(-15deg); + } &.md-rotate-45 { transform: rotate(45deg); } @@ -56,7 +63,10 @@ md-icon { } // &.icon-add:before { // content: "\e317"; -// } + // } + &.icon-alarm:before { + content: "\e855"; + } &.icon-check:before { content: "\e5ca"; } @@ -81,6 +91,12 @@ md-icon { // &.icon_public:before { // content: "\e80b"; // } + &.icon-visibility-off:before { + content: "\e8f5"; + } + &.icon-vpn-key:before { + content: "\e0da"; + } } // Message flag diff --git a/UI/WebServerResources/scss/components/list/list.scss b/UI/WebServerResources/scss/components/list/list.scss index 077911fd3..9f57d5395 100644 --- a/UI/WebServerResources/scss/components/list/list.scss +++ b/UI/WebServerResources/scss/components/list/list.scss @@ -46,7 +46,7 @@ md-list-item { // Add some padding to the first icon in a list item .md-list-item-inner { > i:first-child { - padding-right: $mg; + margin-left: $mg; } }