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
- [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
- [web] respect SOGoLanguage and SOGoSupportedLanguages (#4169)

View File

@ -1,6 +1,6 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -23,10 +23,17 @@
#import <NGCards/iCalToDo.h>
#define taskStatusCompleted 1
#define taskStatusInProcess 2
#define taskStatusCancelled 3
#define taskStatusNeedsAction 4
@class NSMutableArray;
@interface iCalToDo (SOGoExtensions)
+ (NSString *) statusForCode: (int) statusCode;
@end
#endif /* ICALTODO_SOGO_H */

View File

@ -1,6 +1,6 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -43,6 +43,20 @@
@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
{
BOOL isAllDayStartDate, isAllDayDueDate;
@ -305,19 +319,21 @@
if (completed || [status isNotNull])
{
code = 0; /* NEEDS-ACTION */
code = 0;
if (completed || [status isEqualToString: @"COMPLETED"])
code = 1;
code = taskStatusCompleted;
else if ([status isEqualToString: @"IN-PROCESS"])
code = 2;
code = taskStatusInProcess;
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"];
}
else
{
/* confirmed by default */
[row setObject:[NSNumber numberWithInt:1] forKey: @"c_status"];
[row setObject: [NSNumber numberWithInt: 0] forKey: @"c_status"];
}
[row setObject: [NSNumber numberWithUnsignedInt: accessClass]

View File

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

View File

@ -634,6 +634,7 @@
ng-class="{ 'sg-list-selectable': list.mode.multiple }">
<md-list-item ng-repeat="task in list.component.$tasks"
aria-label="{{::task.c_title}}"
ng-class="::task.c_status"
ng-click="list.openTask($event, task)">
<div class="md-secondary sg-avatar-selectable"
label:aria-label="Toggle item"
@ -654,11 +655,14 @@
</div>
</div>
<div class="sg-md-body">
<div><!-- spacer --></div>
<div>{{::task.formatted_enddate}}</div>
<div ng-bind="::task.c_location"><!-- location --></div>
<div ng-bind="::task.formatted_enddate"><!-- enddate --></div>
</div>
</div>
<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_nextalarm">alarm</md-icon>
</div>

View File

@ -79,9 +79,17 @@
<p>{{editor.component.localizedCompletedDate}} {{editor.component.localizedCompletedTime}}</p>
</md-list-item>
<md-list-item ng-show="editor.component.enablePercentComplete()">
<md-icon>call_made</md-icon>
<md-icon>timelapse</md-icon>
<p>{{editor.component.percentComplete}} %</p>
</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 -->
<md-list-item ng-repeat="url in ::editor.component.attachUrls">
<md-icon>link</md-icon>

View File

@ -698,7 +698,7 @@
*/
Component.prototype.enablePercentComplete = function() {
return (this.type == 'task' &&
this.status != 'not-specified' &&
this.percentComplete > 0 &&
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 {
max-height: ($list-item-height * 20); // show a maximum of 20 attendees