feat(mail(js)): new button to expand recipients that are LDAP groups

pull/281/head
Francis Lachapelle 2019-11-21 21:51:27 -05:00
parent f140bba03a
commit 456a66b66b
8 changed files with 81 additions and 22 deletions

View File

@ -82,15 +82,23 @@
label:placeholder="Add a recipient"> label:placeholder="Add a recipient">
<md-item-template> <md-item-template>
<div class="sg-tile-content"> <div class="sg-tile-content">
<div class="sg-md-subhead" <div class="sg-md-subhead">
md-highlight-text="editor.autocomplete.to.searchText" <div md-highlight-text="editor.autocomplete.to.searchText"
md-highlight-flags="gi">{{ user.$shortFormat(editor.autocomplete.to.searchText) }}</div> md-highlight-flags="gi">{{ user.$shortFormat(editor.autocomplete.to.searchText) }}</div>
</div>
<div class="sg-md-body" <div class="sg-md-body"
md-colors="::{color: 'default-background-500'}">{{ user.containername }}</div> md-colors="::{color: 'default-background-500'}">{{ user.containername }}</div>
</div> </div>
</md-item-template> </md-item-template>
</md-autocomplete> </md-autocomplete>
<md-chip-template>{{$chip}}</md-chip-template> <md-chip-template>
<div class="sg-tile-content">
{{$chip}}
<md-button class="sg-tile-btn" md-colors="::{ color: 'accent-600'}" ng-if="$chip.isExpandable" ng-click="editor.expandGroup($chip, 'to')">
<md-icon md-colors="::{ color: 'accent-600'}">add_box</md-icon><span ng-bind="$chip.members.length"></span>
</md-button>
</div>
</md-chip-template>
</md-chips> </md-chips>
</div> </div>
@ -115,15 +123,23 @@
label:placeholder="Add a recipient"> label:placeholder="Add a recipient">
<md-item-template> <md-item-template>
<div class="sg-tile-content"> <div class="sg-tile-content">
<div class="sg-md-subhead" <div class="sg-md-subhead">
md-highlight-text="editor.autocomplete.cc.searchText" <div md-highlight-text="editor.autocomplete.cc.searchText"
md-highlight-flags="gi">{{ user.$shortFormat(editor.autocomplete.cc.searchText) }}</div> md-highlight-flags="gi">{{ user.$shortFormat(editor.autocomplete.cc.searchText) }}</div>
</div>
<div class="sg-md-body" <div class="sg-md-body"
md-colors="::{color: 'default-background-500'}">{{ user.containername }}</div> md-colors="::{color: 'default-background-500'}">{{ user.containername }}</div>
</div> </div>
</md-item-template> </md-item-template>
</md-autocomplete> </md-autocomplete>
<md-chip-template>{{$chip}}</md-chip-template> <md-chip-template>
<div class="sg-tile-content">
{{$chip}}
<md-button class="sg-tile-btn" md-colors="::{ color: 'accent-600'}" ng-if="$chip.isExpandable" ng-click="editor.expandGroup($chip, 'cc')">
<md-icon md-colors="::{ color: 'accent-600'}">add_box</md-icon><span ng-bind="$chip.members.length"></span>
</md-button>
</div>
</md-chip-template>
</md-chips> </md-chips>
</div> </div>
@ -148,15 +164,23 @@
label:placeholder="Add a recipient"> label:placeholder="Add a recipient">
<md-item-template> <md-item-template>
<div class="sg-tile-content"> <div class="sg-tile-content">
<div class="sg-md-subhead" <div class="sg-md-subhead">
md-highlight-text="editor.autocomplete.bcc.searchText" <div md-highlight-text="editor.autocomplete.bcc.searchText"
md-highlight-flags="gi">{{ user.$shortFormat(editor.autocomplete.bcc.searchText) }}</div> md-highlight-flags="gi">{{ user.$shortFormat(editor.autocomplete.bcc.searchText) }}</div>
</div>
<div class="sg-md-body" <div class="sg-md-body"
md-colors="::{color: 'default-background-500'}">{{ user.containername }}</div> md-colors="::{color: 'default-background-500'}">{{ user.containername }}</div>
</div> </div>
</md-item-template> </md-item-template>
</md-autocomplete> </md-autocomplete>
<md-chip-template>{{$chip}}</md-chip-template> <md-chip-template>
<div class="sg-tile-content">
{{$chip}}
<md-button class="sg-tile-btn" md-colors="::{ color: 'accent-600'}" ng-if="$chip.isExpandable" ng-click="editor.expandGroup($chip, 'bcc')">
<md-icon md-colors="::{ color: 'accent-600'}">add_box</md-icon><span ng-bind="$chip.members.length"></span>
</md-button>
</div>
</md-chip-template>
</md-chips> </md-chips>
</div> </div>

