Init version of twitter admin.
This commit is contained in:
parent
272a569b10
commit
b990fa6daf
19 changed files with 342 additions and 152 deletions
|
@ -654,6 +654,9 @@ class App.ControllerModal extends App.Controller
|
|||
post: ->
|
||||
# nothing
|
||||
|
||||
element: =>
|
||||
@el
|
||||
|
||||
render: =>
|
||||
if @buttonSubmit is true
|
||||
@buttonSubmit = 'Submit'
|
||||
|
@ -688,6 +691,11 @@ class App.ControllerModal extends App.Controller
|
|||
e.preventDefault()
|
||||
@el.modal('hide')
|
||||
|
||||
formParams: =>
|
||||
if @container
|
||||
return @formParam(@container.find('.modal form'))
|
||||
return @formParam(@$('.modal form'))
|
||||
|
||||
onShow: ->
|
||||
# do nothing
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal
|
|||
buttonSubmit: 'yes'
|
||||
buttonClass: 'btn--danger'
|
||||
head: 'Confirm'
|
||||
small: true
|
||||
|
||||
content: ->
|
||||
App.i18n.translateContent('Sure to delete this object?')
|
||||
|
@ -275,9 +276,9 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal
|
|||
onSubmit: =>
|
||||
@item.destroy(
|
||||
done: =>
|
||||
@close()
|
||||
if @callback
|
||||
@callback()
|
||||
@close()
|
||||
fail: =>
|
||||
@log 'errors'
|
||||
@close()
|
||||
|
@ -348,6 +349,8 @@ class App.ControllerNavSidbar extends App.ControllerContent
|
|||
constructor: (params) ->
|
||||
super
|
||||
|
||||
@params = params
|
||||
|
||||
# get groups
|
||||
groups = App.Config.get(@configKey)
|
||||
groupsUnsorted = []
|
||||
|
@ -385,6 +388,9 @@ class App.ControllerNavSidbar extends App.ControllerContent
|
|||
else if @target && item.target is window.location.hash
|
||||
item.active = true
|
||||
selectedItem = item
|
||||
else if @target && window.location.hash.match(item.target)
|
||||
item.active = true
|
||||
selectedItem = item
|
||||
else
|
||||
item.active = false
|
||||
|
||||
|
@ -400,7 +406,7 @@ class App.ControllerNavSidbar extends App.ControllerContent
|
|||
renderContainer: =>
|
||||
return if $( ".#{@configKey}" )[0]
|
||||
@html App.view('generic/navbar_level2/index')(
|
||||
className: @configKey
|
||||
className: @configKey
|
||||
)
|
||||
|
||||
renderNavBar: (selectedItem) =>
|
||||
|
@ -427,9 +433,8 @@ class App.ControllerNavSidbar extends App.ControllerContent
|
|||
@activeController.render()
|
||||
return
|
||||
|
||||
@activeController = new selectedItem.controller(
|
||||
el: @$('.main')
|
||||
)
|
||||
@params.el = @$('.main')
|
||||
@activeController = new selectedItem.controller(@params)
|
||||
|
||||
class App.GenericHistory extends App.ControllerModal
|
||||
buttonClose: true
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'click .js-new': 'new'
|
||||
'click .js-edit': 'edit'
|
||||
'click .js-delete': 'delete'
|
||||
'click .js-create-app': 'createApp'
|
||||
'click .js-new': 'new'
|
||||
'click .js-edit': 'edit'
|
||||
'click .js-delete': 'delete'
|
||||
'click .js-configApp': 'configApp'
|
||||
'click .js-configApp': 'configApp'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
# check authentication
|
||||
return if !@authenticate()
|
||||
|
||||
@render()
|
||||
|
||||
#@interval(@load, 60000)
|
||||
#@load()
|
||||
@load()
|
||||
|
||||
load: ->
|
||||
load: =>
|
||||
@startLoading()
|
||||
@ajax(
|
||||
id: 'twitter_index'
|
||||
type: 'GET'
|
||||
url: @apiPath + '/channels/twitter_index'
|
||||
url: "#{@apiPath}/channels/twitter_index"
|
||||
processData: true
|
||||
success: (data, status, xhr) =>
|
||||
@stopLoading()
|
||||
|
@ -29,73 +26,173 @@ class Index extends App.ControllerContent
|
|||
@render(data)
|
||||
)
|
||||
|
||||
render: =>
|
||||
# accounts = App.Twitter.search(
|
||||
# sortBy: 'name'
|
||||
# )
|
||||
render: (data) =>
|
||||
|
||||
# # show description button, only if content exists
|
||||
# showDescription = false
|
||||
# if App.Twitter.description
|
||||
# if !_.isEmpty(accounts)
|
||||
# showDescription = true
|
||||
# else
|
||||
# description = marked(App.Twitter.description)
|
||||
# if no twitter app is registered, show into
|
||||
if !App.ExternalCredential.findByAttribute(name: 'twitter')
|
||||
@html App.view('twitter/index')()
|
||||
return
|
||||
|
||||
@html App.view('twitter/index')()
|
||||
channels = []
|
||||
for channel_id in data.channel_ids
|
||||
channel = App.Channel.find(channel_id)
|
||||
if channel && channel.options && channel.options.sync && channel.options.sync.search
|
||||
for search in channel.options.sync.search
|
||||
displayName = '-'
|
||||
if search.group_id
|
||||
group = App.Group.find(search.group_id)
|
||||
displayName = group.displayName()
|
||||
search.groupName = displayName
|
||||
if channel && channel.options && channel.options.sync && channel.options.sync.mentions
|
||||
displayName = '-'
|
||||
if channel.options.sync.mentions.group_id
|
||||
group = App.Group.find(channel.options.sync.mentions.group_id)
|
||||
displayName = group.displayName()
|
||||
channel.options.sync.mentions.groupName = displayName
|
||||
if channel && channel.options && channel.options.sync && channel.options.sync.direct_messages
|
||||
displayName = '-'
|
||||
if channel.options.sync.direct_messages.group_id
|
||||
group = App.Group.find(channel.options.sync.direct_messages.group_id)
|
||||
displayName = group.displayName()
|
||||
channel.options.sync.direct_messages.groupName = displayName
|
||||
channels.push channel
|
||||
@html App.view('twitter/list')(
|
||||
channels: channels
|
||||
)
|
||||
# accounts: accounts
|
||||
# showDescription: showDescription
|
||||
# description: description
|
||||
|
||||
createApp: ->
|
||||
modal = new App.ControllerModal
|
||||
if @channel_id
|
||||
@edit(undefined, @channel_id)
|
||||
|
||||
configApp: ->
|
||||
external_credential = App.ExternalCredential.findByAttribute(name: 'twitter')
|
||||
modal = new App.ControllerModal(
|
||||
head: 'Connect Twitter App'
|
||||
container: @el.parents('.content')
|
||||
content: App.view('twitter/app_create')
|
||||
contentInline: App.view('twitter/app_config')(external_credential: external_credential)
|
||||
shown: true
|
||||
button: 'Connect'
|
||||
cancel: true
|
||||
onSubmit: =>
|
||||
@html App.view('twitter/list')()
|
||||
modal.close()
|
||||
small: true
|
||||
onSubmit: (e) =>
|
||||
@formDisable(e)
|
||||
|
||||
# verify app credentals
|
||||
@ajax(
|
||||
id: 'twitter_app_verify'
|
||||
type: 'POST'
|
||||
url: "#{@apiPath}/external_credentials/twitter/app_verify"
|
||||
data: JSON.stringify(modal.formParams())
|
||||
processData: true
|
||||
success: (data, status, xhr) =>
|
||||
if data.attributes
|
||||
if !external_credential
|
||||
external_credential = new App.ExternalCredential
|
||||
external_credential.load(name: 'twitter', credentials: modal.formParams())
|
||||
external_credential.save(
|
||||
done: =>
|
||||
@load()
|
||||
modal.close()
|
||||
fail: ->
|
||||
modal.element().find('.alert').removeClass('hidden').text('Unable to create entry.')
|
||||
)
|
||||
return
|
||||
@formEnable(e)
|
||||
modal.element().find('.alert').removeClass('hidden').text(data.error || 'Unable to verify App.')
|
||||
)
|
||||
)
|
||||
|
||||
new: (e) ->
|
||||
# e.preventDefault()
|
||||
# new App.ControllerGenericNew(
|
||||
# pageData:
|
||||
# title: 'SLAs'
|
||||
# object: 'Sla'
|
||||
# objects: 'SLAs'
|
||||
# genericObject: 'Sla'
|
||||
# container: @el.closest('.content')
|
||||
# callback: @load
|
||||
# large: true
|
||||
# )
|
||||
window.location.href = "#{@apiPath}/external_credentials/twitter/link_account"
|
||||
|
||||
edit: (e) ->
|
||||
# e.preventDefault()
|
||||
# id = $(e.target).closest('.action').data('id')
|
||||
# new App.ControllerGenericEdit(
|
||||
# id: id
|
||||
# pageData:
|
||||
# title: 'SLAs'
|
||||
# object: 'Sla'
|
||||
# objects: 'SLAs'
|
||||
# genericObject: 'Sla'
|
||||
# callback: @load
|
||||
# container: @el.closest('.content')
|
||||
# large: true
|
||||
# )
|
||||
edit: (e, id) =>
|
||||
if e
|
||||
e.preventDefault()
|
||||
id = $(e.target).closest('.action').data('id')
|
||||
channel = App.Channel.find(id)
|
||||
content = $( App.view('twitter/account_edit')(channel: channel) )
|
||||
|
||||
delete: (e) ->
|
||||
# e.preventDefault()
|
||||
# id = $(e.target).closest('.action').data('id')
|
||||
# item = App.Twitter.find(id)
|
||||
# new App.ControllerGenericDestroyConfirm(
|
||||
# item: item
|
||||
# container: @el.closest('.content')
|
||||
# callback: @load
|
||||
# )
|
||||
groupSelection = (selected_id, el, prefix) ->
|
||||
selection = App.UiElement.select.render(
|
||||
name: "#{prefix}::group_id"
|
||||
multiple: false
|
||||
limit: 100
|
||||
null: false
|
||||
relation: 'Group'
|
||||
nulloption: true
|
||||
default: selected_id
|
||||
)
|
||||
el.find('.js-groups').html(selection)
|
||||
|
||||
placeholderAdd = (value = '', group_id) ->
|
||||
placeholder = content.find('.js-searchTermPlaceholder').clone()
|
||||
placeholder.removeClass('hidden').removeClass('js-searchTermPlaceholder')
|
||||
placeholder.find('input').val(value)
|
||||
placeholder.find('input').attr('name', 'search::term')
|
||||
groupSelection(group_id, placeholder, 'search')
|
||||
content.find('.js-searchTermList').append(placeholder)
|
||||
|
||||
for item in channel.options.sync.search
|
||||
placeholderAdd(item.term, item.group_id, 'search')
|
||||
|
||||
content.find('.js-searchTermAdd').on('click', ->
|
||||
placeholderAdd('', '')
|
||||
)
|
||||
content.find('.js-searchTerm').on('click', '.js-searchTermRemove',(e) ->
|
||||
$(e.target).closest('.js-searchTermItem').remove()
|
||||
)
|
||||
|
||||
groupSelection(channel.options.sync.mentions.group_id, content.find('.js-mention'), 'mentions')
|
||||
groupSelection(channel.options.sync.direct_messages.group_id, content.find('.js-directMessage'), 'direct_messages')
|
||||
|
||||
modal = new App.ControllerModal(
|
||||
head: 'Twitter Account'
|
||||
container: @el.parents('.content')
|
||||
contentInline: content
|
||||
shown: true
|
||||
cancel: true
|
||||
onSubmit: (e) =>
|
||||
@formDisable(e)
|
||||
params = modal.formParams()
|
||||
search = []
|
||||
position = 0
|
||||
if params.search
|
||||
if _.isArray(params.search.term)
|
||||
for key in params.search.term
|
||||
item =
|
||||
term: params.search.term[position]
|
||||
group_id: params.search.group_id[position]
|
||||
search.push item
|
||||
position += 1
|
||||
else
|
||||
search.push params.search
|
||||
params.search = search
|
||||
channel.options.sync = params
|
||||
@ajax(
|
||||
id: 'channel_twitter_update'
|
||||
type: 'POST'
|
||||
url: "#{@apiPath}/channels/twitter_verify/#{channel.id}"
|
||||
data: JSON.stringify(channel.attributes())
|
||||
processData: true
|
||||
success: (data, status, xhr) =>
|
||||
@load()
|
||||
modal.close()
|
||||
fail: =>
|
||||
@formEnable(e)
|
||||
)
|
||||
)
|
||||
|
||||
delete: (e) =>
|
||||
e.preventDefault()
|
||||
id = $(e.target).closest('.action').data('id')
|
||||
item = App.Channel.find(id)
|
||||
new App.ControllerGenericDestroyConfirm(
|
||||
item: item
|
||||
container: @el.closest('.content')
|
||||
callback: @load
|
||||
)
|
||||
|
||||
description: (e) =>
|
||||
new App.ControllerGenericDescription(
|
||||
|
@ -103,4 +200,4 @@ class Index extends App.ControllerContent
|
|||
container: @el.closest('.content')
|
||||
)
|
||||
|
||||
App.Config.set( 'Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
||||
App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: Index, role: ['Admin'] }, 'NavBarAdmin')
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
class IndexRouter extends App.ControllerNavSidbar
|
||||
configKey: 'NavBarAdmin'
|
||||
|
||||
App.Config.set( 'manage', IndexRouter, 'Routes' )
|
||||
App.Config.set( 'manage/:target', IndexRouter, 'Routes' )
|
||||
App.Config.set( 'settings/:target', IndexRouter, 'Routes' )
|
||||
App.Config.set( 'channels/:target', IndexRouter, 'Routes' )
|
||||
App.Config.set( 'system/:target', IndexRouter, 'Routes' )
|
||||
App.Config.set('manage', IndexRouter, 'Routes')
|
||||
App.Config.set('manage/:target', IndexRouter, 'Routes')
|
||||
App.Config.set('settings/:target', IndexRouter, 'Routes')
|
||||
App.Config.set('channels/:target', IndexRouter, 'Routes')
|
||||
App.Config.set('channels/:target/:channel_id', IndexRouter, 'Routes')
|
||||
App.Config.set('system/:target', IndexRouter, 'Routes')
|
||||
|
||||
App.Config.set( 'Manage', { prio: 1000, name: 'Manage', target: '#manage', role: ['Admin'] }, 'NavBarAdmin' )
|
||||
App.Config.set( 'Channels', { prio: 2500, name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBarAdmin' )
|
||||
App.Config.set( 'Settings', { prio: 7000, name: 'Settings', target: '#settings', role: ['Admin'] }, 'NavBarAdmin' )
|
||||
App.Config.set( 'System', { prio: 8000, name: 'System', target: '#system', role: ['Admin'] }, 'NavBarAdmin' )
|
||||
App.Config.set('Manage', { prio: 1000, name: 'Manage', target: '#manage', role: ['Admin'] }, 'NavBarAdmin')
|
||||
App.Config.set('Channels', { prio: 2500, name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBarAdmin')
|
||||
App.Config.set('Settings', { prio: 7000, name: 'Settings', target: '#settings', role: ['Admin'] }, 'NavBarAdmin')
|
||||
App.Config.set('System', { prio: 8000, name: 'System', target: '#system', role: ['Admin'] }, 'NavBarAdmin')
|
||||
|
|
|
@ -206,4 +206,4 @@ class Verify extends App.ControllerContent
|
|||
removeAll: true
|
||||
@formEnable( @$('form') )
|
||||
|
||||
App.Config.set( 'password_reset_verify/:token', Verify, 'Routes' )
|
||||
App.Config.set('password_reset_verify/:token', Verify, 'Routes')
|
||||
|
|
|
@ -77,6 +77,7 @@ class _ajaxSingleton
|
|||
head: 'StatusCode: ' + status
|
||||
contentInline: '<pre>' + App.Utils.htmlEscape(detail) + '</pre>'
|
||||
buttonClose: true
|
||||
buttonSubmit: false
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -115,7 +115,6 @@ class App.Auth
|
|||
|
||||
# store user data
|
||||
sessionUser = App.User.fullLocal(data.session.id)
|
||||
console.log('set', sessionUser)
|
||||
App.Session.set(sessionUser)
|
||||
|
||||
# trigger auth ok with new session data
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
class App.ExternalCredential extends App.Model
|
||||
@configure 'ExternalCredential', 'name', 'credentials'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/external_credentials'
|
|
@ -0,0 +1,31 @@
|
|||
<div class="alert alert--danger hidden" role="alert"></div>
|
||||
<fieldset>
|
||||
|
||||
<%- @T('Search Terms') %>
|
||||
<div class="js-searchTerm">
|
||||
<div class="js-searchTermItem js-searchTermPlaceholder hidden">
|
||||
<input name="" value=""> -> <div class="js-groups"></div>
|
||||
<div class="btn btn--text js-searchTermRemove">
|
||||
<%- @Icon('trash') %> <%- @T('Remove') %>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="js-searchTermList"></div>
|
||||
<div class="btn btn--text js-searchTermAdd">
|
||||
<%- @Icon('plus-small') %> <%- @T('Add') %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="js-mention">
|
||||
<%- @T('Mentions') %> -> <div class="js-groups"></div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="js-directMessage">
|
||||
<%- @T('Direct Messages') %> -> <div class="js-groups"></div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
23
app/assets/javascripts/app/views/twitter/app_config.jst.eco
Normal file
23
app/assets/javascripts/app/views/twitter/app_config.jst.eco
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div class="alert alert--danger hidden" role="alert"></div>
|
||||
<p>
|
||||
The tutorial on how to create a Twitter App is hosted on <a href="http://zammad.org/twitter-app-tutorial" target="_blank">zammad.org/twitter-app-tutorial</a>
|
||||
</p>
|
||||
<fieldset>
|
||||
<h2>Enter your Twitter App Keys</h2>
|
||||
<div class="input form-group">
|
||||
<div class="formGroup-label">
|
||||
<label for="consumer_key">Twitter API Key <span>*</span></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="consumer_key" type="text" name="consumer_key" value="<% if @external_credential && @external_credential.credentials: %><%= @external_credential.credentials.consumer_key %><% end %>" class="form-control" required autocomplete="off" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="input form-group">
|
||||
<div class="formGroup-label">
|
||||
<label for="consumer_secret">Twitter API Secret <span>*</span></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="consumer_secret" type="text" name="consumer_secret" value="<% if @external_credential && @external_credential.credentials: %><%= @external_credential.credentials.consumer_secret %><% end %>" class="form-control" required autocomplete="off" >
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
|
@ -1,32 +0,0 @@
|
|||
<h2>Create Twitter App</h2>
|
||||
<p>
|
||||
The tutorial on how to create a Twitter App is hosted on <a href="http://zammad.org/twitter-app-tutorial" target="_blank">zammad.org/twitter-app-tutorial</a>
|
||||
</p>
|
||||
<fieldset>
|
||||
<div class="input form-group">
|
||||
<div class="formGroup-label">
|
||||
<label for="CallbackURL">Callback URL</label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="CallbackURL" type="text" name="name" class="form-control" value="http://example.com/twitter-app" readonly>
|
||||
<span class="help-block">You need this callback URL for the Twitter App setup.</span>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Enter your Twitter App Keys</h2>
|
||||
<div class="input form-group">
|
||||
<div class="formGroup-label">
|
||||
<label for="TwitterApiKey">Twitter API Key <span>*</span></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="TwitterApiKey" type="text" name="name" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="input form-group">
|
||||
<div class="formGroup-label">
|
||||
<label for="TwitterApiKeySecret">Twitter API Secret <span>*</span></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="TwitterApiKeySecret" type="text" name="name" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
|
@ -9,6 +9,6 @@
|
|||
<p>
|
||||
Lorem ipsum Consequat ex dolore ullamco dolor ut eu eiusmod voluptate. Lorem ipsum Non aliquip Ut veniam cupidatat velit deserunt. Lorem ipsum Id reprehenderit deserunt esse eiusmod exercitation. Lorem ipsum Voluptate mollit sed Ut nulla consequat enim. Lorem ipsum Adipisicing ullamco dolor elit officia pariatur ex ea laboris Ut exercitation proident sed. Lorem ipsum In officia reprehenderit sed nulla incididunt aute incididunt ad quis tempor. Lorem ipsum Dolore est id minim dolore et labore incididunt commodo. Lorem ipsum Excepteur non consectetur anim ut nostrud amet et. Lorem ipsum Sunt nostrud nulla officia aute laborum enim in pariatur sit enim et.
|
||||
</p>
|
||||
<div class="btn btn--success js-create-app"><%- @T('Connect Twitter App') %></div>
|
||||
<div class="btn btn--success js-configApp"><%- @T('Connect Twitter App') %></div>
|
||||
</div>
|
||||
</div>
|
|
@ -4,47 +4,60 @@
|
|||
</div>
|
||||
|
||||
<div class="page-header-meta">
|
||||
<a class="btn js-config"><%- @T('Configure App') %></a>
|
||||
<a class="btn js-configApp"><%- @T('Configure App') %></a>
|
||||
<a class="btn btn--success js-new"><%- @T('Add Account') %></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
<div class="action">
|
||||
<% for channel in @channels: %>
|
||||
<div class="action" data-id="<%= channel.id %>">
|
||||
<div class="action-block action-row">
|
||||
<h2><%- @Icon('status', 'supergood-color inline') %> Zammad Community <span class="text-muted">@zammad_community</span></h2>
|
||||
<h2><%- @Icon('status', 'supergood-color inline') %> <%= channel.options.user.name %> <span class="text-muted">@<%= channel.options.user.screen_name %></span></h2>
|
||||
</div>
|
||||
<div class="action-flow action-flow--row">
|
||||
<div class="action-block">
|
||||
<h3><%- @T('Search Terms') %></h3>
|
||||
zammad
|
||||
<% if channel.options.sync.search: %>
|
||||
<% for search in channel.options.sync.search: %>
|
||||
<%= search.term %><br>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%- @Icon('arrow-right', 'action-flow-icon') %>
|
||||
<div class="action-block">
|
||||
<h3><%- @T('Group') %></h3>
|
||||
social network
|
||||
<% if channel.options.sync.search: %>
|
||||
<% for search in channel.options.sync.search: %>
|
||||
<%= search.groupName %><br>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-flow action-flow--row">
|
||||
<div class="action-block">
|
||||
<h3><%- @T('Mentions') %></h3>
|
||||
@zammad_community
|
||||
@<%= channel.options.user.screen_name %>
|
||||
</div>
|
||||
<%- @Icon('arrow-right', 'action-flow-icon') %>
|
||||
<div class="action-block">
|
||||
<h3><%- @T('Group') %></h3>
|
||||
social network
|
||||
<% if channel.options.sync.mentions: %>
|
||||
<%= channel.options.sync.mentions.groupName %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-flow action-flow--row">
|
||||
<div class="action-block">
|
||||
<h3><%- @T('Direct Messages') %></h3>
|
||||
@zammad_community
|
||||
@<%= channel.options.user.screen_name %>
|
||||
</div>
|
||||
<%- @Icon('arrow-right', 'action-flow-icon') %>
|
||||
<div class="action-block">
|
||||
<h3><%- @T('Group') %></h3>
|
||||
social network
|
||||
<% if channel.options.sync.direct_messages: %>
|
||||
<%= channel.options.sync.direct_messages.groupName %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-controls">
|
||||
|
@ -52,4 +65,5 @@
|
|||
<div class="sla-edit btn js-edit"><%- @T('Edit') %></div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
|
@ -45,6 +45,28 @@ curl http://localhost/api/v1/channels.json -v -u #{login}:#{password} -H "Conten
|
|||
model_destory_render(Channel, params)
|
||||
end
|
||||
|
||||
def twitter_index
|
||||
assets = {}
|
||||
ExternalCredential.where(name: 'twitter').each {|external_credential|
|
||||
assets = external_credential.assets(assets)
|
||||
}
|
||||
channel_ids = []
|
||||
Channel.order(:id).each {|channel|
|
||||
next if channel.area != 'Twitter::Account'
|
||||
assets = channel.assets(assets)
|
||||
channel_ids.push channel.id
|
||||
}
|
||||
render json: {
|
||||
assets: assets,
|
||||
channel_ids: channel_ids,
|
||||
}
|
||||
end
|
||||
|
||||
def twitter_verify
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
model_update_render(Channel, params)
|
||||
end
|
||||
|
||||
def email_index
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
system_online_service = Setting.get('system_online_service')
|
||||
|
|
|
@ -15,28 +15,12 @@ class ExternalCredentialsController < ApplicationController
|
|||
|
||||
def create
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
|
||||
# try access
|
||||
begin
|
||||
attributes = ExternalCredential.app_verify(params)
|
||||
model_create_render(ExternalCredential, { name: params[:provider].downcase, credentials: attributes })
|
||||
return
|
||||
rescue => e
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
end
|
||||
model_create_render(ExternalCredential, params)
|
||||
end
|
||||
|
||||
def update
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
|
||||
# try access
|
||||
begin
|
||||
attributes = ExternalCredential.app_verify(params)
|
||||
model_update_render(ExternalCredential, { name: params[:provider].downcase, credentials: attributes })
|
||||
return
|
||||
rescue => e
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
end
|
||||
model_update_render(ExternalCredential, params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -44,26 +28,29 @@ class ExternalCredentialsController < ApplicationController
|
|||
model_destory_render(ExternalCredential, params)
|
||||
end
|
||||
|
||||
def app_verify
|
||||
attributes = ExternalCredential.app_verify(params)
|
||||
render json: { attributes: attributes }, status: :ok
|
||||
return
|
||||
rescue => e
|
||||
render json: { error: e.message }, status: :ok
|
||||
|
||||
end
|
||||
|
||||
def link_account
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
provider = params[:provider].downcase
|
||||
|
||||
attributes = ExternalCredential.request_account_to_link(provider, callback_url(provider))
|
||||
|
||||
session[:request_token] = attributes[:request_token]
|
||||
|
||||
redirect_to attributes[:authorize_url]
|
||||
end
|
||||
|
||||
def callback
|
||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||
provider = params[:provider].downcase
|
||||
|
||||
channel = ExternalCredential.link_account(provider, session[:request_token], params)
|
||||
|
||||
session[:request_token] = nil
|
||||
|
||||
render json: channel
|
||||
redirect_to app_url(provider, channel.id)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -72,4 +59,8 @@ class ExternalCredentialsController < ApplicationController
|
|||
"#{Setting.get('http_type')}://#{Setting.get('fqdn')}#{Rails.configuration.api_path}/external_credentials/#{provider}/callback"
|
||||
end
|
||||
|
||||
def app_url(provider, channel_id)
|
||||
"#{Setting.get('http_type')}://#{Setting.get('fqdn')}/#channels/#{provider}/#{channel_id}"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -47,6 +47,8 @@ class Channel::Driver::Twitter
|
|||
|
||||
def fetch (options, channel)
|
||||
|
||||
options = check_external_credential(options)
|
||||
|
||||
@tweet = Tweet.new(options[:auth])
|
||||
@sync = options[:sync]
|
||||
@channel = channel
|
||||
|
@ -90,6 +92,8 @@ class Channel::Driver::Twitter
|
|||
# return if we run import mode
|
||||
return if Setting.get('import_mode')
|
||||
|
||||
options = check_external_credential(options)
|
||||
|
||||
@tweet = Tweet.new(options[:auth])
|
||||
tweet = @tweet.from_article(article)
|
||||
disconnect
|
||||
|
@ -164,4 +168,15 @@ class Channel::Driver::Twitter
|
|||
counter += 1
|
||||
}
|
||||
end
|
||||
|
||||
def check_external_credential(options)
|
||||
if options[:auth] && options[:auth][:external_credential_id]
|
||||
external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
|
||||
fail "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential
|
||||
options[:auth][:consumer_key] = external_credential.credentials['consumer_key']
|
||||
options[:auth][:consumer_secret] = external_credential.credentials['consumer_secret']
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -9,8 +9,12 @@ Zammad::Application.routes.draw do
|
|||
match api_path + '/channels/email_verify', to: 'channels#email_verify', via: :post
|
||||
match api_path + '/channels/email_notification', to: 'channels#email_notification', via: :post
|
||||
|
||||
# twitter helper
|
||||
match api_path + '/channels/twitter_index', to: 'channels#twitter_index', via: :get
|
||||
match api_path + '/channels/twitter_verify/:id', to: 'channels#twitter_verify', via: :post
|
||||
|
||||
# channels
|
||||
match api_path + '/channels/group/:id', to: 'channels#group_update', via: :post
|
||||
match api_path + '/channels/:id', to: 'channels#destroy', via: :delete
|
||||
match api_path + '/channels/group/:id', to: 'channels#group_update', via: :post
|
||||
match api_path + '/channels/:id', to: 'channels#destroy', via: :delete
|
||||
|
||||
end
|
||||
|
|
|
@ -9,6 +9,7 @@ Zammad::Application.routes.draw do
|
|||
match api_path + '/external_credentials/:id', to: 'external_credentials#destroy', via: :delete
|
||||
|
||||
# callback URL
|
||||
match api_path + '/external_credentials/:provider/app_verify', to: 'external_credentials#app_verify', via: :post
|
||||
match api_path + '/external_credentials/:provider/link_account', to: 'external_credentials#link_account', via: :get
|
||||
match api_path + '/external_credentials/:provider/callback', to: 'external_credentials#callback', via: :get
|
||||
|
||||
|
|
|
@ -11,9 +11,15 @@ class ExternalCredential::Twitter
|
|||
|
||||
def self.request_account_to_link(callback_url, credentials = {})
|
||||
external_credential = ExternalCredential.find_by(name: 'twitter')
|
||||
if !credentials[:consumer_key]
|
||||
credentials[:consumer_key] = external_credential.credentials['consumer_key']
|
||||
end
|
||||
if !credentials[:consumer_secret]
|
||||
credentials[:consumer_secret] = external_credential.credentials['consumer_secret']
|
||||
end
|
||||
consumer = OAuth::Consumer.new(
|
||||
credentials[:consumer_key] || external_credential.credentials[:consumer_key],
|
||||
credentials[:consumer_secret] || external_credential.credentials[:consumer_secret], {
|
||||
credentials[:consumer_key],
|
||||
credentials[:consumer_secret], {
|
||||
site: 'https://api.twitter.com'
|
||||
})
|
||||
request_token = consumer.get_request_token(oauth_callback: callback_url)
|
||||
|
@ -25,7 +31,6 @@ class ExternalCredential::Twitter
|
|||
|
||||
def self.link_account(request_token, params)
|
||||
fail if request_token.params[:oauth_token] != params[:oauth_token]
|
||||
|
||||
external_credential = ExternalCredential.find_by(name: 'twitter')
|
||||
access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
|
||||
client = Twitter::REST::Client.new(
|
||||
|
@ -44,6 +49,7 @@ class ExternalCredential::Twitter
|
|||
user: {
|
||||
id: user.id,
|
||||
screen_name: user.screen_name,
|
||||
name: user.name,
|
||||
},
|
||||
auth: {
|
||||
external_credential_id: external_credential.id,
|
||||
|
|
Loading…
Reference in a new issue