Improve display of tasks status

pull/236/head
Francis Lachapelle 2017-05-19 12:13:01 -04:00
parent c24474b197
commit f2af5e9f87
8 changed files with 57 additions and 11 deletions

2
NEWS
View File

@ -6,6 +6,8 @@ New features
Enhancements Enhancements
- [core] now possible to {un}subscribe to folders using sogo-tool - [core] now possible to {un}subscribe to folders using sogo-tool
- [web] AngularJS optimizations in Mail module
- [web] improve display of tasks status
Bug fixes Bug fixes
- [web] respect SOGoLanguage and SOGoSupportedLanguages (#4169) - [web] respect SOGoLanguage and SOGoSupportedLanguages (#4169)

View File

@ -1,6 +1,6 @@
/* iCalToDo+SOGo.h - this file is part of SOGo /* iCalToDo+SOGo.h - this file is part of SOGo
* *
* Copyright (C) 2007-2014 Inverse inc. * Copyright (C) 2007-2017 Inverse inc.
* *
* This file is free software; you can redistribute it and/or modify * This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -23,10 +23,17 @@
#import <NGCards/iCalToDo.h> #import <NGCards/iCalToDo.h>
#define taskStatusCompleted 1
#define taskStatusInProcess 2
#define taskStatusCancelled 3
#define taskStatusNeedsAction 4
@class NSMutableArray; @class NSMutableArray;
@interface iCalToDo (SOGoExtensions) @interface iCalToDo (SOGoExtensions)
+ (NSString *) statusForCode: (int) statusCode;
@end @end
#endif /* ICALTODO_SOGO_H */ #endif /* ICALTODO_SOGO_H */

View File

@ -1,6 +1,6 @@
/* iCalToDot+SOGo.m - this file is part of SOGo /* iCalToDot+SOGo.m - this file is part of SOGo
* *
* Copyright (C) 2008-2016 Inverse inc. * Copyright (C) 2008-2017 Inverse inc.
* *
* This file is free software; you can redistribute it and/or modify * This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -43,6 +43,20 @@
@implementation iCalToDo (SOGoExtensions) @implementation iCalToDo (SOGoExtensions)
+ (NSString *) statusForCode: (int) statusCode
{
if (statusCode == taskStatusCompleted)
return @"completed";
else if (statusCode == taskStatusInProcess)
return @"in-process";
else if (statusCode == taskStatusCancelled)
return @"cancelled";
else if (statusCode == taskStatusNeedsAction)
return @"needs-action";
return @"";
}
- (NSDictionary *) attributesInContext: (WOContext *) context - (NSDictionary *) attributesInContext: (WOContext *) context
{ {
BOOL isAllDayStartDate, isAllDayDueDate; BOOL isAllDayStartDate, isAllDayDueDate;
@ -305,19 +319,21 @@
if (completed || [status isNotNull]) if (completed || [status isNotNull])
{ {
code = 0; /* NEEDS-ACTION */ code = 0;
if (completed || [status isEqualToString: @"COMPLETED"]) if (completed || [status isEqualToString: @"COMPLETED"])
code = 1; code = taskStatusCompleted;
else if ([status isEqualToString: @"IN-PROCESS"]) else if ([status isEqualToString: @"IN-PROCESS"])
code = 2; code = taskStatusInProcess;
else if ([status isEqualToString: @"CANCELLED"]) else if ([status isEqualToString: @"CANCELLED"])
code = 3; code = taskStatusCancelled;
else if ([status isEqualToString: @"NEEDS-ACTION"])
code = taskStatusNeedsAction;
[row setObject: [NSNumber numberWithInt: code] forKey: @"c_status"]; [row setObject: [NSNumber numberWithInt: code] forKey: @"c_status"];
} }
else else
{ {
/* confirmed by default */ /* confirmed by default */
[row setObject:[NSNumber numberWithInt:1] forKey: @"c_status"]; [row setObject: [NSNumber numberWithInt: 0] forKey: @"c_status"];
} }
[row setObject: [NSNumber numberWithUnsignedInt: accessClass] [row setObject: [NSNumber numberWithUnsignedInt: accessClass]

View File

@ -46,6 +46,7 @@
#import <SOGo/NSArray+Utilities.h> #import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSObject+Utilities.h> #import <SOGo/NSObject+Utilities.h>
#import <SOGo/WOResourceManager+SOGo.h> #import <SOGo/WOResourceManager+SOGo.h>
#import <Appointments/iCalToDo+SOGo.h>
#import <Appointments/SOGoAppointmentFolders.h> #import <Appointments/SOGoAppointmentFolders.h>
#import <Appointments/SOGoWebAppointmentFolder.h> #import <Appointments/SOGoWebAppointmentFolder.h>
@ -1593,6 +1594,8 @@ _computeBlocksPosition (NSArray *blocks)
statusFlag = [self _getStatusClassForStatusCode: statusCode statusFlag = [self _getStatusClassForStatusCode: statusCode
andEndDateStamp: endDateStamp]; andEndDateStamp: endDateStamp];
[filteredTask addObject: statusFlag]; [filteredTask addObject: statusFlag];
statusFlag = [iCalToDo statusForCode: statusCode];
[filteredTask replaceObjectAtIndex: taskStatusIndex withObject: statusFlag];
if (endDateStamp > 0) if (endDateStamp > 0)
[filteredTask addObject: [self _formattedDateForSeconds: endDateStamp [filteredTask addObject: [self _formattedDateForSeconds: endDateStamp
forAllDay: NO]]; forAllDay: NO]];

View File

@ -634,6 +634,7 @@
ng-class="{ 'sg-list-selectable': list.mode.multiple }"> ng-class="{ 'sg-list-selectable': list.mode.multiple }">
<md-list-item ng-repeat="task in list.component.$tasks" <md-list-item ng-repeat="task in list.component.$tasks"
aria-label="{{::task.c_title}}" aria-label="{{::task.c_title}}"
ng-class="::task.c_status"
ng-click="list.openTask($event, task)"> ng-click="list.openTask($event, task)">
<div class="md-secondary sg-avatar-selectable" <div class="md-secondary sg-avatar-selectable"
label:aria-label="Toggle item" label:aria-label="Toggle item"
@ -654,11 +655,14 @@
</div> </div>
</div> </div>
<div class="sg-md-body"> <div class="sg-md-body">
<div><!-- spacer --></div> <div ng-bind="::task.c_location"><!-- location --></div>
<div>{{::task.formatted_enddate}}</div> <div ng-bind="::task.formatted_enddate"><!-- enddate --></div>
</div> </div>
</div> </div>
<div class="sg-tile-icons"> <div class="sg-tile-icons">
<md-icon ng-show="::(task.status == 'completed')">check</md-icon>
<md-icon ng-show="::(task.c_status == 'in-process')">timelapse</md-icon>
<md-icon ng-show="::(task.c_status == 'needs-action')">error_outline</md-icon>
<md-icon ng-show="::task.c_iscycle">repeat</md-icon> <md-icon ng-show="::task.c_iscycle">repeat</md-icon>
<md-icon ng-show="::task.c_nextalarm">alarm</md-icon> <md-icon ng-show="::task.c_nextalarm">alarm</md-icon>
</div> </div>

View File

@ -79,9 +79,17 @@
<p>{{editor.component.localizedCompletedDate}} {{editor.component.localizedCompletedTime}}</p> <p>{{editor.component.localizedCompletedDate}} {{editor.component.localizedCompletedTime}}</p>
</md-list-item> </md-list-item>
<md-list-item ng-show="editor.component.enablePercentComplete()"> <md-list-item ng-show="editor.component.enablePercentComplete()">
<md-icon>call_made</md-icon> <md-icon>timelapse</md-icon>
<p>{{editor.component.percentComplete}} %</p> <p>{{editor.component.percentComplete}} %</p>
</md-list-item> </md-list-item>
<md-list-item ng-show="editor.component.status == 'cancelled'">
<md-icon>close</md-icon>
<p><var:string label:value="status_CANCELLED"/></p>
</md-list-item>
<md-list-item ng-show="editor.component.status == 'needs-action'">
<md-icon>error_outline</md-icon>
<p><var:string label:value="status_NEEDS-ACTION"/></p>
</md-list-item>
<!-- attach urls --> <!-- attach urls -->
<md-list-item ng-repeat="url in ::editor.component.attachUrls"> <md-list-item ng-repeat="url in ::editor.component.attachUrls">
<md-icon>link</md-icon> <md-icon>link</md-icon>

View File

@ -698,7 +698,7 @@
*/ */
Component.prototype.enablePercentComplete = function() { Component.prototype.enablePercentComplete = function() {
return (this.type == 'task' && return (this.type == 'task' &&
this.status != 'not-specified' && this.percentComplete > 0 &&
this.status != 'cancelled'); this.status != 'cancelled');
}; };

View File

@ -647,6 +647,12 @@ $quarter_height: 10px;
} }
} }
/* Tasks list */
.cancelled .sg-md-subhead {
text-decoration: line-through;
}
/* Attendees dialog Editor */ /* Attendees dialog Editor */
.attendees { .attendees {
max-height: ($list-item-height * 20); // show a maximum of 20 attendees max-height: ($list-item-height * 20); // show a maximum of 20 attendees