Signal notification fixes and UI updates
This commit is contained in:
parent
d93797172a
commit
59872f579a
11 changed files with 440 additions and 201 deletions
|
|
@ -0,0 +1,220 @@
|
||||||
|
class ProfileNotification extends App.ControllerSubContent
|
||||||
|
@include App.TicketNotificationMatrix
|
||||||
|
|
||||||
|
@requiredPermission: 'user_preferences.notifications+ticket.agent'
|
||||||
|
header: __('Notifications')
|
||||||
|
events:
|
||||||
|
'submit form': 'update'
|
||||||
|
'click .js-reset' : 'reset'
|
||||||
|
'change .js-notificationSound': 'previewSound'
|
||||||
|
'change #profile-groups-limit': 'didSwitchGroupsLimit'
|
||||||
|
'change input[name=group_ids]': 'didChangeGroupIds'
|
||||||
|
'change input[name$=".channel.signal"]': 'didChangeSignalCheckbox'
|
||||||
|
|
||||||
|
elements:
|
||||||
|
'#profile-groups-limit': 'profileGroupsLimitInput'
|
||||||
|
'.profile-groups-limit-settings-inner': 'groupsLimitSettings'
|
||||||
|
'.profile-groups-all-unchecked': 'groupsAllUncheckedWarning'
|
||||||
|
|
||||||
|
sounds: [
|
||||||
|
{
|
||||||
|
name: 'Bell'
|
||||||
|
file: 'Bell.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Kalimba'
|
||||||
|
file: 'Kalimba.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Marimba'
|
||||||
|
file: 'Marimba.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Peep'
|
||||||
|
file: 'Peep.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Plop'
|
||||||
|
file: 'Plop.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ring'
|
||||||
|
file: 'Ring.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Space'
|
||||||
|
file: 'Space.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Wood'
|
||||||
|
file: 'Wood.mp3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Xylo'
|
||||||
|
file: 'Xylo.mp3'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
App.User.full(App.Session.get().id, @render, true, true)
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
|
||||||
|
matrix =
|
||||||
|
create:
|
||||||
|
name: __('New Ticket')
|
||||||
|
update:
|
||||||
|
name: __('Ticket update')
|
||||||
|
reminder_reached:
|
||||||
|
name: __('Ticket reminder reached')
|
||||||
|
escalation:
|
||||||
|
name: __('Ticket escalation')
|
||||||
|
|
||||||
|
config =
|
||||||
|
group_ids: []
|
||||||
|
matrix: {}
|
||||||
|
|
||||||
|
user_config = @Session.get('preferences').notification_config
|
||||||
|
if user_config
|
||||||
|
config = $.extend(true, {}, config, user_config)
|
||||||
|
|
||||||
|
# groups
|
||||||
|
user_group_config = true
|
||||||
|
if !user_config || !user_config['group_ids'] || _.isEmpty(user_config['group_ids']) || user_config['group_ids'][0] is '-'
|
||||||
|
user_group_config = false
|
||||||
|
|
||||||
|
groups = []
|
||||||
|
group_ids = App.User.find(@Session.get('id')).allGroupIds()
|
||||||
|
if group_ids
|
||||||
|
for group_id in group_ids
|
||||||
|
group = App.Group.find(group_id)
|
||||||
|
groups.push group
|
||||||
|
if !user_group_config
|
||||||
|
if !config['group_ids']
|
||||||
|
config['group_ids'] = []
|
||||||
|
config['group_ids'].push group_id.toString()
|
||||||
|
|
||||||
|
groups = _.sortBy(groups, (item) -> return item.name)
|
||||||
|
|
||||||
|
for sound in @sounds
|
||||||
|
sound.selected = sound.file is App.OnlineNotification.soundFile() ? true : false
|
||||||
|
|
||||||
|
signal_notification_enabled = App.Config.get('signal_notification_enabled')
|
||||||
|
|
||||||
|
signal_uid = config.signal_uid || ''
|
||||||
|
|
||||||
|
# Check if any signal checkbox is currently checked in the matrix
|
||||||
|
signal_has_checked = false
|
||||||
|
if signal_notification_enabled
|
||||||
|
for key, val of config.matrix
|
||||||
|
if val?.channel?.signal
|
||||||
|
signal_has_checked = true
|
||||||
|
break
|
||||||
|
|
||||||
|
@html App.view('profile/notification')
|
||||||
|
matrixTableHTML: @renderNotificationMatrix(config.matrix)
|
||||||
|
groups: groups
|
||||||
|
config: config
|
||||||
|
sounds: @sounds
|
||||||
|
notificationSoundEnabled: App.OnlineNotification.soundEnabled()
|
||||||
|
user_group_config: user_group_config
|
||||||
|
signal_notification_enabled: signal_notification_enabled
|
||||||
|
signal_uid: signal_uid
|
||||||
|
signal_has_checked: signal_has_checked
|
||||||
|
|
||||||
|
update: (e) =>
|
||||||
|
|
||||||
|
#notification_config
|
||||||
|
e.preventDefault()
|
||||||
|
params = {}
|
||||||
|
params.notification_config = {}
|
||||||
|
|
||||||
|
formParams = @formParam(e.target)
|
||||||
|
|
||||||
|
params.notification_config.matrix = @updatedNotificationMatrixValues(formParams)
|
||||||
|
|
||||||
|
if formParams.signal_uid?
|
||||||
|
params.notification_config.signal_uid = formParams.signal_uid
|
||||||
|
|
||||||
|
if @profileGroupsLimitInput.is(':checked')
|
||||||
|
params.notification_config.group_ids = formParams['group_ids']
|
||||||
|
if typeof params.notification_config.group_ids isnt 'object'
|
||||||
|
params.notification_config.group_ids = [params.notification_config.group_ids]
|
||||||
|
|
||||||
|
if _.isEmpty(params.notification_config.group_ids)
|
||||||
|
delete params.notification_config.group_ids
|
||||||
|
|
||||||
|
@formDisable(e)
|
||||||
|
|
||||||
|
params.notification_sound = formParams.notification_sound
|
||||||
|
if !params.notification_sound.enabled
|
||||||
|
params.notification_sound.enabled = false
|
||||||
|
else
|
||||||
|
params.notification_sound.enabled = true
|
||||||
|
|
||||||
|
# get data
|
||||||
|
@ajax(
|
||||||
|
id: 'preferences'
|
||||||
|
type: 'PUT'
|
||||||
|
url: @apiPath + '/users/preferences'
|
||||||
|
data: JSON.stringify(params)
|
||||||
|
processData: true
|
||||||
|
success: @success
|
||||||
|
error: @error
|
||||||
|
)
|
||||||
|
|
||||||
|
reset: (e) =>
|
||||||
|
new App.ControllerConfirm(
|
||||||
|
message: __('Are you sure? Your notifications settings will be reset to default.')
|
||||||
|
buttonClass: 'btn--danger'
|
||||||
|
callback: =>
|
||||||
|
@ajax(
|
||||||
|
id: 'preferences_notifications_reset'
|
||||||
|
type: 'POST'
|
||||||
|
url: "#{@apiPath}/users/preferences_notifications_reset"
|
||||||
|
processData: true
|
||||||
|
success: @success
|
||||||
|
)
|
||||||
|
container: @el.closest('.content')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
App.User.full(
|
||||||
|
App.Session.get('id'),
|
||||||
|
=>
|
||||||
|
App.Event.trigger('ui:rerender')
|
||||||
|
@notify(
|
||||||
|
type: 'success'
|
||||||
|
msg: __('Update successful.')
|
||||||
|
)
|
||||||
|
,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
error: (xhr, status, error) =>
|
||||||
|
@render()
|
||||||
|
data = JSON.parse(xhr.responseText)
|
||||||
|
@notify(
|
||||||
|
type: 'error'
|
||||||
|
msg: data.message
|
||||||
|
)
|
||||||
|
|
||||||
|
previewSound: (e) =>
|
||||||
|
params = @formParam(e.target)
|
||||||
|
return if !params.notification_sound
|
||||||
|
return if !params.notification_sound.file
|
||||||
|
App.OnlineNotification.play(params.notification_sound.file)
|
||||||
|
|
||||||
|
didSwitchGroupsLimit: (e) =>
|
||||||
|
@groupsLimitSettings.collapse('toggle')
|
||||||
|
|
||||||
|
didChangeGroupIds: (e) =>
|
||||||
|
@groupsAllUncheckedWarning.toggleClass 'hide', @el.find('input[name=group_ids]:checked').length != 0
|
||||||
|
|
||||||
|
didChangeSignalCheckbox: (e) =>
|
||||||
|
hasChecked = @el.find('input[name$=".channel.signal"]:checked').length > 0
|
||||||
|
@el.find('.js-signal-phone-container').toggle(hasChecked)
|
||||||
|
|
||||||
|
App.Config.set('Notifications', { prio: 2600, name: __('Notifications'), parent: '#profile', target: '#profile/notifications', permission: ['user_preferences.notifications+ticket.agent'], controller: ProfileNotification }, 'NavBarProfile')
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
class ProfileSignalNotifications extends App.ControllerSubContent
|
|
||||||
@requiredPermission: 'user_preferences.signal_notifications+ticket.agent'
|
|
||||||
header: __('Signal Notifications')
|
|
||||||
events:
|
|
||||||
'submit form': 'update'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
App.User.full(App.Session.get().id, @render, true, true)
|
|
||||||
|
|
||||||
render: =>
|
|
||||||
config =
|
|
||||||
enabled: false
|
|
||||||
events:
|
|
||||||
create: true
|
|
||||||
update: true
|
|
||||||
escalation: true
|
|
||||||
reminder_reached: true
|
|
||||||
|
|
||||||
user = App.User.find(App.Session.get().id)
|
|
||||||
user_config = user.preferences?.signal_notifications
|
|
||||||
if user_config
|
|
||||||
config = $.extend(true, {}, config, user_config)
|
|
||||||
|
|
||||||
@html App.view('profile/signal_notifications')
|
|
||||||
config: config
|
|
||||||
signal_uid: user.signal_uid || ''
|
|
||||||
signal_notification_enabled: App.Config.get('signal_notification_enabled')
|
|
||||||
|
|
||||||
update: (e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
params = @formParam(e.target)
|
|
||||||
|
|
||||||
preferences = {}
|
|
||||||
preferences.signal_notifications =
|
|
||||||
enabled: params.enabled == 'true'
|
|
||||||
events:
|
|
||||||
create: params.event_create == 'true'
|
|
||||||
update: params.event_update == 'true'
|
|
||||||
escalation: params.event_escalation == 'true'
|
|
||||||
reminder_reached: params.event_reminder_reached == 'true'
|
|
||||||
|
|
||||||
@formDisable(e)
|
|
||||||
|
|
||||||
@ajax(
|
|
||||||
id: 'preferences_signal_notifications'
|
|
||||||
type: 'PUT'
|
|
||||||
url: @apiPath + '/users/preferences'
|
|
||||||
data: JSON.stringify(preferences)
|
|
||||||
processData: true
|
|
||||||
success: @successPreferences
|
|
||||||
error: @error
|
|
||||||
)
|
|
||||||
|
|
||||||
if params.signal_uid?
|
|
||||||
user = App.User.find(App.Session.get().id)
|
|
||||||
user.signal_uid = params.signal_uid
|
|
||||||
user.save(
|
|
||||||
done: =>
|
|
||||||
# User saved successfully
|
|
||||||
fail: (settings, details) =>
|
|
||||||
@notify(
|
|
||||||
type: 'error'
|
|
||||||
msg: details.error || __('Failed to save Signal phone number')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
successPreferences: (data, status, xhr) =>
|
|
||||||
App.User.full(
|
|
||||||
App.Session.get('id'),
|
|
||||||
=>
|
|
||||||
App.Event.trigger('ui:rerender')
|
|
||||||
@notify(
|
|
||||||
type: 'success'
|
|
||||||
msg: __('Update successful.')
|
|
||||||
)
|
|
||||||
,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
error: (xhr, status, error) =>
|
|
||||||
@render()
|
|
||||||
data = JSON.parse(xhr.responseText)
|
|
||||||
@notify(
|
|
||||||
type: 'error'
|
|
||||||
msg: data.message
|
|
||||||
)
|
|
||||||
|
|
||||||
App.Config.set('SignalNotifications', { prio: 2650, name: __('Signal Notifications'), parent: '#profile', target: '#profile/signal_notifications', permission: ['user_preferences.signal_notifications+ticket.agent'], controller: ProfileSignalNotifications }, 'NavBarProfile')
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# coffeelint: disable=camel_case_classes
|
||||||
|
class App.UiElement.notification_matrix
|
||||||
|
@render: (values, options = {}) ->
|
||||||
|
|
||||||
|
matrixYAxe =
|
||||||
|
create:
|
||||||
|
name: __('New Ticket')
|
||||||
|
update:
|
||||||
|
name: __('Ticket update')
|
||||||
|
reminder_reached:
|
||||||
|
name: __('Ticket reminder reached')
|
||||||
|
escalation:
|
||||||
|
name: __('Ticket escalation')
|
||||||
|
|
||||||
|
$( App.view('generic/notification_matrix')( matrixYAxe: matrixYAxe, values: values, signal_notification_enabled: options.signal_notification_enabled ) )
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Common handling for the notification matrix
|
||||||
|
App.TicketNotificationMatrix =
|
||||||
|
renderNotificationMatrix: (values) ->
|
||||||
|
App.UiElement.notification_matrix.render(values, signal_notification_enabled: App.Config.get('signal_notification_enabled'))[0].outerHTML
|
||||||
|
|
||||||
|
updatedNotificationMatrixValues: (formParams) ->
|
||||||
|
matrix = {}
|
||||||
|
|
||||||
|
for key, value of formParams
|
||||||
|
area = key.split('.')
|
||||||
|
|
||||||
|
continue if area[0] isnt 'matrix'
|
||||||
|
|
||||||
|
if !matrix[area[1]]
|
||||||
|
matrix[area[1]] = {}
|
||||||
|
|
||||||
|
switch area[2]
|
||||||
|
when 'criteria'
|
||||||
|
if !matrix[area[1]][area[2]]
|
||||||
|
matrix[area[1]][area[2]] = {}
|
||||||
|
|
||||||
|
matrix[area[1]][area[2]][area[3]] = value is 'true'
|
||||||
|
when 'channel'
|
||||||
|
if !matrix[area[1]][area[2]]
|
||||||
|
matrix[area[1]][area[2]] = { online: true }
|
||||||
|
|
||||||
|
matrix[area[1]][area[2]][area[3]] = value is 'true'
|
||||||
|
|
||||||
|
matrix
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<% if @signal_notification_enabled: %>
|
||||||
|
<% colWidth = "13%" %>
|
||||||
|
<% channelWidth = "100px" %>
|
||||||
|
<% else: %>
|
||||||
|
<% colWidth = "16%" %>
|
||||||
|
<% channelWidth = "120px" %>
|
||||||
|
<% end %>
|
||||||
|
<table class="settings-list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<th width="<%= colWidth %>" style="text-align: center;"><%- @T('My Tickets') %>
|
||||||
|
<th width="<%= colWidth %>" style="text-align: center;"><%- @T('Not Assigned') %>*
|
||||||
|
<th width="<%= colWidth %>" style="text-align: center;"><%- @T('Subscribed Tickets') %>
|
||||||
|
<th width="<%= colWidth %>" style="text-align: center;"><%- @T('All Tickets') %>*
|
||||||
|
<th width="<%= channelWidth %>" class="settings-list-separator" style="text-align: center;"><%- @T('Also notify via email') %>
|
||||||
|
<% if @signal_notification_enabled: %>
|
||||||
|
<th width="<%= channelWidth %>" class="settings-list-separator" style="text-align: center;"><%- @T('Also notify via Signal') %>
|
||||||
|
<% end %>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if @matrixYAxe: %>
|
||||||
|
<% for key, value of @matrixYAxe: %>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<%- @T(value.name) %>
|
||||||
|
<% criteria = @values[key]?.criteria %>
|
||||||
|
<% channel = @values[key]?.channel %>
|
||||||
|
<td class="u-positionOrigin">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="matrix.<%= key %>.criteria.owned_by_me" value="true"<% if criteria && criteria.owned_by_me: %> checked<% end %> />
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<td class="u-positionOrigin">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="matrix.<%= key %>.criteria.owned_by_nobody" value="true"<% if criteria && criteria.owned_by_nobody: %> checked<% end %> />
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<td class="u-positionOrigin">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="matrix.<%= key %>.criteria.subscribed" value="true"<% if criteria && criteria.subscribed: %> checked<% end %> />
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<td class="u-positionOrigin">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="matrix.<%= key %>.criteria.no" value="true"<% if criteria && criteria.no: %> checked<% end %> />
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<td class="u-positionOrigin settings-list-separator">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="matrix.<%= key %>.channel.email" value="true"<% if channel && channel.email: %> checked<% end %> />
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<% if @signal_notification_enabled: %>
|
||||||
|
<td class="u-positionOrigin settings-list-separator">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="matrix.<%= key %>.channel.signal" value="true"<% if channel && channel.signal: %> checked<% end %> />
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="page-header-title"><h1><%- @T('Notifications') %></h1></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="page-content form--flexibleWidth profile-settings-notifications-content">
|
||||||
|
|
||||||
|
<div class="settings-entry">
|
||||||
|
<%- @matrixTableHTML %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if @signal_notification_enabled: %>
|
||||||
|
<div class="js-signal-phone-container" style="<% if !@signal_has_checked: %>display: none;<% end %>">
|
||||||
|
<h2><%- @T('Signal Phone Number') %></h2>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="signal_uid" class="form-control" value="<%= @signal_uid %>" placeholder="+1234567890">
|
||||||
|
<p class="help-block"><%- @T('Use international format with country code (e.g., +1234567890)') %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if @groups: %>
|
||||||
|
<div class="zammad-switch zammad-switch--small" data-name="profile-groups-limit">
|
||||||
|
<input type="checkbox" id="profile-groups-limit" <% if @user_group_config: %> checked <% end %>>
|
||||||
|
<label for="profile-groups-limit"></label>
|
||||||
|
</div>
|
||||||
|
<h2>
|
||||||
|
<%- @T('Limit Groups') %>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="settings-entry profile-groups-limit-settings">
|
||||||
|
<div class="profile-groups-limit-settings-inner collapse <% if @user_group_config: %>in<% end %>">
|
||||||
|
<div class="alert alert--warning profile-groups-all-unchecked hide" role="alert">
|
||||||
|
<%- @T('Disabling the notifications from all groups will turn off the limit. Instead, to disable the notifications use the settings above.') %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="settings-list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><%- @T('Group') %>
|
||||||
|
<th><%- @T('Not Assigned') %> & <%- @T('All Tickets') %>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% for group in @groups: %>
|
||||||
|
<tr>
|
||||||
|
<td><%- @P(group, 'name') %>
|
||||||
|
<td class="u-positionOrigin">
|
||||||
|
<label class="checkbox-replacement checkbox-replacement--fullscreen">
|
||||||
|
<input type="checkbox" name="group_ids" value="<%= group.id %>" <% if _.include(_.map(@config.group_ids, (group_id) -> group_id.toString()), group.id.toString()): %>checked<% end %>/>
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</label>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<h2><%- @T('Sounds') %></h2>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="formGroup-label">
|
||||||
|
<label for="notification-sound"><%- @T('Notification Sound') %></label>
|
||||||
|
</div>
|
||||||
|
<div class="controls controls--select">
|
||||||
|
<select class="form-control js-notificationSound" id="notification-sound" name="notification_sound::file">
|
||||||
|
<% for sound in @sounds: %>
|
||||||
|
<option value="<%= sound.file %>"<%= ' selected' if sound.selected %>><%= sound.name %></option>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
<%- @Icon('arrow-down') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="inline-label">
|
||||||
|
<span class="checkbox-replacement checkbox-replacement--inline">
|
||||||
|
<input type="checkbox" name="notification_sound::enabled" value="true" <% if @notificationSoundEnabled: %> checked<% end %> class="js-SoundEnableDisable">
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</span>
|
||||||
|
<%- @T('Play user interface sound effects') %>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn--primary"><%- @T( 'Submit' ) %></button>
|
||||||
|
<input type="button" class="btn btn--danger js-reset" value="<%- @T( 'Reset to default settings' ) %>">
|
||||||
|
</form>
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
<div class="page-header">
|
|
||||||
<div class="page-header-title"><h1><%- @T('Signal Notifications') %></h1></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% if !@signal_notification_enabled: %>
|
|
||||||
<div class="alert alert--warning" role="alert">
|
|
||||||
<%- @T('Signal notifications are currently disabled by the administrator.') %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<form class="page-content form--flexibleWidth">
|
|
||||||
<h2><%- @T('Signal Phone Number') %></h2>
|
|
||||||
<p class="help-text">
|
|
||||||
<%- @T('Enter your Signal phone number to receive ticket notifications via Signal.') %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="signal-uid"><%- @T('Signal Phone Number') %></label>
|
|
||||||
<input type="text" id="signal-uid" name="signal_uid" class="form-control" value="<%= @signal_uid %>" placeholder="+1234567890">
|
|
||||||
<p class="help-block"><%- @T('Use international format with country code (e.g., +1234567890)') %></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2><%- @T('Notification Settings') %></h2>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="inline-label">
|
|
||||||
<span class="checkbox-replacement checkbox-replacement--inline">
|
|
||||||
<input type="checkbox" name="enabled" value="true" <% if @config.enabled: %> checked<% end %>>
|
|
||||||
<%- @Icon('checkbox', 'icon-unchecked') %>
|
|
||||||
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
|
||||||
</span>
|
|
||||||
<%- @T('Enable Signal notifications') %>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3><%- @T('Notification Events') %></h3>
|
|
||||||
<p class="help-text">
|
|
||||||
<%- @T('Select which events should trigger Signal notifications.') %>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="inline-label">
|
|
||||||
<span class="checkbox-replacement checkbox-replacement--inline">
|
|
||||||
<input type="checkbox" name="event_create" value="true" <% if @config.events?.create: %> checked<% end %>>
|
|
||||||
<%- @Icon('checkbox', 'icon-unchecked') %>
|
|
||||||
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
|
||||||
</span>
|
|
||||||
<%- @T('New Ticket') %>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="inline-label">
|
|
||||||
<span class="checkbox-replacement checkbox-replacement--inline">
|
|
||||||
<input type="checkbox" name="event_update" value="true" <% if @config.events?.update: %> checked<% end %>>
|
|
||||||
<%- @Icon('checkbox', 'icon-unchecked') %>
|
|
||||||
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
|
||||||
</span>
|
|
||||||
<%- @T('Ticket update') %>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="inline-label">
|
|
||||||
<span class="checkbox-replacement checkbox-replacement--inline">
|
|
||||||
<input type="checkbox" name="event_escalation" value="true" <% if @config.events?.escalation: %> checked<% end %>>
|
|
||||||
<%- @Icon('checkbox', 'icon-unchecked') %>
|
|
||||||
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
|
||||||
</span>
|
|
||||||
<%- @T('Ticket escalation') %>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="inline-label">
|
|
||||||
<span class="checkbox-replacement checkbox-replacement--inline">
|
|
||||||
<input type="checkbox" name="event_reminder_reached" value="true" <% if @config.events?.reminder_reached: %> checked<% end %>>
|
|
||||||
<%- @Icon('checkbox', 'icon-unchecked') %>
|
|
||||||
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
|
||||||
</span>
|
|
||||||
<%- @T('Ticket reminder reached') %>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn--primary"><%- @T('Submit') %></button>
|
|
||||||
</form>
|
|
||||||
|
|
@ -11,7 +11,9 @@ class SignalNotificationJob < ApplicationJob
|
||||||
|
|
||||||
user = User.find_by(id: user_id)
|
user = User.find_by(id: user_id)
|
||||||
return if !user
|
return if !user
|
||||||
return if user.signal_uid.blank?
|
|
||||||
|
signal_uid = user.preferences.dig('notification_config', 'signal_uid').presence
|
||||||
|
return if signal_uid.blank?
|
||||||
|
|
||||||
article = article_id ? Ticket::Article.find_by(id: article_id) : nil
|
article = article_id ? Ticket::Article.find_by(id: article_id) : nil
|
||||||
|
|
||||||
|
|
@ -30,13 +32,13 @@ class SignalNotificationJob < ApplicationJob
|
||||||
|
|
||||||
SignalNotificationSender.send_message(
|
SignalNotificationSender.send_message(
|
||||||
channel: channel,
|
channel: channel,
|
||||||
recipient: user.signal_uid,
|
recipient: signal_uid,
|
||||||
message: message
|
message: message
|
||||||
)
|
)
|
||||||
|
|
||||||
add_history(ticket, user, type)
|
add_history(ticket, user, signal_uid, type)
|
||||||
|
|
||||||
Rails.logger.info "Sent Signal notification to #{user.signal_uid} for ticket ##{ticket.number} (#{type})"
|
Rails.logger.info "Sent Signal notification to #{signal_uid} for ticket ##{ticket.number} (#{type})"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
@ -48,8 +50,8 @@ class SignalNotificationJob < ApplicationJob
|
||||||
Channel.find_by(id: channel_id, area: 'Signal::Number', active: true)
|
Channel.find_by(id: channel_id, area: 'Signal::Number', active: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_history(ticket, user, type)
|
def add_history(ticket, user, signal_uid, type)
|
||||||
identifier = user.signal_uid.presence || user.login
|
identifier = signal_uid.presence || user.login
|
||||||
recipient_list = "#{identifier}(#{type}:signal)"
|
recipient_list = "#{identifier}(#{type}:signal)"
|
||||||
|
|
||||||
History.add(
|
History.add(
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,8 @@ class Transaction::SignalNotification
|
||||||
possible_recipients_with_ooo.each do |user|
|
possible_recipients_with_ooo.each do |user|
|
||||||
next if recipient_is_current_user?(user)
|
next if recipient_is_current_user?(user)
|
||||||
next if !user.active?
|
next if !user.active?
|
||||||
next if !user_has_signal_notifications_enabled?(user)
|
next if user_signal_uid(user).blank?
|
||||||
next if user.signal_uid.blank?
|
next if !user_wants_signal_for_event?(user)
|
||||||
next if !should_notify_for_event?(user)
|
|
||||||
|
|
||||||
recipients.push(user)
|
recipients.push(user)
|
||||||
end
|
end
|
||||||
|
|
@ -123,11 +122,11 @@ class Transaction::SignalNotification
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_has_signal_notifications_enabled?(user)
|
def user_signal_uid(user)
|
||||||
user.preferences.dig('signal_notifications', 'enabled') == true
|
user.preferences.dig('notification_config', 'signal_uid').presence
|
||||||
end
|
end
|
||||||
|
|
||||||
def should_notify_for_event?(user)
|
def user_wants_signal_for_event?(user)
|
||||||
event_type = @item[:type]
|
event_type = @item[:type]
|
||||||
return false if event_type.blank?
|
return false if event_type.blank?
|
||||||
|
|
||||||
|
|
@ -139,6 +138,6 @@ class Transaction::SignalNotification
|
||||||
else return false
|
else return false
|
||||||
end
|
end
|
||||||
|
|
||||||
user.preferences.dig('signal_notifications', 'events', event_key) == true
|
user.preferences.dig('notification_config', 'matrix', event_key, 'channel', 'signal') == true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -57,20 +57,13 @@ class AddSignalNotificationSettings < ActiveRecord::Migration[5.2]
|
||||||
frontend: false
|
frontend: false
|
||||||
)
|
)
|
||||||
|
|
||||||
# Permission for Signal notifications profile page
|
|
||||||
Permission.create_if_not_exists(
|
|
||||||
name: 'user_preferences.signal_notifications',
|
|
||||||
description: 'Manage Signal notification preferences',
|
|
||||||
preferences: {
|
|
||||||
translations: ['Profile - Signal Notifications']
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.down
|
def self.down
|
||||||
|
# Only destroy the transaction backend registration.
|
||||||
|
# Preserve signal_notification_enabled and signal_notification_channel_id
|
||||||
|
# so admin configuration survives addon reinstalls (setup.rb runs
|
||||||
|
# uninstall + install on every container start).
|
||||||
Setting.find_by(name: '0105_signal_notification')&.destroy
|
Setting.find_by(name: '0105_signal_notification')&.destroy
|
||||||
Setting.find_by(name: 'signal_notification_enabled')&.destroy
|
|
||||||
Setting.find_by(name: 'signal_notification_channel_id')&.destroy
|
|
||||||
Permission.find_by(name: 'user_preferences.signal_notifications')&.destroy
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ class SignalNotificationSender
|
||||||
return if recipient.blank?
|
return if recipient.blank?
|
||||||
return if message.blank?
|
return if message.blank?
|
||||||
|
|
||||||
api_url = channel.options[:api_url]
|
api_url = channel.options['bot_endpoint'] || channel.options[:bot_endpoint]
|
||||||
api_token = channel.options[:api_token]
|
api_token = channel.options['bot_token'] || channel.options[:bot_token]
|
||||||
|
|
||||||
return if api_url.blank? || api_token.blank?
|
return if api_url.blank? || api_token.blank?
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue