Merge branch 'develop' of github.com:martini/zammad into develop

This commit is contained in:
Felix Niklas 2015-11-18 16:12:53 +01:00
commit 9a7413503b
15 changed files with 283 additions and 335 deletions

View file

@ -170,7 +170,7 @@ class App.ControllerGenericIndex extends App.Controller
# append content table # append content table
params = _.extend( params = _.extend(
{ {
el: @el.find('.table-overview') el: @$('.table-overview')
model: App[ @genericObject ] model: App[ @genericObject ]
objects: objects objects: objects
bindRow: bindRow:
@ -301,9 +301,9 @@ class App.ControllerDrox extends App.Controller
inline: (data) -> inline: (data) ->
@html App.view('generic/drox')(data) @html App.view('generic/drox')(data)
if data.text if data.text
@el.find('.drox-body').text(data.text) @$('.drox-body').text(data.text)
if data.html if data.html
@el.find('.drox-body').html(data.html) @$('.drox-body').html(data.html)
template: (data) -> template: (data) ->
drox = $( App.view('generic/drox')(data) ) drox = $( App.view('generic/drox')(data) )
@ -311,50 +311,6 @@ class App.ControllerDrox extends App.Controller
drox.find('.drox-body').append(content) drox.find('.drox-body').append(content)
drox drox
class App.ControllerLevel2 extends App.ControllerContent
events:
'click [data-toggle="tabnav"]': 'toggle',
constructor: ->
super
render: ->
# set title
@title @page.title
@navupdate @page.nav
@html App.view('generic/admin_level2/index')(
page: @page
menus: @menu
type: @type
target: @target
)
if !@target
@target = @menu[0]['target']
for menu in @menu
@el.find('.nav-tab-content').append('<div class="tabbable" id="' + menu.target + '"></div>')
if menu.controller && ( @toggleable is true || ( @toggleable is false && menu.target is @target ) )
params = menu.params || {}
params.el = @el.find( '#' + menu.target )
new menu.controller( params )
@el.find('.tabbable').addClass('hide')
@el.find( '#' + @target ).removeClass('hide')
@el.find('[data-toggle="tabnav"][href*="/' + @target + '"]').parent().addClass('active')
toggle: (e) ->
return true if @toggleable is false
e.preventDefault()
target = $(e.target).data('target')
$(e.target).parents('ul').find('li').removeClass('active')
$(e.target).parents('li').addClass('active')
@el.find('.tabbable').addClass('hide')
@el.find('#' + target).removeClass('hide')
# window.scrollTo(0,0)
class App.ControllerTabs extends App.Controller class App.ControllerTabs extends App.Controller
events: events:
'click .nav-tabs [data-toggle="tab"]': 'tabRemember', 'click .nav-tabs [data-toggle="tab"]': 'tabRemember',
@ -372,24 +328,25 @@ class App.ControllerTabs extends App.Controller
# insert content # insert content
for tab in @tabs for tab in @tabs
@el.find('.tab-content').append("<div class=\"tab-pane\" id=\"#{tab.target}\"></div>") @$('.tab-content').append("<div class=\"tab-pane\" id=\"#{tab.target}\"></div>")
if tab.controller if tab.controller
params = tab.params || {} params = tab.params || {}
params.name = tab.name params.name = tab.name
params.target = tab.target params.target = tab.target
params.el = @el.find( "##{tab.target}" ) params.el = @$( "##{tab.target}" )
new tab.controller( params ) new tab.controller( params )
# check if tabs need to be hidden # check if tabs need to be show / cant' use .tab(), because tabs are note shown (only one tab exists)
# if @tabs.length <= 1 if @tabs.length <= 1
# @el.find('.page-tabs').addClass('hide') @$('.tab-pane').addClass('active')
return
# set last or first tab to active # set last or first tab to active
@lastActiveTab = @Config.get('lastTab') @lastActiveTab = @Config.get('lastTab')
if @lastActiveTab && @el.find(".nav-tabs li a[href=#{@lastActiveTab}]")[0] if @lastActiveTab && @$(".nav-tabs li a[href=#{@lastActiveTab}]")[0]
@el.find(".nav-tabs li a[href=#{@lastActiveTab}]").tab('show') @$(".nav-tabs li a[href=#{@lastActiveTab}]").tab('show')
else else
@el.find('.nav-tabs li:first a').tab('show') @$('.nav-tabs li:first a').tab('show')
tabRemember: (e) => tabRemember: (e) =>
@lastActiveTab = $(e.target).attr('href') @lastActiveTab = $(e.target).attr('href')
@ -439,15 +396,22 @@ class App.ControllerNavSidbar extends App.ControllerContent
else else
item.active = false item.active = false
@render(selectedItem) @renderContainer(selectedItem)
@renderNavBar(selectedItem)
@bind( @bind(
'ui:rerender' 'ui:rerender'
=> =>
@render(selectedItem, true) @renderNavBar(selectedItem)
) )
render: (selectedItem, force) => renderContainer: =>
return if $( ".#{@configKey}" )[0]
@html App.view('generic/navbar_level2/index')(
className: @configKey
)
renderNavBar: (selectedItem) =>
# remember latest selected item # remember latest selected item
selectedItemMeta = selectedItemMeta =
@ -455,17 +419,24 @@ class App.ControllerNavSidbar extends App.ControllerContent
date: new Date date: new Date
App.Config.set("Runtime::#{@configKey}", selectedItemMeta) App.Config.set("Runtime::#{@configKey}", selectedItemMeta)
if !$( ".#{@configKey}" )[0] || force @$('.sidebar').html App.view('generic/navbar_level2/navbar')(
@html App.view('generic/navbar_l2')( groups: @groupsSorted
groups: @groupsSorted className: @configKey
className: @configKey )
)
if selectedItem if selectedItem
@el.find('li').removeClass('active') @$('li').removeClass('active')
@el.find("a[href=\"#{selectedItem.target}\"]").parent().addClass('active') @$("a[href=\"#{selectedItem.target}\"]").parent().addClass('active')
@executeController(selectedItem)
new selectedItem.controller( executeController: (selectedItem) =>
el: @el.find('.main')
# in case of rerendering
if @activeController && @activeController.render
@activeController.render()
return
@activeController = new selectedItem.controller(
el: @$('.main')
) )
class App.GenericHistory extends App.ControllerModal class App.GenericHistory extends App.ControllerModal
@ -580,7 +551,7 @@ class App.ActionRow extends App.Controller
for item in @items for item in @items
do (item) => do (item) =>
@el.find('[data-type="' + item.name + '"]').on( @$('[data-type="' + item.name + '"]').on(
'click', 'click',
(e) -> (e) ->
e.preventDefault() e.preventDefault()
@ -624,13 +595,13 @@ class App.Sidebar extends App.Controller
# init content callback # init content callback
for item in @items for item in @items
if item.callback if item.callback
item.callback( @el.find( '.sidebar[data-tab="' + item.name + '"] .sidebar-content' ) ) item.callback( @$( '.sidebar[data-tab="' + item.name + '"] .sidebar-content' ) )
# add item acctions # add item acctions
for item in @items for item in @items
if item.actions if item.actions
new App.ActionRow( new App.ActionRow(
el: @el.find('.sidebar[data-tab="' + item.name + '"] .js-actions') el: @$('.sidebar[data-tab="' + item.name + '"] .js-actions')
items: item.actions items: item.actions
type: 'small' type: 'small'
) )
@ -675,13 +646,13 @@ class App.Sidebar extends App.Controller
@tabs.removeClass('active') @tabs.removeClass('active')
# add active state # add active state
@el.find('.tabsSidebar-tab[data-tab=' + name + ']').addClass('active') @$('.tabsSidebar-tab[data-tab=' + name + ']').addClass('active')
# hide all content tabs # hide all content tabs
@sidebars.addClass('hide') @sidebars.addClass('hide')
# show active tab content # show active tab content
tabContent = @el.find('.sidebar[data-tab=' + name + ']') tabContent = @$('.sidebar[data-tab=' + name + ']')
tabContent.removeClass('hide') tabContent.removeClass('hide')
# remember current tab # remember current tab

View file

@ -16,15 +16,16 @@ class Index extends App.ControllerContent
@ajax( @ajax(
id: 'packages', id: 'packages',
type: 'GET', type: 'GET',
url: @apiPath + '/packages', url: "#{@apiPath}/packages",
processData: true, processData: true,
success: (data) => success: (data) =>
@render(data) @packages = data
@render()
) )
render: (data) -> render: ->
for item in data.packages for item in @packages
item.action = [] item.action = []
if item.state == 'installed' if item.state == 'installed'
# item.action = ['uninstall', 'deactivate'] # item.action = ['uninstall', 'deactivate']
@ -36,7 +37,7 @@ class Index extends App.ControllerContent
@html App.view('package')( @html App.view('package')(
head: 'Dashboard' head: 'Dashboard'
packages: data.packages packages: @packages
) )
action: (e) -> action: (e) ->
@ -48,12 +49,12 @@ class Index extends App.ControllerContent
if httpType if httpType
@ajax( @ajax(
id: 'packages', id: 'packages'
type: httpType, type: httpType
url: @apiPath + '/packages', url: "#{@apiPath}/packages",
data: JSON.stringify( { id: id } ), data: JSON.stringify( { id: id } )
processData: false, processData: false
success: (data) => success: =>
@load() @load()
) )

View file

@ -1,7 +1,6 @@
class Index extends App.ControllerContent class Index extends App.ControllerContent
divClass: 'lala'
events: events:
'click [data-type="delete"]': 'destroy' 'click .js-delete': 'destroy'
constructor: -> constructor: ->
super super
@ -27,26 +26,25 @@ class Index extends App.ControllerContent
url: @apiPath + '/sessions' url: @apiPath + '/sessions'
success: (data) => success: (data) =>
@stopLoading() @stopLoading()
@render(data) App.Collection.loadAssets(data.assets)
@sessions = data.sessions
@render()
) )
render: (data) -> render: ->
# load assets
App.Collection.loadAssets( data.assets )
# fill users # fill users
for session in data.sessions for session in @sessions
if session.data && session.data.user_id if session.data && session.data.user_id
session.data.user = App.User.find( session.data.user_id ) session.data.user = App.User.find(session.data.user_id)
@html App.view('session')( @html App.view('session')(
sessions: data.sessions sessions: @sessions
) )
destroy: (e) -> destroy: (e) ->
e.preventDefault() e.preventDefault()
sessionId = $( e.target ).closest('a').data('session-id') sessionId = $(e.target ).closest('a').data('session-id')
@ajax( @ajax(
id: 'sessions/' + sessionId id: 'sessions/' + sessionId
type: 'DELETE' type: 'DELETE'
@ -55,4 +53,4 @@ class Index extends App.ControllerContent
@load() @load()
) )
App.Config.set( 'Session', { prio: 3700, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) App.Config.set('Session', { prio: 3700, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -11,47 +11,87 @@ class Index extends App.ControllerContent
return if !@authenticate() return if !@authenticate()
@title 'Translations', true @title 'Translations', true
@locale = App.i18n.get()
@render() @render()
@bind(
'i18n:translation_update',
=>
@load()
)
render: => render: =>
@html App.view('translation/index')()
options = {}
locales = App.Locale.all() locales = App.Locale.all()
currentLanguage = @locale
for locale in locales for locale in locales
options[locale.locale] = locale.name if locale.locale is @locale
configure_attributes = [ currentLanguage = locale.name
{ name: 'locale', display: '', tag: 'select', null: false, class: 'input', options: options, default: App.i18n.get() }, @html App.view('translation/index')(
] currentLanguage: currentLanguage
load = (params) =>
@translationToDo = new TranslationToDo(
el: @$('.js-ToDo')
locale: params.locale
)
@translationList = new TranslationList(
el: @$('.js-List')
locale: params.locale
)
new App.ControllerForm(
el: @$('.language')
model: { configure_attributes: configure_attributes }
autofocus: false
handlers: [load]
) )
@load()
load: =>
@ajax(
id: 'translations_admin'
type: 'GET'
url: "#{@apiPath}/translations/admin/lang/#{@locale}"
processData: true
success: (data, status, xhr) =>
@times = []
@stringsNotTranslated = []
@stringsTranslated = []
for item in data.list
# if item has changed
if item[2] isnt item[3]
@showAction()
# collect items
if item[4] is 'time'
@times.push item
else
if item[2] is ''
@stringsNotTranslated.push item
else
@stringsTranslated.push item
if !@translationToDo
@translationToDo = new TranslationToDo(
el: @$('.js-ToDo')
locale: @locale
)
@translationToDo.update(
stringsNotTranslated: @stringsNotTranslated
stringsTranslated: @stringsTranslated
times: @times
)
if !@translationList
@translationList = new TranslationList(
el: @$('.js-List')
locale: @locale
)
@translationList.update(
stringsNotTranslated: @stringsNotTranslated
stringsTranslated: @stringsTranslated
times: @times
)
)
showAction: =>
@$('.js-changes').removeClass('hidden')
release: => release: =>
rerender = -> rerender = ->
App.Event.trigger('ui:rerender') App.Event.trigger('ui:rerender')
if @translationToDo.changes() || @translationList.changes() console.log('rr')
if @translationList.changes()
App.Delay.set(rerender, 400) App.Delay.set(rerender, 400)
console.log('111', @translationList.changes())
hideAction: => hideAction: =>
@el.closest('.content').find('.js-changes').addClass('hidden') @el.closest('.content').find('.js-changes').addClass('hidden')
pushChanges: => pushChanges: =>
locale = @$('[name="locale"]').val()
@loader = new App.ControllerModalLoading( @loader = new App.ControllerModalLoading(
head: 'Push my changes' head: 'Push my changes'
message: 'Pushing translations to i18n.zammad.com' message: 'Pushing translations to i18n.zammad.com'
@ -62,7 +102,7 @@ class Index extends App.ControllerContent
id: 'translations' id: 'translations'
type: 'PUT' type: 'PUT'
url: "#{@apiPath}/translations/push" url: "#{@apiPath}/translations/push"
data: JSON.stringify(locale: locale) data: JSON.stringify(locale: @locale)
processData: false processData: false
success: (data, status, xhr) => success: (data, status, xhr) =>
@loader.update('Thanks for contributing!') @loader.update('Thanks for contributing!')
@ -73,8 +113,6 @@ class Index extends App.ControllerContent
) )
resetChanges: => resetChanges: =>
locale = @$('[name="locale"]').val()
@loader = new App.ControllerModalLoading( @loader = new App.ControllerModalLoading(
head: 'Reset changes' head: 'Reset changes'
message: 'Reseting changes...' message: 'Reseting changes...'
@ -85,11 +123,10 @@ class Index extends App.ControllerContent
id: 'translations' id: 'translations'
type: 'POST' type: 'POST'
url: "#{@apiPath}/translations/reset" url: "#{@apiPath}/translations/reset"
data: JSON.stringify(locale: locale) data: JSON.stringify(locale: @locale)
processData: false processData: false
success: (data, status, xhr) => success: (data, status, xhr) =>
App.Event.trigger('i18n:translation_todo_reload') App.Event.trigger('i18n:translation_update')
App.Event.trigger('i18n:translation_list_reload')
@hideAction() @hideAction()
@loader.hide() @loader.hide()
error: => error: =>
@ -97,8 +134,6 @@ class Index extends App.ControllerContent
) )
syncChanges: => syncChanges: =>
locale = @$('[name="locale"]').val()
@loader = new App.ControllerModalLoading( @loader = new App.ControllerModalLoading(
head: 'Get latest translations' head: 'Get latest translations'
message: 'Getting latest translations from i18n.zammad.com' message: 'Getting latest translations from i18n.zammad.com'
@ -106,8 +141,7 @@ class Index extends App.ControllerContent
) )
hide = => hide = =>
App.Event.trigger('i18n:translation_todo_reload') App.Event.trigger('i18n:translation_update')
App.Event.trigger('i18n:translation_list_reload')
@hideAction() @hideAction()
@loader.hide(1) @loader.hide(1)
@ -131,19 +165,17 @@ class Index extends App.ControllerContent
) )
class TranslationToDo extends App.Controller class TranslationToDo extends App.Controller
hasChanges: false
events: events:
'click .js-create': 'create' 'click .js-create': 'create'
'click .js-theSame': 'same' 'click .js-theSame': 'same'
constructor: -> constructor: ->
super super
update: (data) =>
for key, value of data
@[key] = value
@render() @render()
@bind(
'i18n:translation_todo_reload',
=>
@render()
)
render: => render: =>
@ -151,42 +183,37 @@ class TranslationToDo extends App.Controller
@html App.view('translation/english')() @html App.view('translation/english')()
return return
if !App.i18n.getNotTranslated(@locale) if !App.i18n.getNotTranslated(@locale) && _.isEmpty(@stringsNotTranslated)
@html '' @html ''
return return
listNotTranslated = [] if App.i18n.getNotTranslated(@locale)
for key, value of App.i18n.getNotTranslated(@locale) for key, value of App.i18n.getNotTranslated(@locale)
item = [ '', key, '', ''] item = [ '', key, '', '']
listNotTranslated.push item @stringsNotTranslated.push item
@html App.view('translation/todo')( @html App.view('translation/todo')(
list: listNotTranslated list: @stringsNotTranslated
) )
showAction: =>
@el.closest('.content').find('.js-changes').removeClass('hidden')
changes: =>
@hasChanges
create: (e) => create: (e) =>
e.preventDefault() e.preventDefault()
@hasChanges = true
@showAction()
field = $(e.target).closest('tr').find('.js-Item') field = $(e.target).closest('tr').find('.js-Item')
id = field.data('id')
source = field.data('source') source = field.data('source')
format = 'string'
target = field.val() target = field.val()
return if !target
# remove from not translated list # remove from not translated list
$(e.target).closest('tr').remove() $(e.target).closest('tr').remove()
# local update # local update
App.i18n.removeNotTranslated( @locale, source ) App.i18n.removeNotTranslated(@locale, source)
# update runtime if same language is used # update runtime if same language is used
if App.i18n.get() is @locale if App.i18n.get() is @locale
App.i18n.setMap( source, target, 'string' ) App.i18n.setMap(source, target, 'string')
# remote update # remote update
params = params =
@ -195,20 +222,27 @@ class TranslationToDo extends App.Controller
target: target target: target
target_initial: '' target_initial: ''
if id
method = 'PUT'
params.id = id
url = "#{@apiPath}/translations/#{id}"
else
method = 'POST'
url = "#{@apiPath}/translations"
@ajax( @ajax(
id: 'translations' id: 'translations'
type: 'POST' type: method
url: @apiPath + '/translations' url: url
data: JSON.stringify(params) data: JSON.stringify(params)
processData: false processData: false
success: (data, status, xhr) -> success: (data, status, xhr) ->
App.Event.trigger('i18n:translation_list_reload') App.Event.trigger('i18n:translation_update')
) )
same: (e) => same: (e) =>
e.preventDefault() e.preventDefault()
@hasChanges = true @hasChanges = true
@showAction()
field = $(e.target).closest('tr').find('.js-Item') field = $(e.target).closest('tr').find('.js-Item')
source = field.data('source') source = field.data('source')
@ -216,11 +250,11 @@ class TranslationToDo extends App.Controller
$(e.target).closest('tr').remove() $(e.target).closest('tr').remove()
# local update # local update
App.i18n.removeNotTranslated( @locale, source ) App.i18n.removeNotTranslated(@locale, source)
# update runtime if same language is used # update runtime if same language is used
if App.i18n.get() is @locale if App.i18n.get() is @locale
App.i18n.setMap( source, source, 'string' ) App.i18n.setMap(source, source, 'string')
# remote update # remote update
params = params =
@ -236,65 +270,33 @@ class TranslationToDo extends App.Controller
data: JSON.stringify(params) data: JSON.stringify(params)
processData: false processData: false
success: (data, status, xhr) -> success: (data, status, xhr) ->
App.Event.trigger('i18n:translation_list_reload') App.Event.trigger('i18n:translation_update')
) )
class TranslationList extends App.Controller class TranslationList extends App.Controller
hasChanges: false hasChanges: false
events: events:
'blur .js-translated input': 'update' 'blur .js-translated input': 'updateItem'
'click .js-translated .js-Reset': 'reset' 'click .js-translated .js-Reset': 'resetItem'
constructor: -> constructor: ->
super super
@load()
@bind(
'i18n:translation_list_reload',
=>
@load()
)
load: => update: (data) =>
@startLoading() for key, value of data
@ajax( @[key] = value
id: 'translations_admin' @render()
type: 'GET'
url: @apiPath + "/translations/admin/lang/#{@locale}"
processData: true
success: (data, status, xhr) =>
@stopLoading()
@render(data)
)
render: (data = {}) =>
@strings = []
@times = []
for item in data.list
if item[4] is 'time'
@times.push item
else
@strings.push item
render: =>
@html App.view('translation/list')( @html App.view('translation/list')(
times: @times times: @times
strings: @strings strings: @stringsTranslated
) )
ui = @
@changesAvailable = false
@$('.js-Item').each( (e) ->
id = $(@).data('id')
ui.updateRow(id)
)
if @changesAvailable
@showAction()
showAction: =>
@el.closest('.content').find('.js-changes').removeClass('hidden')
changes: => changes: =>
@hasChanges @hasChanges
reset: (e) -> resetItem: (e) ->
e.preventDefault() e.preventDefault()
@hasChanges = true @hasChanges = true
field = $(e.target).closest('tr').find('.js-Item') field = $(e.target).closest('tr').find('.js-Item')
@ -303,38 +305,12 @@ class TranslationList extends App.Controller
initial = field.data('initial') initial = field.data('initial')
format = field.data('format') format = field.data('format')
# if it's translated by user it self, delete it
if !initial || initial is ''
# locale reset
$(e.target).closest('tr').remove()
# update runtime if same language is used
if App.i18n.get() is @locale
App.i18n.setMap( source, '', format )
# remote reset
params =
id: id
@ajax(
id: 'translations'
type: 'DELETE'
url: @apiPath + '/translations/' + id
data: JSON.stringify(params)
processData: false
success: =>
App.i18n.setNotTranslated( @locale, source )
App.Event.trigger('i18n:translation_todo_reload')
)
return
# update runtime if same language is used # update runtime if same language is used
if App.i18n.get() is @locale if App.i18n.get() is @locale
App.i18n.setMap( source, initial, format ) App.i18n.setMap(source, initial, format)
# locale reset # locale reset
field.val( initial ) field.val(initial)
@updateRow(id) @updateRow(id)
# remote reset # remote reset
@ -345,24 +321,29 @@ class TranslationList extends App.Controller
@ajax( @ajax(
id: 'translations' id: 'translations'
type: 'PUT' type: 'PUT'
url: @apiPath + '/translations/' + id url: "#{@apiPath}/translations/#{id}"
data: JSON.stringify(params) data: JSON.stringify(params)
processData: false processData: false
success: (data, status, xhr) ->
App.Event.trigger('i18n:translation_update')
) )
update: (e) -> updateItem: (e) ->
e.preventDefault() e.preventDefault()
id = $( e.target ).data('id') @hasChanges = true
source = $( e.target ).data('source') field = $(e.target).closest('tr').find('.js-Item')
format = $( e.target ).data('format') id = field.data('id')
target = $( e.target ).val() source = field.data('source')
format = field.data('format')
target = field.val()
return if !target
# local update # local update
@updateRow(id) @updateRow(id)
# update runtime if same language is used # update runtime if same language is used
if App.i18n.get() is @locale if App.i18n.get() is @locale
App.i18n.setMap( source, target, format ) App.i18n.setMap(source, target, format)
# remote update # remote update
params = params =
@ -372,9 +353,11 @@ class TranslationList extends App.Controller
@ajax( @ajax(
id: 'translations' id: 'translations'
type: 'PUT' type: 'PUT'
url: @apiPath + '/translations/' + id url: "#{@apiPath}/translations/#{id}"
data: JSON.stringify(params) data: JSON.stringify(params)
processData: false processData: false
success: (data, status, xhr) ->
App.Event.trigger('i18n:translation_update')
) )
updateRow: (id) => updateRow: (id) =>
@ -384,11 +367,10 @@ class TranslationList extends App.Controller
reset = field.closest('tr').find('.js-Reset') reset = field.closest('tr').find('.js-Reset')
if current isnt initial if current isnt initial
@changesAvailable = true @changesAvailable = true
@showAction() reset.removeClass('hidden')
reset.show()
reset.closest('tr').addClass('warning') reset.closest('tr').addClass('warning')
else else
reset.hide() reset.addClass('hidden')
reset.closest('tr').removeClass('warning') reset.closest('tr').removeClass('warning')
App.Config.set( 'Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) App.Config.set('Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -1,17 +0,0 @@
<div class="sidebar <%= @className %>">
<% if @groups: %>
<% for group in @groups: %>
<h2><%- @T(group.name) %></h2>
<ul class="nav nav-pills nav-stacked">
<% if group.items: %>
<% for item in group.items: %>
<li <% if item.active: %>class="active"<% end %>><a href="<%= item.target %>"><%- @T(item.name) %></a></li>
<% end %>
<% end %>
</ul>
<% end %>
</div>
<div class="main flex"></div>

View file

@ -0,0 +1,2 @@
<div class="sidebar <%= @className %>"></div>
<div class="main flex"></div>

View file

@ -0,0 +1,12 @@
<% if @groups: %>
<% for group in @groups: %>
<h2><%- @T(group.name) %></h2>
<ul class="nav nav-pills nav-stacked">
<% if group.items: %>
<% for item in group.items: %>
<li <% if item.active: %>class="active"<% end %>><a href="<%= item.target %>"><%- @T(item.name) %></a></li>
<% end %>
<% end %>
</ul>
<% end %>
<% end %>

View file

@ -11,10 +11,12 @@
<% end %> <% end %>
</div> </div>
<div class="page-content"> <div class="page-content">
<ul class="nav nav-tabs" role="tablist"> <% if @tabs.length > 1: %>
<% for tab in @tabs: %> <ul class="nav nav-tabs" role="tablist">
<li><a href="#<%= tab.target %>" role="tab" data-toggle="tab"><%- @T( tab.name ) %></a></li> <% for tab in @tabs: %>
<li><a href="#<%= tab.target %>" role="tab" data-toggle="tab"><%- @T( tab.name ) %></a></li>
<% end %>
</ul>
<% end %> <% end %>
</ul>
<div class="tab-content"></div> <div class="tab-content"></div>
</div> </div>

View file

@ -21,7 +21,7 @@
<td title="<%= session.data.remote_id %>"><% if session.data.geo && session.data.geo.country_name: %><%= session.data.geo.country_name %> <%= session.data.geo.city_name %><% else: %><%= session.data.remote_id %><% end %></td> <td title="<%= session.data.remote_id %>"><% if session.data.geo && session.data.geo.country_name: %><%= session.data.geo.country_name %> <%= session.data.geo.city_name %><% else: %><%= session.data.remote_id %><% end %></td>
<td><%- @humanTime(session.created_at) %></td> <td><%- @humanTime(session.created_at) %></td>
<td><%- @humanTime(session.updated_at) %></td> <td><%- @humanTime(session.updated_at) %></td>
<td><a href="#" data-session-id="<%- session.id %>" data-type="delete" title="<%- @Ti('Delete') %>"><%- @Icon('trash') %></a></td> <td><a href="#" data-session-id="<%- session.id %>" class="js-delete" title="<%- @Ti('Delete') %>"><%- @Icon('trash') %></a></td>
</tr> </tr>
<% end %> <% end %>
</tbody> </tbody>

View file

@ -1,12 +1,11 @@
<div class="page-header"> <div class="page-header">
<div class="page-header-title"> <div class="page-header-title">
<h1><%- @T('Translations') %> <small></small></h1> <h1><%- @T('Translations') %> <small><%= @currentLanguage %></small></h1>
</div> </div>
<div class="page-header-meta"> <div class="page-header-meta">
<a class="btn btn--success js-syncChanges"><%- @T('Get latest translations') %></a> <a class="btn btn--success js-syncChanges"><%- @T('Get latest translations') %></a>
<a class="btn btn--danger hidden js-changes js-resetChanges"><%- @T('Reset changes') %></a> <a class="btn btn--danger hidden js-changes js-resetChanges"><%- @T('Reset changes') %></a>
<a class="btn btn--primary hidden js-changes js-pushChanges"><%- @T('Push my changes') %></a> <a class="btn btn--primary hidden js-changes js-pushChanges"><%- @T('Push my changes') %></a>
<div class="language"></div>
</div> </div>
</div> </div>
<div class="page-content"> <div class="page-content">

View file

@ -9,16 +9,15 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% if @times: %> <% for time in @times: %>
<% for time in @times: %> <% changed = false %>
<tr> <% changed = true if time[2] isnt time[3] %>
<td title="<%= time[1] %>"><%= time[1] %></td> <tr <% if changed: %>class="warning"<% end %>>
<td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= time[2] %>" data-source="<%= time[1] %>" data-initial="<%= time[3] %>" data-id="<%= time[0] %>" data-format="<%= time[4] %>"></td> <td title="<%= time[1] %>"><%= time[1] %>
<td title="<%= time[3] %>"><%= time[3]%></td> <td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= time[2] %>" data-source="<%= time[1] %>" data-initial="<%= time[3] %>" data-id="<%= time[0] %>" data-format="<%= time[4] %>">
<td><a href="#" class="js-Reset"><%- @T('Reset') %></a></td> <td title="<%= time[3] %>"><%= time[3]%>
</tr> <td><a href="#" class="js-Reset <% if !changed: %>hidden<% end %>"><%- @T('Reset') %></a>
<% end %> <% end %>
<% end %>
</tbody> </tbody>
</table> </table>
@ -33,15 +32,14 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% if @strings: %> <% for item in @strings: %>
<% for item in @strings: %> <% changed = false %>
<tr> <% changed = true if item[2] isnt item[3] %>
<td title="<%= item[1] %>"><%= item[1] %></td> <tr <% if changed: %>class="warning"<% end %>>
<td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-source="<%= item[1] %>" data-initial="<%= item[3] %>" data-id="<%= item[0] %>" data-format="<%= item[4] %>"></td> <td title="<%= item[1] %>"><%= item[1] %>
<td title="<%= item[3] %>"><%= item[3]%></td> <td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-source="<%= item[1] %>" data-initial="<%= item[3] %>" data-id="<%= item[0] %>" data-format="<%= item[4] %>">
<td><a href="#" class="js-Reset"><%- @T('Reset') %></a></td> <td title="<%= item[3] %>"><%= item[3]%>
</tr> <td><a href="#" class="js-Reset <% if !changed: %>hidden<% end %>"><%- @T('Reset') %></a>
<% end %>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>

View file

@ -8,14 +8,11 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% if @list: %> <% for item in @list: %>
<% for item in @list: %> <tr>
<tr> <td title="<%= item[1] %>"><%= item[1] %>
<td title="<%= item[1] %>"><%= item[1] %></td> <td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-source="<%= item[1] %>" data-id="<%= item[0] %>">
<td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-source="<%= item[1] %>"></td> <td><a href="#" class="js-create"><%- @T('Create') %></a> / <a href="#" class="js-theSame"><%- @T('is the same') %></a>
<td><a href="#" class="js-create"><%- @T('Create') %></a> / <a href="#" class="js-theSame"><%- @T('is the same') %></a></td>
</tr>
<% end %>
<% end %> <% end %>
</tbody> </tbody>
</table> </table>

View file

@ -1,11 +1,11 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class TranslationsController < ApplicationController class TranslationsController < ApplicationController
before_action :authentication_check, except: [:load] before_action :authentication_check, except: [:lang]
# GET /translations/lang/:locale # GET /translations/lang/:locale
def load def lang
render json: Translation.list( params[:locale] ) render json: Translation.lang(params[:locale])
end end
# PUT /translations/push # PUT /translations/push
@ -36,7 +36,7 @@ class TranslationsController < ApplicationController
# GET /translations/admin/lang/:locale # GET /translations/admin/lang/:locale
def admin def admin
return if deny_if_not_role(Z_ROLENAME_ADMIN) return if deny_if_not_role(Z_ROLENAME_ADMIN)
render json: Translation.list( params[:locale], true ) render json: Translation.lang(params[:locale], true)
end end
# GET /translations # GET /translations

View file

@ -154,50 +154,53 @@ reset translations to origin
get list of translations get list of translations
list = Translation.list('de-de') list = Translation.lang('de-de')
=end =end
def self.list(locale, admin = false) def self.lang(locale, admin = false)
# use cache if not admin page is requested # use cache if not admin page is requested
if !admin if !admin
data = cache_get(locale) data = cache_get(locale)
return data if data
end end
if !data
# show total translations as reference count # show total translations as reference count
data = { data = {
'total' => Translation.where(locale: 'de-de').count, 'total' => Translation.where(locale: 'de-de').count,
} }
list = [] list = []
if admin
translations = Translation.where(locale: locale.downcase).order(:source) translations = Translation.where(locale: locale.downcase).order(:source)
translations.each { |item| else
if admin translations = Translation.where(locale: locale.downcase).where.not(target: '').order(:source)
translation_item = [ end
item.id, translations.each { |item|
item.source, if admin
item.target, translation_item = [
item.target_initial, item.id,
item.format, item.source,
] item.target,
list.push translation_item item.target_initial,
else item.format,
translation_item = [ ]
item.id, list.push translation_item
item.source, else
item.target, translation_item = [
item.format, item.id,
] item.source,
list.push translation_item item.target,
end item.format,
data['list'] = list ]
} list.push translation_item
# set cache
if !admin
cache_set(locale, data)
end end
data['list'] = list
}
# set cache
if !admin
cache_set(locale, data)
end end
data data
@ -214,13 +217,13 @@ translate strings in ruby context, e. g. for notifications
def self.translate(locale, string) def self.translate(locale, string)
# translate string # translate string
records = Translation.where( locale: locale, source: string ) records = Translation.where(locale: locale, source: string)
records.each {|record| records.each {|record|
return record.target if record.source == string return record.target if record.source == string
} }
# fallback lookup in en # fallback lookup in en
records = Translation.where( locale: 'en', source: string ) records = Translation.where(locale: 'en', source: string)
records.each {|record| records.each {|record|
return record.target if record.source == string return record.target if record.source == string
} }
@ -237,14 +240,14 @@ translate strings in ruby context, e. g. for notifications
end end
def cache_clear def cache_clear
Cache.delete( 'TranslationMap::' + locale.downcase ) Cache.delete('TranslationMapOnlyContent::' + locale.downcase)
end end
def self.cache_set(locale, data) def self.cache_set(locale, data)
Cache.write( 'TranslationMap::' + locale.downcase, data ) Cache.write('TranslationMapOnlyContent::' + locale.downcase, data)
end end
def self.cache_get(locale) def self.cache_get(locale)
Cache.get( 'TranslationMap::' + locale.downcase ) Cache.get('TranslationMapOnlyContent::' + locale.downcase)
end end
end end

View file

@ -4,7 +4,7 @@ Zammad::Application.routes.draw do
match api_path + '/translations/push', to: 'translations#push', via: :put match api_path + '/translations/push', to: 'translations#push', via: :put
match api_path + '/translations/sync/:locale', to: 'translations#sync', via: :get match api_path + '/translations/sync/:locale', to: 'translations#sync', via: :get
match api_path + '/translations/reset', to: 'translations#reset', via: :post match api_path + '/translations/reset', to: 'translations#reset', via: :post
match api_path + '/translations/lang/:locale', to: 'translations#load', via: :get match api_path + '/translations/lang/:locale', to: 'translations#lang', via: :get
match api_path + '/translations/admin/lang/:locale', to: 'translations#admin', via: :get match api_path + '/translations/admin/lang/:locale', to: 'translations#admin', via: :get
match api_path + '/translations', to: 'translations#index', via: :get match api_path + '/translations', to: 'translations#index', via: :get