View File

@ -70,8 +70,8 @@
<div class="sg-md-subhead"><div>{{currentAttendee.name}}</div></div> <div class="sg-md-subhead"><div>{{currentAttendee.name}}</div></div>
<div class="sg-md-body"> <div class="sg-md-body">
<div>{{currentAttendee.email}}</div> <div>{{currentAttendee.email}}</div>
<md-button class="sg-tile-thread" md-colors="::{ color: 'accent-600'}" ng-if="currentAttendee.isExpandableGroup" ng-click="editor.expandAttendee(currentAttendee)"> <md-button class="sg-tile-btn" md-colors="::{ color: 'accent-600'}" ng-if="currentAttendee.isExpandableGroup" ng-click="editor.expandAttendee(currentAttendee)">
<md-icon class="md-rotate-180-ccw" md-colors="::{ color: 'accent-600'}">add_box</md-icon><span ng-bind="currentAttendee.members.length"></span> <md-icon md-colors="::{ color: 'accent-600'}">add_box</md-icon><span ng-bind="currentAttendee.members.length"></span>
</md-button> </md-button>
</div> </div>
</div> </div>

View File

@ -254,7 +254,7 @@
if (this.members) if (this.members)
return Card.$q.when(this.members); return Card.$q.when(this.members);
if (this.isgroup) { if (this.$isGroup({expandable: true})) {
return Card.$$resource.fetch(this.$path(), 'members').then(function(data) { return Card.$$resource.fetch(this.$path(), 'members').then(function(data) {
_this.members = _.map(data.members, function(member) { _this.members = _.map(data.members, function(member) {
return new Card(member); return new Card(member);
@ -262,6 +262,8 @@
return _this.members; return _this.members;
}); });
} }
return Card.$q.reject("Card " + this.id + " is not an LDAP group");
}; };
/** /**
@ -429,6 +431,11 @@
return this.c_component == 'vlist' && condition; return this.c_component == 'vlist' && condition;
}; };
Card.prototype.$isGroup = function(options) {
var condition = (!options || !options.expandable || options.expandable && Card.$Preferences.defaults.SOGoLDAPGroupExpansionEnabled);
return this.isgroup && condition;
};
Card.prototype.$addOrg = function(org) { Card.prototype.$addOrg = function(org) {
if (angular.isUndefined(this.orgs)) { if (angular.isUndefined(this.orgs)) {
this.orgs = [org]; this.orgs = [org];

View File

@ -745,7 +745,7 @@
*/ */
Message.prototype.$save = function() { Message.prototype.$save = function() {
var _this = this, var _this = this,
data = this.editable; data = this.$omit();
Message.$log.debug('save = ' + JSON.stringify(data, undefined, 2)); Message.$log.debug('save = ' + JSON.stringify(data, undefined, 2));
@ -765,7 +765,7 @@
*/ */
Message.prototype.$send = function() { Message.prototype.$send = function() {
var _this = this, var _this = this,
data = angular.copy(this.editable); data = this.$omit();
Message.$log.debug('send = ' + JSON.stringify(data, undefined, 2)); Message.$log.debug('send = ' + JSON.stringify(data, undefined, 2));
@ -828,8 +828,13 @@
Message.prototype.$omit = function(options) { Message.prototype.$omit = function(options) {
var message = {}, var message = {},
privateAttributes = options && options.privateAttributes; privateAttributes = options && options.privateAttributes;
angular.forEach(this, function(value, key) { angular.forEach(this.editable, function(value, key) {
if (key != 'constructor' && key[0] != '$' || privateAttributes) { if (_.includes(['to', 'cc', 'bcc'], key)) {
message[key] = _.map(value, function (addr) {
return addr.toString();
});
}
else if (key != 'constructor' && key[0] != '$' || privateAttributes) {
message[key] = value; message[key] = value;
} }
}); });

View File

@ -329,6 +329,16 @@
}); });
} }
} }
else if (contact.$isGroup({expandable: true})) {
recipient = {
toString: function () { return contact.$shortFormat(); },
isExpandable: true,
members: []
};
contact.$members().then(function (members) {
recipient.members = members;
});
}
else { else {
recipient = contact.$shortFormat(); recipient = contact.$shortFormat();
} }
@ -339,6 +349,16 @@
return null; return null;
} }
this.expandGroup = function(contact, field) {
var recipients, i, j;
recipients = vm.message.editable[field];
i = recipients.indexOf(contact);
recipients.splice(i, 1);
for (j = 0; j < contact.members.length; j++) {
recipients.splice(i + j, 0, contact.members[j].$shortFormat());
}
};
// Drafts autosaving // Drafts autosaving
function autosaveDrafts() { function autosaveDrafts() {
vm.message.$save(); vm.message.$save();

View File

@ -26,7 +26,7 @@
' <div class="sg-md-body">', ' <div class="sg-md-body">',
' <div class="sg-tile-subject"><!-- subject --></div>', ' <div class="sg-tile-subject"><!-- subject --></div>',
' <div class="sg-tile-size"><!-- size --></div>', ' <div class="sg-tile-size"><!-- size --></div>',
' <md-button class="sg-tile-thread md-secondary ng-hide" md-colors="::{ color: \'accent-600\'}" ng-click="$ctrl.toggleThread()">', ' <md-button class="sg-tile-btn md-secondary ng-hide" md-colors="::{ color: \'accent-600\'}" ng-click="$ctrl.toggleThread()">',
' <md-icon class="md-rotate-180-ccw" md-colors="::{ color: \'accent-600\'}">expand_more</md-icon><span></span>', // expanded by default (icon is rotated) ' <md-icon class="md-rotate-180-ccw" md-colors="::{ color: \'accent-600\'}">expand_more</md-icon><span></span>', // expanded by default (icon is rotated)
' </md-button>', ' </md-button>',
' </div>', ' </div>',

View File

@ -72,6 +72,9 @@ md-chips {
width: 100%; width: 100%;
} }
} }
.sg-tile-btn {
margin-right: 3px !important; // assume the button is right before the close button
}
} }
// Adapting avatars in contact chips to the new material guidelines // Adapting avatars in contact chips to the new material guidelines

View File

@ -176,7 +176,7 @@ div.md-tile-left {
&-tile-content { &-tile-content {
flex: 1; flex: 1;
overflow: hidden; // required in Firefox overflow: hidden; // required in Firefox
.sg-tile-date, .sg-tile-size, .sg-tile-thread { .sg-tile-date, .sg-tile-size, .sg-tile-btn {
flex-shrink: 0; flex-shrink: 0;
font-size: sg-size(body); font-size: sg-size(body);
font-weight: $sg-font-light; font-weight: $sg-font-light;
@ -186,7 +186,7 @@ div.md-tile-left {
.sg-tile-size { .sg-tile-size {
font-size: sg-size(caption); font-size: sg-size(caption);
} }
.sg-tile-thread { .sg-tile-btn {
min-height: auto; min-height: auto;
min-width: auto; min-width: auto;
padding: 0 3px !important; padding: 0 3px !important;