Browse Source

MSPB-62: Expose ring groups as next action for groups (#196)

* Fix group sorting by name

* Pass down ring groups to be selected in next action feature

* Expose ring group selection in template

* Set selected entity with helper rather than manually

* Extract template data formatting into own function

* Clean up next action feature data formatter

- generate categories in logic rather than template
- sort categories/entities alphabetically
- don't render empty categories
4.3
Joris Tirado 6 years ago
committed by GitHub
parent
commit
25336951b2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 61 deletions
  1. +1
    -0
      i18n/en-US.json
  2. +114
    -39
      submodules/groups/groups.js
  3. +20
    -22
      submodules/groups/views/feature-next_action.html

+ 1
- 0
i18n/en-US.json View File

@ -112,6 +112,7 @@
"mainMenu": "Main Menu (Open hours)",
"voicemails": "Voicemail Boxes",
"users": "Users",
"groups": "Groups",
"__comment": "UI-2664: Adding devices as next action",
"__version": "4.1",
"devices": "Devices"


+ 114
- 39
submodules/groups/groups.js View File

@ -52,7 +52,7 @@ define(function(require) {
template.find('.groups-rows').append(templateGroup);
});
self.groupsBindEvents(template, parent);
self.groupsBindEvents(template, parent, dataTemplate.groups);
parent
.empty()
@ -81,14 +81,11 @@ define(function(require) {
groupsFormatListData: function(data) {
var self = this,
mapGroups = {},
arrayGroups = [];
_.each(data.groups, function(group) {
mapGroups[group.id] = group;
mapGroups[group.id].extra = self.groupsGetGroupFeatures(group);
});
mapGroups = _.transform(data.groups, function(object, group) {
_.set(object, group.id, _.merge({
extra: self.groupsGetGroupFeatures(group)
}, group));
}, {});
_.each(data.callflows, function(callflow) {
if (callflow.group_id in mapGroups) {
@ -126,18 +123,18 @@ define(function(require) {
}
});
_.each(mapGroups, function(group) {
// Only list groups created with SmartPBX (e.g. with an associated baseGroup callflow)
group.extra.hasOwnProperty('baseCallflowId') && arrayGroups.push(group);
});
arrayGroups.sort(function(a, b) {
return a.name > b.name ? 1 : -1;
});
data.groups = arrayGroups;
return data;
return {
groups: _
.chain(mapGroups)
// Only list groups created with SmartPBX (e.g. with an associated baseGroup callflow)
.reject(function(group) {
return !_.has(group, 'extra.baseCallflowId');
})
.sortBy(function(group) {
return _.toLower(group.name);
})
.value()
};
},
groupsGetGroupFeatures: function(group) {
@ -184,7 +181,7 @@ define(function(require) {
return result;
},
groupsBindEvents: function(template, parent) {
groupsBindEvents: function(template, parent, groups) {
var self = this;
setTimeout(function() { template.find('.search-query').focus(); });
@ -237,7 +234,7 @@ define(function(require) {
'border-top-color': 'transparent'
});
self.groupsGetTemplate(type, groupId, function(template, data) {
self.groupsGetTemplate(type, groupId, groups, function(template, data) {
monster.ui.tooltips(template);
row.find('.edit-groups').append(template).slideDown();
@ -424,7 +421,7 @@ define(function(require) {
return formattedData;
},
groupsGetTemplate: function(type, groupId, callbackAfterData) {
groupsGetTemplate: function(type, groupId, groups, callbackAfterData) {
var self = this;
if (type === 'name') {
@ -434,13 +431,13 @@ define(function(require) {
} else if (type === 'extensions') {
self.groupsGetExtensionsTemplate(groupId, callbackAfterData);
} else if (type === 'features') {
self.groupsGetFeaturesTemplate(groupId, callbackAfterData);
self.groupsGetFeaturesTemplate(groupId, groups, callbackAfterData);
} else if (type === 'members') {
self.groupsGetMembersTemplate(groupId, callbackAfterData);
}
},
groupsGetFeaturesTemplate: function(groupId, callback) {
groupsGetFeaturesTemplate: function(groupId, groups, callback) {
var self = this;
self.groupsGetFeaturesData(groupId, function(data) {
@ -450,7 +447,9 @@ define(function(require) {
submodule: 'groups'
}));
self.groupsBindFeatures(template, data);
self.groupsBindFeatures(template, _.merge({
groups: groups
}, data));
callback && callback(template, data);
});
@ -828,20 +827,9 @@ define(function(require) {
groupsRenderNextAction: function(data) {
var self = this,
flow = data.callflow.flow,
selectedEntity = null;
while (flow.module !== 'callflow') {
flow = flow.children._;
} //Go to the first callflow (i.e. base ring group)
if ('_' in flow.children) {
selectedEntity = flow.children._.data.id;
} //Find the existing Next Action if there is one
var templateData = $.extend(true, {selectedEntity: selectedEntity}, data),
featureTemplate = $(self.getTemplate({
name: 'feature-next_action',
data: templateData,
data: self.groupsFormatNextActionData(data),
submodule: 'groups'
})),
switchFeature = featureTemplate.find('.switch-state'),
@ -912,6 +900,93 @@ define(function(require) {
});
},
groupsFormatNextActionData: function(data) {
var self = this,
featureData = data.group.extra.mapFeatures.next_action,
//Get the first callflow (i.e. base ring group)
flow = (function huntDownFirstCallflow(flow) {
return flow.module === 'callflow'
? flow
: huntDownFirstCallflow(flow.children._);
}(data.callflow.flow));
return _.merge({
//Find the existing Next Action if there is one
selectedEntity: _.get(flow.children, '_.data.id', null),
iconClass: featureData.icon,
isEnabled: featureData.active,
categories: _
.chain([{
dataPath: 'devices',
label: self.i18n.active().groups.nextAction.devices,
module: 'device',
entityValuePath: 'id',
entityLabelPath: 'userName'
}, {
dataPath: 'groups',
label: self.i18n.active().groups.nextAction.groups,
module: 'callflow',
entityValuePath: 'extra.callflowId',
entityLabelPath: 'name',
reject: {
by: 'id',
values: [data.group.id]
}
}, {
dataPath: 'voicemails',
label: self.i18n.active().groups.nextAction.voicemails,
module: 'voicemails',
entityValuePath: 'id',
entityLabelPath: 'name'
}, {
dataPath: 'userCallflows',
label: self.i18n.active().groups.nextAction.users,
module: 'callflow',
entityValuePath: 'id',
entityLabelPath: 'userName'
}])
.reject(function(category) {
return _
.chain(data)
.get(category.dataPath, [])
.isEmpty()
.value();
})
.map(function(category) {
return _.merge({
entities: _
.chain(data)
.get(category.dataPath, [])
.reject(function(entity) {
return _.has(category, 'reject') && _.includes(
category.reject.values,
_.get(entity, category.reject.by)
);
})
.map(function(entity) {
return {
value: _.get(entity, category.entityValuePath),
label: _.get(entity, category.entityLabelPath)
};
})
.sortBy(function(entity) {
return _.toLower(entity.label);
})
.value()
}, _.pick(category, [
'label',
'module'
]));
})
.sortBy(function(category) {
return _.toLower(category.label);
})
.value()
}, _.pick(data, [
'mainMenu'
]));
},
groupsRenderForward: function(data) {
var self = this,
featureTemplate = $(self.getTemplate({


+ 20
- 22
submodules/groups/views/feature-next_action.html View File

@ -2,7 +2,7 @@
<div class="feature-popup-title">
<div class="popup-title">
<div class="feature-fa-wrapper">
<i class="{{group.extra.mapFeatures.next_action.icon}}"></i>
<i class="{{iconClass}}"></i>
</div>
<div class="feature-title">
{{ i18n.groups.nextAction.headline }}
@ -10,36 +10,34 @@
</div>
<div class="switch popup-action">
{{#monsterSwitch}}
<input class="switch-state" type="checkbox" data-on="{{i18n.enabled}}" data-off="{{i18n.disabled}}"{{#if group.extra.mapFeatures.next_action.active}} checked="checked"{{/if}}></input>
<input class="switch-state" type="checkbox" data-on="{{i18n.enabled}}" data-off="{{i18n.disabled}}"{{#if isEnabled}} checked="checked"{{/if}}></input>
{{/monsterSwitch}}
</div>
</div>
<div class="content{{#unless group.extra.mapFeatures.next_action.active}} disabled{{/unless}}">
<div class="content{{#unless isEnabled}} disabled{{/unless}}">
<div class="next-action">
<span>{{ i18n.groups.nextAction.label }}</span>
<select class="next-action-select">
<optgroup label="{{ i18n.groups.nextAction.menu }}">
{{#if mainMenu}}
<option value="{{mainMenu.id}}" data-module="callflow" {{#compare selectedEntity '===' mainMenu.id}}selected{{/compare}}>{{ i18n.groups.nextAction.mainMenu }}</option>
{{/if}}
</optgroup>
<optgroup label="{{ i18n.groups.nextAction.voicemails }}">
{{#each voicemails}}
<option value="{{id}}" data-module="voicemail" {{#compare ../selectedEntity '===' id}}selected{{/compare}}>{{name}}</option>
{{#select selectedEntity}}
{{#if mainMenu}}
<optgroup label="{{ i18n.groups.nextAction.menu }}">
<option value="{{mainMenu.id}}" data-module="callflow">
{{ i18n.groups.nextAction.mainMenu }}
</option>
</optgroup>
{{/if}}
{{#each categories}}
<optgroup label="{{label}}">
{{#each entities}}
<option value="{{value}}" data-module="{{../module}}">
{{label}}
</option>
{{/each}}
</optgroup>
<optgroup label="{{ i18n.groups.nextAction.users }}">
{{#each userCallflows}}
<option value="{{id}}" data-module="callflow" {{#compare ../selectedEntity '===' id}}selected{{/compare}}>{{userName}}</option>
{{/each}}
</optgroup>
<optgroup label="{{ i18n.groups.nextAction.devices }}">
{{#each devices}}
<option value="{{id}}" data-module="device" {{#compare ../selectedEntity '===' id}}selected{{/compare}}>{{name}}</option>
{{/each}}
</optgroup>
</optgroup>
{{/each}}
{{/select}}
</select>
</div>
</div>


Loading…
Cancel
Save