Merge branch 'feature/ui2' into develop

This commit is contained in:
Martin Edenhofer 2013-09-30 02:37:56 +02:00
commit f7835a9af0
220 changed files with 11438 additions and 8530 deletions

View file

@ -145,11 +145,11 @@ class App.Controller extends Spine.Controller
all_attributes = [
{ name: 'number', link: true, title: 'title' },
{ name: 'title', link: true, title: 'title' },
{ name: 'customer', class: 'user-data', data: { id: true } },
{ name: 'customer', class: 'user-popover', data: { id: true } },
{ name: 'ticket_state', translate: true, title: true },
{ name: 'ticket_priority', translate: true, title: true },
{ name: 'group', title: 'group' },
{ name: 'owner', class: 'user-data', data: { id: true } },
{ name: 'owner', class: 'user-popover', data: { id: true } },
{ name: 'created_at', callback: @frontendTime },
{ name: 'last_contact', callback: @frontendTime },
{ name: 'last_contact_agent', callback: @frontendTime },
@ -191,7 +191,7 @@ class App.Controller extends Spine.Controller
if diff > 0
escalated = '-'
if diff >= 0
style = "class=\"label label-important\""
style = "class=\"label label-danger\""
else if diff > -60 * 60
style = "class=\"label label-warning\""
else
@ -244,7 +244,7 @@ class App.Controller extends Spine.Controller
el.unbind()
# start customer info controller
new App.UserInfo(
new App.WidgetUser(
el: el
user_id: data.user_id
callback: data.callback
@ -282,26 +282,26 @@ class App.Controller extends Spine.Controller
ticketPopups: (position = 'right') ->
# remove old popovers
$('.popover-inner').parent().remove()
$('.popover').remove()
# show ticket popup
ui = @
$('.ticket-data').popover(
@el.find('.ticket-popover').popover(
trigger: 'hover'
container: 'body'
html: true
delay: { show: 500, hide: 1200 }
# placement: 'bottom'
placement: position
title: ->
ticket_id = $(@).data('id')
ticket = App.Ticket.retrieve( ticket_id )
ticket.title
App.i18n.escape( ticket.title )
content: ->
ticket_id = $(@).data('id')
ticket = App.Ticket.retrieve( ticket_id )
ticket.humanTime = ui.humanTime(ticket.created_at)
# insert data
App.view('ticket_info_small')(
App.view('popover/ticket')(
ticket: ticket,
)
)
@ -309,19 +309,19 @@ class App.Controller extends Spine.Controller
userPopups: (position = 'right') ->
# remove old popovers
$('.popover-inner').parent().remove()
$('.popover').remove()
# show user popup
$('.user-data').popover(
@el.find('.user-popover').popover(
trigger: 'hover'
container: 'body'
html: true
delay: { show: 500, hide: 1200 }
# placement: 'bottom'
placement: position
title: ->
user_id = $(@).data('id')
user = App.User.find( user_id )
user.displayName()
App.i18n.escape( user.displayName() )
content: ->
user_id = $(@).data('id')
user = App.User.find( user_id )
@ -346,7 +346,7 @@ class App.Controller extends Spine.Controller
data.push item
# insert data
App.view('user_info_small')(
App.view('popover/user')(
user: user,
data: data,
)
@ -355,24 +355,24 @@ class App.Controller extends Spine.Controller
organizationPopups: (position = 'right') ->
# remove old popovers
$('.popover-inner').parent().remove()
$('.popover').remove()
# show organization popup
$('.organization-data').popover(
@el.find('.organization-popover').popover(
trigger: 'hover'
container: 'body'
html: true
delay: { show: 500, hide: 1200 }
# placement: 'bottom'
placement: position
title: ->
organization_id = $(@).data('id')
organization = App.Organization.find( organization_id )
organization.name
App.i18n.escape( organization.name )
content: ->
organization_id = $(@).data('id')
organization = App.Organization.find( organization_id )
# insert data
App.view('organization_info_small')(
App.view('popover/organization')(
organization: organization,
)
)
@ -380,7 +380,7 @@ class App.Controller extends Spine.Controller
userTicketPopups: (data) ->
# remove old popovers
$('.popover-inner').parent().remove()
$('.popover').remove()
# get data
tickets = {}
@ -400,8 +400,9 @@ class App.Controller extends Spine.Controller
# show user popup
controller = @
$(data.selector).popover(
@el.find(data.selector).popover(
trigger: 'hover'
container: 'body'
html: true
delay: { show: 500, hide: 5200 }
placement: data.position
@ -417,7 +418,7 @@ class App.Controller extends Spine.Controller
ticket.humanTime = controller.humanTime(ticket.created_at)
# insert data
App.view('user_ticket_info_small')(
App.view('popover/user_ticket_list')(
tickets: data,
)
)
@ -437,7 +438,7 @@ class App.ControllerContent extends App.Controller
$('#content_permanent').hide()
class App.ControllerModal extends App.Controller
className: 'modal hide fade',
className: 'modal fade',
tag: 'div',
events:
@ -484,11 +485,11 @@ class App.ControllerModal extends App.Controller
data = $.extend({}, defaults, params)
@el.modal(data)
@el.bind('hidden', =>
@el.bind('hidden.bs.modal', =>
# navigate back to home page
if @pageData && @pageData.home
@navigate @pageData.home
# if @pageData && @pageData.home
# @navigate @pageData.home
# navigate back
if params && params.navigateBack

View file

@ -362,10 +362,10 @@ class App.ControllerForm extends App.Controller
params:
form_id: @form_id
text:
uploadButton: '<i class="icon-attachment"></i>'
uploadButton: '<i class="glyphicon glyphicon-paperclip"></i>'
template: '<div class="qq-uploader">' +
'<pre class="btn qq-upload-icon qq-upload-drop-area"><span>{dragZoneText}</span></pre>' +
'<div class="btn qq-upload-icon qq-upload-button pull-right" style="">{uploadButtonText}</div>' +
'<div class="btn btn-default qq-upload-icon2 qq-upload-button pull-right" style="">{uploadButtonText}</div>' +
'<ul class="qq-upload-list span5" style="margin-top: 10px;"></ul>' +
'</div>',
classes:
@ -383,7 +383,8 @@ class App.ControllerForm extends App.Controller
container = document.getElementById( attribute.id + "_tagsinput" )
if reorder
$('#' + attribute.id + "_tagsinput" ).height( 20 )
height = container.scrollHeight
height = container.scrollHeight || 45
console.log('siteUpdate', height)
$('#' + attribute.id + "_tagsinput" ).height( height - 16 )
onAddTag = =>
@ -393,10 +394,9 @@ class App.ControllerForm extends App.Controller
siteUpdate(true)
$('#' + attribute.id + '_tagsinput').remove()
w = $('#' + attribute.id).width()
h = $('#' + attribute.id).height()
$('#' + attribute.id).tagsInput(
width: w + 'px'
width: '100%'
# height: (h + 30 )+ 'px'
onAddTag: onAddTag
onRemoveTag: onRemoveTag
@ -1051,14 +1051,14 @@ class App.ControllerForm extends App.Controller
if !_.isArray(name)
name = [name]
for key in name
el.find('[name="' + key + '"]').parents('.control-group').removeClass('hide')
el.find('[name="' + key + '"]').parents('.form-group').removeClass('hide')
el.find('[name="' + key + '"]').removeClass('is-hidden')
_hide: (name, el = @el) ->
if !_.isArray(name)
name = [name]
for key in name
el.find('[name="' + key + '"]').parents('.control-group').addClass('hide')
el.find('[name="' + key + '"]').parents('.form-group').addClass('hide')
el.find('[name="' + key + '"]').addClass('is-hidden')
# sort attribute.options
@ -1347,18 +1347,18 @@ class App.ControllerForm extends App.Controller
@validate: (data) ->
# remove all errors
$(data.form).parents().find('.error').removeClass('error')
$(data.form).parents().find('.has-error').removeClass('has-error')
$(data.form).parents().find('.help-inline').html('')
# show new errors
for key, msg of data.errors
$(data.form).parents().find('[name*="' + key + '"]').parents('div .control-group').addClass('error')
$(data.form).parents().find('[name*="' + key + '"]').parents('div .form-group').addClass('has-error')
$(data.form).parents().find('[name*="' + key + '"]').parent().find('.help-inline').html(msg)
# set autofocus
$(data.form).parents().find('.error').find('input, textarea').first().focus()
$(data.form).parents().find('.has-error').find('input, textarea').first().focus()
# # enable form again
# if $(data.form).parents().find('.error').html()
# if $(data.form).parents().find('.has-error').html()
# @formEnable(data.form)

View file

@ -199,6 +199,26 @@ class DestroyConfirm extends App.ControllerModal
@modalHide()
@item.destroy()
class App.ControllerDrox extends App.Controller
constructor: (params) ->
super
if params.data && ( params.data.text || params.data.html )
@inline(params.data)
inline: (data) ->
@html App.view('generic/drox')(data)
if data.text
@el.find('.drox-body').text(data.text)
if data.html
@el.find('.drox-body').html(data.html)
template: (data) ->
drox = $( App.view('generic/drox')(data) )
content = App.view(data.file)(data.params)
drox.find('.drox-body').append(content)
drox
class App.ControllerLevel2 extends App.ControllerContent
events:
'click [data-toggle="tabnav"]': 'toggle',
@ -261,3 +281,66 @@ class App.ControllerTabs extends App.Controller
new tab.controller( params )
@el.find('.tab-content .tab-pane:first').addClass('active')
class App.ControllerNavSidbar extends App.ControllerContent
constructor: (params) ->
super
# get groups
groups = App.Config.get(@configKey)
groupsUnsorted = []
for key, value of groups
if !value.controller
groupsUnsorted.push value
@groupsSorted = _.sortBy( groupsUnsorted, (item) -> return item.prio )
# get items of group
for group in @groupsSorted
items = App.Config.get(@configKey)
itemsUnsorted = []
for key, value of items
if value.controller
if value.parent is group.target
itemsUnsorted.push value
group.items = _.sortBy( itemsUnsorted, (item) -> return item.prio )
# set active item
selectedItem = undefined
for group in @groupsSorted
if group.items
for item in group.items
if !@target && !selectedItem
item.active = true
selectedItem = item
else if @target && item.target is window.location.hash
item.active = true
selectedItem = item
else
item.active = false
@render(selectedItem)
if selectedItem
new selectedItem.controller(
el: @el.find('.main')
)
@bind(
'ui:rerender'
=>
@render(selectedItem, true)
)
render: (selectedItem, force) ->
if !$( '.' + @configKey )[0] || force
@html App.view('generic/navbar_l2')(
groups: @groupsSorted
className: @configKey
)
if selectedItem
@el.find('li').removeClass('active')
@el.find('a[href="' + selectedItem.target + '"]').parent().addClass('active')

View file

@ -22,11 +22,11 @@ class App.ControllerTable extends App.Controller
overview_extended: [
{ name: 'number', link: true },
{ name: 'title', link: true },
{ name: 'customer', class: 'user-data', data: { id: true } },
{ name: 'customer', class: 'user-popover', data: { id: true } },
{ name: 'ticket_state', translate: true },
{ name: 'ticket_priority', translate: true },
{ name: 'group' },
{ name: 'owner', class: 'user-data', data: { id: true } },
{ name: 'owner', class: 'user-popover', data: { id: true } },
{ name: 'created_at', callback: @frontendTime },
{ name: 'last_contact', callback: @frontendTime },
{ name: 'last_contact_agent', callback: @frontendTime },
@ -127,10 +127,10 @@ class App.ControllerTable extends App.Controller
# enable checkbox bulk selection
if data.checkbox
table.delegate('[name="bulk_all"]', 'click', (e) ->
if $(e.target).attr('checked')
$(e.target).parents().find('[name="bulk"]').attr( 'checked', true );
if $(e.target).prop('checked')
$(e.target).parents().find('[name="bulk"]').prop( 'checked', true );
else
$(e.target).parents().find('[name="bulk"]').attr( 'checked', false );
$(e.target).parents().find('[name="bulk"]').prop( 'checked', false );
)
return table

View file

@ -1,7 +1,4 @@
class App.ChannelFacebook extends App.Controller
events:
'click [data-toggle="tabnav"]': 'toggle',
constructor: ->
super

View file

@ -1,7 +1,4 @@
class App.ChannelTwitter extends App.Controller
events:
'click [data-toggle="tabnav"]': 'toggle',
constructor: ->
super
@ -9,8 +6,6 @@ class App.ChannelTwitter extends App.Controller
@render()
render: ->
@html App.view('channel/twitter')(
head: 'some header'
)

View file

@ -21,7 +21,7 @@ class App.DashboardActivityStream extends App.Controller
type: 'GET'
url: @apiPath + '/activity_stream'
data: {
limit: 8
limit: @limit || 8
}
processData: true
success: (data) =>
@ -40,21 +40,23 @@ class App.DashboardActivityStream extends App.Controller
render: (items) ->
for item in items
if item.history_object is 'Ticket'
ticket = App.Ticket.find( item.o_id )
item.link = '#ticket/zoom/' + ticket.id
item.title = ticket.title
item.type = 'Ticket'
item.updated_by_id = ticket.updated_by_id
item.updated_by = App.User.find( ticket.updated_by_id )
else if item.history_object is 'Ticket::Article'
item.link = ''
item.title = '???'
if item.object is 'Ticket::Article'
item.object = 'Article'
article = App.TicketArticle.find( item.o_id )
ticket = App.Ticket.find( article.ticket_id )
item.link = '#ticket/zoom/' + ticket.id + '/' + article.id
item.title = article.subject || ticket.title
item.type = 'Article'
item.updated_by_id = article.updated_by_id
item.updated_by = App.User.find( article.updated_by_id )
item.link = article.uiUrl()
if App[item.object]
object = App[item.object].find( item.o_id )
item.link = object.uiUrl()
item.title = object.displayName()
item.created_by = App.User.find( item.created_by_id )
html = App.view('dashboard/activity_stream')(
head: 'Activity Stream',
@ -65,5 +67,7 @@ class App.DashboardActivityStream extends App.Controller
@html html
# start user popups
@userPopups('left')
@userPopups('right')
# update time
@frontendTimeUpdate()

View file

@ -9,6 +9,5 @@ App.Config.set( 'User', {
role: [ 'Agent', 'Customer' ]
}, 'NavBarRight' )
App.Config.set( 'Admin', { prio: 10000, parent: '', name: 'Manage', target: '#admin', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Setting', { prio: 20000, parent: '', name: 'Settings', target: '#settings', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Admin', { prio: 10000, parent: '', name: 'Admin', target: '#manage', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Misc', { prio: 90000, parent: '', name: 'Tools', target: '#tools', child: true }, 'NavBar' )

View file

@ -1,4 +1,4 @@
class App.ProfileLanguage extends App.Controller
class Index extends App.Controller
events:
'submit form': 'update'
@ -66,3 +66,6 @@ class App.ProfileLanguage extends App.Controller
type: 'error'
msg: App.i18n.translateContent( data.message )
)
App.Config.set( 'Language', { prio: 1000, name: 'Language', parent: '#profile', target: '#profile/language', controller: Index }, 'NavBarProfile' )

View file

@ -1,4 +1,4 @@
class App.ProfileLinkedAccounts extends App.Controller
class Index extends App.Controller
events:
'click [data-type="remove"]': 'remove'
@ -75,3 +75,6 @@ class App.ProfileLinkedAccounts extends App.Controller
type: 'error'
msg: App.i18n.translateContent( data.message )
)
App.Config.set( 'LinkedAccounts', { prio: 3000, name: 'Linked Accunts', parent: '#profile', target: '#profile/linked', controller: Index }, 'NavBarProfile' )

View file

@ -1,4 +1,4 @@
class App.ProfilePassword extends App.Controller
class Index extends App.Controller
events:
'submit form': 'update'
@ -59,3 +59,6 @@ class App.ProfilePassword extends App.Controller
type: 'error'
msg: App.i18n.translateContent( data.message )
)
App.Config.set( 'Password', { prio: 2000, name: 'Password', parent: '#profile', target: '#profile/password', controller: Index }, 'NavBarProfile' )

View file

@ -48,7 +48,7 @@ class App.SettingsAreaItem extends App.Controller
)
new App.ControllerForm(
el: @el.find('#form-item'),
el: @el.find('.form-item'),
model: { configure_attributes: @configure_attributes, className: '' },
autofocus: false,
)
@ -73,6 +73,7 @@ class App.SettingsAreaItem extends App.Controller
}
@setting['state'] = state
ui = @
@setting.save(
success: =>
@ -81,7 +82,7 @@ class App.SettingsAreaItem extends App.Controller
msg: App.i18n.translateContent('Update successful!')
timeout: 1500
}
ui.render()
# login check
App.Auth.loginCheck()
# App.Auth.loginCheck()
)

View file

@ -191,15 +191,15 @@ class App.TicketCreate extends App.Controller
@el.find('textarea').trigger('change')
# show template UI
new App.TemplateUI(
el: @el.find('[data-id="ticket_template"]')
new App.WidgetTemplate(
el: @el.find('.ticket_template')
template_id: template['id']
)
@formDefault = @formParam( @el.find('.ticket-create') )
# show text module UI
@textModule = new App.TextModuleUI(
@textModule = new App.WidgetTextModule(
el: @el.find('.ticket-create').find('textarea')
)
@ -217,7 +217,7 @@ class App.TicketCreate extends App.Controller
@userInfo(
user_id: params.customer_id
el: @el.find('[data-id="customer_info"]')
el: @el.find('.customer_info')
callback: callback
)

View file

@ -9,6 +9,7 @@ class App.TicketHistory extends App.ControllerModal
@fetch(@ticket_id)
fetch: (@ticket_id) ->
# get data
@ajax(
id: 'ticket_history',
@ -19,18 +20,40 @@ class App.TicketHistory extends App.ControllerModal
# load collections
App.Event.trigger 'loadAssets', data.assets
# load history collections
App.History.deleteAll()
App.Collection.load( type: 'History', data: data.history )
# render page
@render()
@render(data.history)
)
render: ->
render: ( items, orderClass = '' ) ->
for item in items
item.link = ''
item.title = '???'
if item.object is 'Ticket::Article'
item.object = 'Article'
article = App.TicketArticle.find( item.o_id )
ticket = App.Ticket.find( article.ticket_id )
item.title = article.subject || ticket.title
item.link = article.uiUrl()
if App[item.object]
object = App[item.object].find( item.o_id )
item.link = object.uiUrl()
item.title = object.displayName()
item.created_by = App.User.find( item.created_by_id )
# set cache
@historyListCache = items
@html App.view('agent_ticket_history')(
objects: App.History.search()
items: items
orderClass: orderClass
@historyListCache
)
@modalShow()
@ -43,25 +66,9 @@ class App.TicketHistory extends App.ControllerModal
sortorder: (e) ->
e.preventDefault()
isSorted = @el.find('.sorted')
isDown = @el.find('[data-type="sortorder"]').hasClass('down')
if isSorted.length
@sortstate = 'notsorted'
@html App.view('agent_ticket_history')(
objects: App.History.search()
state: @sortstate
)
if isDown
@render( @historyListCache, 'up' )
else
@sortstate = 'sorted'
@html App.view('agent_ticket_history')(
objects: App.History.search().reverse()
state: @sortstate
)
@modalShow()
# enable user popups
@userPopups()
# show frontend times
@delay( @frontendTimeUpdate, 200, 'ui-time-update' )
@render( @historyListCache.reverse(), 'down' )

View file

@ -39,11 +39,11 @@ class App.TicketMerge extends App.ControllerModal
overview_extended: [
{ name: 'number', link: true },
{ name: 'title', link: true },
# { name: 'customer', class: 'user-data', data: { id: true } },
# { name: 'customer', class: 'user-popover', data: { id: true } },
{ name: 'ticket_state', translate: true },
# { name: 'ticket_priority', translate: true },
{ name: 'group' },
# { name: 'owner', class: 'user-data', data: { id: true } },
# { name: 'owner', class: 'user-popover', data: { id: true } },
{ name: 'created_at', callback: @humanTime },
# { name: 'last_contact', callback: @frontendTime },
# { name: 'last_contact_agent', callback: @frontendTime },
@ -66,11 +66,11 @@ class App.TicketMerge extends App.ControllerModal
overview_extended: [
{ name: 'number', link: true },
{ name: 'title', link: true },
# { name: 'customer', class: 'user-data', data: { id: true } },
# { name: 'customer', class: 'user-popover', data: { id: true } },
{ name: 'ticket_state', translate: true },
# { name: 'ticket_priority', translate: true },
{ name: 'group' },
# { name: 'owner', class: 'user-data', data: { id: true } },
# { name: 'owner', class: 'user-popover', data: { id: true } },
{ name: 'created_at', callback: @humanTime },
# { name: 'last_contact', callback: @frontendTime },
# { name: 'last_contact_agent', callback: @frontendTime },

View file

@ -1,30 +1,13 @@
class Index extends App.ControllerLevel2
# toggleable: true
toggleable: false
#App.Config.set( 'channels/:target', Index, 'Routes' )
#App.Config.set( 'channels', Index, 'Routes' )
menu: [
{ name: 'Web', target: 'web', controller: App.ChannelWeb },
{ name: 'Mail', target: 'email', controller: App.ChannelEmail },
{ name: 'Chat', target: 'chat', controller: App.ChannelChat },
{ name: 'Twitter', target: 'twitter', controller: App.ChannelTwitter },
{ name: 'Facebook', target: 'facebook', controller: App.ChannelFacebook },
]
page: {
title: 'Channels',
head: 'Channels',
sub_title: 'Management'
nav: '#channels',
}
#App.Config.set( 'Channels', { prio: 2500, name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBarLevel4' )
constructor: ->
super
#App.Config.set( 'Channels', { prio: 2500, parent: '#admin', name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBar' )
return if !@authenticate()
App.Config.set( 'Web', { prio: 1000, name: 'Web', parent: '#channels', target: '#channels/web', controller: App.ChannelWeb, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'Email', { prio: 2000, name: 'Email', parent: '#channels', target: '#channels/email', controller: App.ChannelEmail, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'Chat', { prio: 3000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'Twitter', { prio: 4000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: App.ChannelTwitter, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'Facebook', { prio: 5000, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: App.ChannelFacebook, role: ['Admin'] }, 'NavBarAdmin' )
# render page
@render()
App.Config.set( 'channels/:target', Index, 'Routes' )
App.Config.set( 'channels', Index, 'Routes' )
App.Config.set( 'Channels', { prio: 2500, parent: '#admin', name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBar' )

View file

@ -114,6 +114,13 @@ class Index extends App.ControllerContent
# update textarea size
@el.find('textarea').trigger('change')
new App.ControllerDrox(
el: @el.find('.sidebar')
data:
header: App.i18n.translateInline('What can you do here?')
html: App.i18n.translateInline('The way to communicate with us is this thing called "Ticket".') + ' ' + App.i18n.translateInline('Here you can create one.')
)
cancel: ->
@navigate '#'

View file

@ -33,17 +33,17 @@ class Index extends App.ControllerContent
activity_stream: {
controller: App.DashboardActivityStream,
params: {
limit: 8,
},
},
rss_atom: {
controller: App.DashboardRss,
params: {
head: 'Heise ATOM',
url: 'http://www.heise.de/newsticker/heise-atom.xml',
limit: 5,
limit: 20,
},
},
# rss_atom: {
# controller: App.DashboardRss,
# params: {
# head: 'Heise ATOM',
# url: 'http://www.heise.de/newsticker/heise-atom.xml',
# limit: 5,
# },
# },
# rss_rdf: {
# controller: App.DashboardRss,
# params: {
@ -52,10 +52,9 @@ class Index extends App.ControllerContent
# limit: 5,
# },
# },
recent_viewed: {
controller: App.DashboardRecentViewed,
}
# recent_viewed: {
# controller: App.DashboardRecentViewed,
# }
}
}

View file

@ -1,6 +1,4 @@
class App.Footer extends App.Controller
className: 'container'
constructor: ->
super
@render()
@ -12,4 +10,4 @@ class App.Footer extends App.Controller
render: () ->
@html App.view('footer')()
App.Config.set( 'footer', App.Footer, 'Footers' )
#App.Config.set( 'footer', App.Footer, 'Footers' )

View file

@ -142,8 +142,10 @@ class Index extends App.ControllerContent
# type: 'success',
# msg: 'Thanks for joining. Email sent to "' + @params.email + '". Please verify your email address.'
@el.find('.master_user').fadeOut('slow', =>
@el.find('.agent_user').fadeIn()
)
@el.find('.master_user').addClass('hide')
@el.find('.agent_user').removeClass('hide')
# @el.find('.master_user').fadeOut('slow', =>
# @el.find('.agent_user').fadeIn()
# )
App.Config.set( 'getting_started', Index, 'Routes' )

View file

@ -24,6 +24,4 @@ class Index extends App.ControllerContent
},
)
App.Config.set( 'groups', Index, 'Routes' )
App.Config.set( 'Group', { prio: 1500, parent: '#admin', name: 'Groups', target: '#groups', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Group', { prio: 1500, name: 'Groups', parent: '#manage', target: '#manage/groups', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -1,4 +1,4 @@
class App.Maintenance extends App.ControllerContent
class Index extends App.ControllerContent
events:
'submit form': 'sendMessage'
@ -23,5 +23,4 @@ class App.Maintenance extends App.ControllerContent
)
@render()
App.Config.set( 'maintenance', App.Maintenance, 'Routes' )
App.Config.set( 'maintenance', { prio: 3600, parent: '#admin', name: 'Maintenance Message', target: '#maintenance', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Maintenance', { prio: 3600, name: 'Maintenance', parent: '#system', target: '#system/maintenance', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -0,0 +1,16 @@
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', { 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( 'SystemObject', { prio: 1700, parent: '#system', name: 'Objects', target: '#system/objects', controller: true, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -35,6 +35,13 @@ class App.Navigation extends App.Controller
@recent_viewed_build(data)
@render()
# bell on / bell off
@bind 'bell', (data) =>
if data is 'on'
@el.find('.bell').addClass('show')
else
@el.find('.bell').removeClass('show')
render: () ->
user = App.Session.all()
nav_left = @getItems( navbar: @Config.get( 'NavBar' ) )
@ -66,13 +73,13 @@ class App.Navigation extends App.Controller
)
# start ticket popups
@ticketPopups('right')
@ticketPopups('left')
# start user popups
@userPopups('right')
@userPopups('left')
# start oorganization popups
@organizationPopups('right')
@organizationPopups('left')
# set focus to search box
if @searchFocus
@ -105,8 +112,8 @@ class App.Navigation extends App.Controller
data =
display: "##{ticket.number} - #{ticket.title} - #{ticket.humanTime}"
id: ticket.id
class: "ticket-data"
url: "#ticket/zoom/#{ticket.id}"
class: "ticket-popover"
url: ticket.uiUrl()
area.result.push data
else if area.name is 'User'
area.result = []
@ -115,8 +122,8 @@ class App.Navigation extends App.Controller
data =
display: "#{user.displayName()}"
id: user.id
class: "user-data"
url: "#users/#{user.id}"
class: "user-popover"
url: user.uiUrl()
area.result.push data
else if area.name is 'Organization'
area.result = []
@ -125,8 +132,8 @@ class App.Navigation extends App.Controller
data =
display: "#{organization.displayName()}"
id: organization.id
class: "organization-data"
url: "#organizations/#{ticket.id}"
class: "organization-popover"
url: organization.uiUrl()
area.result.push data
if @result
@ -263,8 +270,8 @@ class App.Navigation extends App.Controller
@el.find("[href=\"#{url}\"]").parents('li').addClass('active')
ticket_overview_build: (data) =>
App.Store.write( 'navupdate_ticket_overview', data )
return
# remove old views
NavBar = @Config.get( 'NavBar' ) || {}
@ -313,11 +320,11 @@ class App.Navigation extends App.Controller
ticket = App.Ticket.find( item.o_id )
prio++
NavBarRight['RecendViewed::' + ticket.id + '-' + prio ] = {
prio: prio,
parent: '#current_user',
name: item.recent_view_object + ' (' + ticket.title + ')',
target: '#ticket/zoom/' + ticket.id,
divider: divider,
prio: prio
parent: '#current_user'
name: item.recent_view_object + ' (' + ticket.title + ')'
target: ticket.uiUrl()
divider: divider
navheader: navheader
}

View file

@ -24,7 +24,4 @@ class Index extends App.ControllerContent
},
)
App.Config.set( 'organizations', Index, 'Routes' )
App.Config.set( 'Organization', { prio: 2000, parent: '#admin', name: 'Organizations', target: '#organizations', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Organization', { prio: 2000, name: 'Organizations', parent: '#manage', target: '#manage/organizations', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -24,6 +24,4 @@ class Index extends App.ControllerContent
},
)
App.Config.set( 'overviews', Index, 'Routes' )
App.Config.set( 'Overview', { prio: 2300, parent: '#admin', name: 'Overviews', target: '#overviews', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Overview', { prio: 2300, name: 'Overviews', parent: '#manage', target: '#manage/overviews', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -57,5 +57,4 @@ class Index extends App.ControllerContent
@load()
)
App.Config.set( 'package', Index, 'Routes' )
App.Config.set( 'Packages', { prio: 1800, parent: '#settings', name: 'Packages', target: '#package', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Packages', { prio: 1000, name: 'Packages', parent: '#system', target: '#system/package', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -1,32 +1,9 @@
class Index extends App.ControllerLevel2
toggleable: false
# toggleable: true
class Index extends App.ControllerNavSidbar
configKey: 'NavBarProfile'
constructor: ->
super
return if !@authenticate()
@menu = [
{ name: 'Password', 'target': 'password', controller: App.ProfilePassword, params: {} },
{ name: 'Language', 'target': 'language', controller: App.ProfileLanguage, params: {} },
{ name: 'Link Accounts', 'target': 'accounts', controller: App.ProfileLinkedAccounts, params: {} },
# { name: 'Notifications', 'target': 'notify', controller: App.SettingsArea, params: { area: 'Ticket::Number' } },
]
@page = {
title: 'Profile',
head: 'Profile',
sub_title: 'Settings'
nav: '#profile',
}
# render page
@render()
# render: ->
# @html App.view('profile')()
App.Config.set( 'profile/:target', Index, 'Routes' )
App.Config.set( 'profile', Index, 'Routes' )
App.Config.set( 'profile/:target', Index, 'Routes' )
App.Config.set( 'Profile', { prio: 1000, name: 'Profile', target: '#profile' }, 'NavBarProfile' )
App.Config.set( 'Profile', { prio: 1700, parent: '#current_user', name: 'Profile', target: '#profile', role: [ 'Agent', 'Customer' ] }, 'NavBarRight' )

View file

@ -25,7 +25,7 @@ class Index extends App.ControllerContent
{ name: 'username', display: 'Enter your username or email address', tag: 'input', type: 'text', limit: 100, null: false, class: 'input span4', },
]
@html App.view('reset_password')(params)
@html App.view('password/reset')(params)
@form = new App.ControllerForm(
el: @el.find('#form-password-item')
@ -98,7 +98,7 @@ class Verify extends App.ControllerContent
{ name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 100, null: false, class: 'input span4', },
]
@html App.view('reset_password_change')()
@html App.view('password/reset_change')()
new App.ControllerForm(
el: @el.find('#form-password-change')

View file

@ -18,6 +18,4 @@ class Index extends App.ControllerContent
head: 'some header'
)
App.Config.set( 'scheduler', Index, 'Routes' )
App.Config.set( 'Scheduler', { prio: 3500, parent: '#admin', name: 'Scheduler', target: '#scheduler', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Scheduler', { prio: 2000, name: 'Schedulers', parent: '#manage', target: '#manage/schedulers', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -1,4 +1,5 @@
class Session extends App.ControllerContent
class Index extends App.ControllerContent
divClass: 'lala'
events:
'click [data-type="delete"]': 'destroy'
@ -11,7 +12,7 @@ class Session extends App.ControllerContent
@interval(
=>
@load()
30000
45000
)
# fetch data, render view
@ -50,6 +51,4 @@ class Session extends App.ControllerContent
@load()
)
App.Config.set( 'session', Session, 'Routes' )
App.Config.set( 'session', { prio: 3700, parent: '#admin', name: 'Sessions', target: '#session', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Session', { prio: 3700, name: 'Sessions', parent: '#system', target: '#system/sessions', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -1,78 +1,67 @@
class Index extends App.ControllerLevel2
toggleable: false
# toggleable: true
class System extends App.ControllerTabs
constructor: ->
super
return if !@authenticate()
# system
if @type is 'system'
@menu = [
@tabs = [
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'System::Base' } },
# { name: 'Language', 'target': 'language', controller: App.SettingsSystem, params: { area: 'System::Language' } },
# { name: 'Log', 'target': 'log', controller: App.SettingsSystem, params: { area: 'System::Log' } },
{ name: 'Storage', 'target': 'storage', controller: App.SettingsArea, params: { area: 'System::Storage' } },
{ name: 'Geo Services', 'target': 'geo', controller: App.SettingsArea, params: { area: 'System::Geo' } },
]
@page = {
title: 'System',
head: 'System',
sub_title: 'Settings'
nav: '#settings/system',
}
# security
if @type is 'security'
@menu = [
# render page
@render()
class Security extends App.ControllerTabs
constructor: ->
super
return if !@authenticate()
@tabs = [
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Security::Base' } },
# { name: 'Authentication', 'target': 'auth', controller: App.SettingsArea, params: { area: 'Security::Authentication' } },
{ name: 'Password', 'target': 'password', controller: App.SettingsArea, params: { area: 'Security::Password' } },
{ name: 'Third-Party Applications', 'target': 'third_party_auth', controller: App.SettingsArea, params: { area: 'Security::ThirdPartyAuthentication' } },
# { name: 'Session', 'target': 'session', controller: '' },
]
@page = {
title: 'Security',
head: 'Security',
sub_title: 'Settings'
nav: '#settings/security',
}
@render()
class Import extends App.ControllerTabs
constructor: ->
super
return if !@authenticate()
# import
if @type is 'import'
@menu = [
@tabs = [
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Import::Base' } },
{ name: 'OTRS', 'target': 'otrs', controller: App.SettingsArea, params: { area: 'Import::OTRS' } },
]
@page = {
title: 'Import',
head: 'Import',
sub_title: 'System'
nav: '#settings/import',
}
@render()
class Ticket extends App.ControllerTabs
constructor: ->
super
return if !@authenticate()
# ticket
if @type is 'ticket'
@menu = [
@tabs = [
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } },
{ name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } },
# { name: 'Sender Format', 'target': 'sender-format', controller: App.SettingsArea, params: { area: 'Ticket::SenderFormat' } },
]
@page = {
title: 'Ticket',
head: 'Ticket',
sub_title: 'Settings'
nav: '#settings/ticket',
}
# render page
@render()
App.Config.set( 'settings/:type/:target', Index, 'Routes' )
App.Config.set( 'settings/:type', Index, 'Routes' )
App.Config.set( 'SettingSystem', { prio: 1400, parent: '#settings', name: 'System', target: '#settings/system', controller: System, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'SettingSecurity', { prio: 1500, parent: '#settings', name: 'Security', target: '#settings/security', controller: Security, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'SettingImport', { prio: 1550, parent: '#settings', name: 'Import', target: '#settings/import', controller: Import, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'SettingTicket', { prio: 1600, parent: '#settings', name: 'Ticket', target: '#settings/ticket', controller: Ticket, role: ['Admin'] }, 'NavBarAdmin' )
App.Config.set( 'System', { prio: 1400, parent: '#settings', name: 'System', target: '#settings/system', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Security', { prio: 1500, parent: '#settings', name: 'Security', target: '#settings/security', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Import', { prio: 1550, parent: '#settings', name: 'Import', target: '#settings/import', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Ticket', { prio: 1600, parent: '#settings', name: 'Ticket', target: '#settings/ticket', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Object', { prio: 1700, parent: '#settings', name: 'Objects', target: '#settings/objects', role: ['Admin'] }, 'NavBar' )

View file

@ -24,6 +24,4 @@ class Index extends App.ControllerContent
},
)
App.Config.set( 'slas', Index, 'Routes' )
App.Config.set( 'Sla', { prio: 2900, parent: '#admin', name: 'SLAs', target: '#slas', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -215,19 +215,18 @@ class Taskbar extends App.Controller
@navigate '#'
resizeTasks: ->
width = $('#task .taskbar').width() - $('#task .taskbar-new').width() - 200
width = $('#task .taskbar-items').width()# - $('#task .taskbar-new').width() - 200
task_count = App.TaskManager.all().length
task_size = ( width / task_count ) - ( task_count * 1.3 )
task_size = ( width / task_count ) - 40
elementsOversize = 0
elementsOversizeLeftTotal = 0
$('#task .task').each(
(position, element) ->
width = $(element).parent().width()
if width > task_size
widthTask = $(element).width()
if widthTask > task_size
elementsOversize++
else
elementsOversizeLeftTotal += task_size - width
elementsOversizeLeftTotal += task_size - widthTask
)
addOversize = elementsOversizeLeftTotal / elementsOversize

View file

@ -24,6 +24,4 @@ class Index extends App.ControllerContent
},
)
App.Config.set( 'text_modules', Index, 'Routes' )
App.Config.set( 'TextModule', { prio: 2300, parent: '#admin', name: 'Text Modules', target: '#text_modules', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'TextModule', { prio: 2300, name: 'TextModules', parent: '#manage', target: '#manage/text_modules', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -37,7 +37,7 @@ class App.TicketCustomer extends App.ControllerModal
@modalHide()
# reload zoom view
@zoom.render()
@ui.render()
# load user if not already exists
App.User.retrieve( params['customer_id'], callback )

View file

@ -1,4 +1,29 @@
class Index extends App.ControllerContent
class Index extends App.Controller
constructor: ->
super
@render()
render: ->
@html App.view('agent_ticket_view')()
if !@view
cache = App.Store.get( 'navupdate_ticket_overview' )
if cache && cache[0]
@view = cache[0].link
new Navbar(
el: @el.find('.sidebar')
view: @view
)
new Table(
el: @el.find('.main')
view: @view
)
class Table extends App.ControllerContent
events:
'click [data-type=edit]': 'zoom'
'click [data-type=settings]': 'settings'
@ -128,7 +153,7 @@ class Index extends App.ControllerContent
]
if @isRole('Customer')
view_modes = []
html = App.view('agent_ticket_view')(
html = App.view('agent_ticket_view/content')(
overview: @overview
view_modes: view_modes
checkbox: checkbox
@ -137,6 +162,7 @@ class Index extends App.ControllerContent
html = $(html)
# html.find('li').removeClass('active')
# html.find("[data-id=\"#{@start_page}\"]").parents('li').addClass('active')
@html html
# create table/overview
@ -483,6 +509,50 @@ class Settings extends App.ControllerModal
)
@modalHide()
class Navbar extends App.Controller
constructor: ->
super
# rebuild ticket overview data
@bind 'navupdate_ticket_overview', (data) =>
if !_.isEmpty(data)
App.Store.write( 'navupdate_ticket_overview', data )
@render(data)
cache = App.Store.get( 'navupdate_ticket_overview' )
if cache
@render( cache )
else
@render( [] )
# init fetch via ajax, all other updates on time via websockets
@ajax(
id: 'ticket_overviews',
type: 'GET',
url: @apiPath + '/ticket_overviews',
processData: true,
success: (data) =>
App.Store.write( 'navupdate_ticket_overview', data )
@render(data)
)
render: (dataOrig) ->
data = _.clone(dataOrig)
# add new views
for item in data
item.target = '#ticket_view/' + item.link
if item.link is @view
item.active = true
else
item.active = false
@html App.view('agent_ticket_view/navbar')(
items: data
)
class Router extends App.Controller
constructor: ->
super
@ -535,8 +605,9 @@ class Router extends App.Controller
else
@navigate 'ticket/zoom/' + @ticket_ids[ @position - 1 ] + '/nav/true'
App.Config.set( 'ticket_view', Index, 'Routes' )
App.Config.set( 'ticket_view/:view', Index, 'Routes' )
App.Config.set( 'ticket_view/:view/:position/:direction', Router, 'Routes' )
#App.Config.set( 'ticket_view/:view/:position/:direction', Router, 'Routes' )
App.Config.set( 'TicketOverview', { prio: 1000, parent: '', name: 'Overviews', target: '#ticket_view', role: ['Agent', 'Customer'] }, 'NavBar' )
#App.Config.set( '', { prio: 1000, parent: '#ticket_view', name: 'My assigned Tickets (51)', target: '#ticket_view/my_assigned', role: ['Agent'] }

View file

@ -72,7 +72,7 @@ class App.TicketZoom extends App.Controller
success: (data, status, xhr) =>
# check if ticket has changed
newTicketRaw = data.assets.tickets[ticket_id]
newTicketRaw = data.assets.Ticket[ticket_id]
if @ticketUpdatedAtLastCall && !force
# return if ticket hasnt changed
@ -140,7 +140,7 @@ class App.TicketZoom extends App.Controller
@frontendTimeUpdate()
@TicketTitle()
@TicketInfo()
@TicketWidgets()
@TicketAction()
@ArticleView()
@ -156,7 +156,7 @@ class App.TicketZoom extends App.Controller
# show text module UI
if !@isRole('Customer')
new App.TextModuleUI(
new App.WidgetTextModule(
el: @el.find('textarea')
data:
ticket: @ticket
@ -177,13 +177,6 @@ class App.TicketZoom extends App.Controller
el: @el.find('.ticket-title')
)
TicketInfo: =>
# show ticket info
new TicketInfo(
ticket: @ticket
el: @el.find('.ticket-info')
)
ArticleView: =>
# show article
new ArticleView(
@ -203,12 +196,21 @@ class App.TicketZoom extends App.Controller
ui: @
)
TicketAction: =>
TicketWidgets: =>
# show ticket action row
new TicketAction(
new TicketWidgets(
ticket: @ticket
task_key: @task_key
el: @el.find('.ticket-widgets')
ui: @
)
TicketAction: =>
# start action controller
if !@isRole('Customer')
new TicketActionRow(
el: @el.find('.ticket-action')
ticket: @ticket
ui: @
)
@ -221,7 +223,7 @@ class TicketTitle extends App.Controller
@render()
render: ->
@html App.view('ticket_zoom/ticket_title')(
@html App.view('ticket_zoom/title')(
ticket: @ticket
)
@ -248,59 +250,58 @@ class TicketTitle extends App.Controller
App.Event.trigger 'task:render'
class TicketInfo extends App.Controller
class TicketInfo extends App.ControllerDrox
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/ticket_info')(
@html @template(
file: 'ticket_zoom/info'
header: '#' + @ticket.number
params:
ticket: @ticket
)
class TicketAction extends App.Controller
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/ticket_action')()
# start customer info controller
if !@isRole('Customer')
new App.UserInfo(
el: @el.find('.customer_info')
user_id: @ticket.customer_id
ticket: @ticket
)
# start action controller
if !@isRole('Customer')
new TicketActionRow(
el: @el.find('.action_info')
ticket: @ticket
zoom: @ui
)
# start tag controller
if !@isRole('Customer')
new App.TagWidget(
new App.WidgetTag(
el: @el.find('.tag_info')
object_type: 'Ticket'
object: @ticket
)
class TicketWidgets extends App.Controller
constructor: ->
super
@render()
render: ->
@html App.view('ticket_zoom/widgets')()
# show ticket info
new TicketInfo(
ticket: @ticket
el: @el.find('.ticket_info')
)
# start customer info controller
if !@isRole('Customer')
new App.WidgetUser(
el: @el.find('.customer_info')
user_id: @ticket.customer_id
ticket: @ticket
)
# start link info controller
if !@isRole('Customer')
new App.LinkInfo(
new App.WidgetLink(
el: @el.find('.link_info')
object_type: 'Ticket'
object: @ticket
)
class Edit extends App.Controller
events:
'click .submit': 'update'
@ -337,12 +338,12 @@ class Edit extends App.Controller
@configure_attributes_article = [
{ name: 'ticket_article_type_id', display: 'Type', tag: 'select', multiple: false, null: true, relation: 'TicketArticleType', filter: @edit_form, default: '9', translate: true, class: 'medium' },
{ name: 'internal', display: 'Visibility', tag: 'select', null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: '', default: false },
{ name: 'to', display: 'To', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
# { name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', hide: true },
{ name: 'in_reply_to', display: 'In Reply to', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true },
{ name: 'internal', display: 'Visibility', tag: 'select', null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: '', default: false },
]
if @isRole('Customer')
@configure_attributes_article = [
@ -423,8 +424,9 @@ class Edit extends App.Controller
if !@autosaveLast || ( diff && !_.isEmpty( diff ) )
@autosaveLast = currentData
@log 'notice', 'form hash changed', diff, currentData
@el.find('.ticket-update').parent().addClass('form-changed')
@el.find('.ticket-update').parent().parent().find('.reset-message').show()
@el.find('.ticket-edit').addClass('form-changed')
@el.find('.ticket-edit').find('.reset-message').show()
@el.find('.ticket-edit').find('.reset-message').removeClass('hide')
App.TaskManager.update( @task_key, { 'state': currentData })
@interval( update, 3000, 'autosave' )
@ -604,11 +606,14 @@ class ArticleView extends App.Controller
show_toogle: (e) ->
e.preventDefault()
$(e.target).hide()
#$(e.target).hide()
if $(e.target).next('div')[0]
$(e.target).next('div').show()
if $(e.target).next('div').hasClass('hide')
$(e.target).next('div').removeClass('hide')
$(e.target).text( App.i18n.translateContent('Fold in') )
else
$(e.target).parent().next('div').show()
$(e.target).text( App.i18n.translateContent('See more') )
$(e.target).next('div').addClass('hide')
checkIfSignatureIsNeeded: (article_type) =>
@ -703,9 +708,9 @@ class Article extends App.Controller
if article_lines.length > preview
preview_mode = true
if article_lines[preview] is ''
article_lines.splice( preview, 0, '----SEEMORE----' )
article_lines.splice( preview, 0, '-----SEEMORE-----' )
else
article_lines.splice( preview + 1, 0, '----SEEMORE----' )
article_lines.splice( preview - 1, 0, '-----SEEMORE-----' )
@article['html'] = article_lines.join("\n")
@article['html'] = window.linkify( @article['html'] )
notify = '<a href="#" class="show_toogle">' + App.i18n.translateContent('See more') + '</a>'
@ -713,9 +718,9 @@ class Article extends App.Controller
# preview mode
if preview_mode
@article_changed = false
@article['html'] = @article['html'].replace /^\n{0,10}----SEEMORE----\n/m, (match) =>
@article['html'] = @article['html'].replace /^-----SEEMORE-----\n/m, (match) =>
@article_changed = true
notify + '<div class="hide">'
notify + '<div class="hide preview">'
if @article_changed
@article['html'] = @article['html'] + '</div>'
@ -724,11 +729,10 @@ class Article extends App.Controller
@article_changed = false
@article['html'] = @article['html'].replace /^\n{0,10}(--|__)/m, (match) =>
@article_changed = true
notify + '<div class="hide">' + match
notify + '<div class="hide preview">' + match
if @article_changed
@article['html'] = @article['html'] + '</div>'
actionRow: ->
if @isRole('Customer')
@article.actions = []
@ -786,7 +790,7 @@ class TicketActionRow extends App.Controller
@render()
render: ->
@html App.view('ticket_action')()
@html App.view('ticket_zoom/actions')()
history_dialog: (e) ->
e.preventDefault()
@ -794,11 +798,11 @@ class TicketActionRow extends App.Controller
merge_dialog: (e) ->
e.preventDefault()
new App.TicketMerge( ticket_id: @ticket.id, task_key: @zoom.task_key )
new App.TicketMerge( ticket_id: @ticket.id, task_key: @ui.task_key )
customer_dialog: (e) ->
e.preventDefault()
new App.TicketCustomer( ticket_id: @ticket.id, zoom: @zoom )
new App.TicketCustomer( ticket_id: @ticket.id, ui: @ui )
class TicketZoomRouter extends App.ControllerPermanent
constructor: (params) ->

View file

@ -18,6 +18,8 @@ class Index extends App.ControllerContent
head: 'some header'
)
App.Config.set( 'trigger', Index, 'Routes' )
#App.Config.set( 'trigger', Index, 'Routes' )
#App.Config.set( 'Trigger', { prio: 3000, parent: '#admin', name: 'Trigger', target: '#trigger', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'Trigger', { prio: 3000, name: 'Triggers', target: '#manage/triggers', controller: Index, role: ['Admin'] }, 'NavBarLevel2' )
App.Config.set( 'Trigger', { prio: 3000, parent: '#admin', name: 'Trigger', target: '#trigger', role: ['Admin'] }, 'NavBar' )

View file

@ -1,4 +1,4 @@
class Index extends App.ControllerContent
class Index extends App.Controller
constructor: ->
super
@ -6,26 +6,24 @@ class Index extends App.ControllerContent
return if !@authenticate()
new App.ControllerGenericIndex(
el: @el,
id: @id,
genericObject: 'User',
defaultSortBy: 'login',
ignoreObjectIDs: [1],
pageData: {
title: 'Users',
home: 'users',
object: 'User',
objects: 'Users',
navupdate: '#users',
el: @el
id: @id
genericObject: 'User'
defaultSortBy: 'login'
ignoreObjectIDs: [1]
pageData:
title: 'Users'
home: 'users'
object: 'User'
objects: 'Users'
navupdate: '#users'
notes: [
'Users are for any person in the system. Agents (Owners, Resposbiles, ...) and Customers.'
],
]
buttons: [
# { name: 'List', 'data-type': '', class: 'active' },
{ name: 'New User', 'data-type': 'new', class: 'primary' },
],
}
{ name: 'New User', 'data-type': 'new', class: 'primary' }
]
)
App.Config.set( 'users', Index, 'Routes' )
App.Config.set( 'User', { prio: 1000, parent: '#admin', name: 'Users', target: '#users', role: ['Admin'] }, 'NavBar' )
App.Config.set( 'User', { prio: 1000, name: 'Users', parent: '#manage', target: '#manage/users', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )

View file

@ -1,4 +1,4 @@
class App.ChatWidget extends App.Controller
class Widget extends App.Controller
events:
'submit #chat_form': 'submitMessage'
'focusin [name=chat_message]': 'focusIn'
@ -130,6 +130,7 @@ class App.ChatWidget extends App.Controller
'chat-message-new'
)
@el.find('#chat_content').show(100)
@el.find('#chat_content').removeClass('hide')
@newMessage = false
# hide
@ -142,6 +143,7 @@ class App.ChatWidget extends App.Controller
hide: =>
@isShown = false
@el.find('#chat_content').hide(100)
@el.find('#chat_content').addClass('hide')
@el.find('#chat_toogle').html('&diams;');
focusIn: =>
@ -171,7 +173,7 @@ class App.ChatWidget extends App.Controller
shown = false
if @isShown
shown = true
@html App.view('chat_widget')(
@html App.view('widget/chat')(
messages: @messageLog
isShown: shown
)
@ -210,4 +212,4 @@ class App.ChatWidget extends App.Controller
)
@render()
App.Config.set( 'chat', App.ChatWidget, 'Widgets' )
App.Config.set( 'chat', Widget, 'Widgets' )

View file

@ -1,14 +1,14 @@
class App.LinkInfo extends App.Controller
class App.WidgetLink extends App.ControllerDrox
events:
'click [data-type=add]': 'add',
'click [data-type=edit]': 'edit',
'click [data-type=edit]': 'toggle',
'click [data-type=remove]': 'remove',
constructor: ->
super
@fetch()
fetch: () =>
fetch: =>
# fetch item on demand
# get data
@ajax(
@ -27,9 +27,12 @@ class App.LinkInfo extends App.Controller
App.Event.trigger 'loadAssets', data.assets
@render()
if _.isEmpty(data.links)
@toggle()
)
render: () =>
render: =>
list = {}
for item in @links
@ -43,8 +46,12 @@ class App.LinkInfo extends App.Controller
list[ item['link_type'] ].push ticket
# insert data
@html App.view('link/info')(
links: list,
@html @template(
file: 'link/info'
header: 'Links'
edit: true
params:
links: list
)
# show edit mode once enabled
@ -58,15 +65,16 @@ class App.LinkInfo extends App.Controller
# )
# enable/disable edit mode
edit: (e) =>
toggle: (e) =>
if e
e.preventDefault()
@edit_mode = true
if $(e.target).parent().parent().find('[data-type=add]').hasClass('hide')
$(e.target).parent().parent().find('[data-type=remove]').removeClass('hide')
$(e.target).parent().parent().find('[data-type=add]').removeClass('hide')
if @el.find('[data-type=add]').hasClass('hide')
@el.find('[data-type=remove]').removeClass('hide')
@el.find('[data-type=add]').removeClass('hide')
else
$(e.target).parent().parent().find('[data-type=remove]').addClass('hide')
$(e.target).parent().parent().find('[data-type=add]').addClass('hide')
@el.find('[data-type=remove]').addClass('hide')
@el.find('[data-type=add]').addClass('hide')
remove: (e) =>
e.preventDefault()

View file

@ -1,4 +1,4 @@
class App.MaintenanceWidget extends App.Controller
class Widget extends App.Controller
constructor: ->
super
@ -31,4 +31,4 @@ class Message extends App.ControllerModal
forceReload: message.reload
)
App.Config.set( 'maintenance', App.MaintenanceWidget, 'Widgets' )
App.Config.set( 'maintenance', Widget, 'Widgets' )

View file

@ -0,0 +1,78 @@
class App.WidgetOrganization extends App.Controller
events:
'focusout [data-type=update-org]': 'update',
'click [data-type=edit-org]': 'edit'
constructor: ->
super
# show organization
callback = (organization) =>
@render(organization)
if @callback
@callback(organization)
# subscribe and reload data / fetch new data if triggered
@subscribeId = organization.subscribe(@render)
App.Organization.retrieve( @organization_id, callback )
release: =>
App.Organization.unsubscribe(@subscribeId)
render: (organization) =>
if !organization
organization = @u
# get display data
organizationData = []
for item2 in App.Organization.configure_attributes
item = _.clone( item2 )
# check if value for _id exists
itemNameValue = item.name
itemNameValueNew = itemNameValue.substr( 0, itemNameValue.length - 3 )
if itemNameValueNew of organization
item.name = itemNameValueNew
# add to show if value exists
if organization[item.name] || item.tag is 'textarea'
# do not show name / already show via diplayName()
if item.name isnt 'name'
if item.info
organizationData.push item
# insert userData
@html App.view('widget/organization')(
organization: organization
organizationData: organizationData
)
###
@userTicketPopups(
selector: '.user-tickets'
user_id: user.id
position: 'right'
)
###
update: (e) =>
note = $(e.target).parent().find('[data-type=update]').val()
organization = App.Organization.find( @organization_id )
if organization.note isnt note
organization.updateAttributes( note: note )
@log 'notice', 'update', e, note, organization
edit: (e) =>
e.preventDefault()
new App.ControllerGenericEdit(
id: @organization_id,
genericObject: 'Organization',
pageData: {
title: 'Organizations',
object: 'Organization',
objects: 'Organizations',
},
callback: @render
)

View file

@ -1,4 +1,4 @@
class App.TagWidget extends App.Controller
class App.WidgetTag extends App.Controller
constructor: ->
super
@load()
@ -6,6 +6,8 @@ class App.TagWidget extends App.Controller
# update box size
@bind 'ui:rerender:content', =>
@siteUpdate()
@bind 'ui:rerender:task', =>
@siteUpdate()
load: =>
@attribute_id = 'tags_' + @object.id + '_' + @object_type
@ -24,16 +26,16 @@ class App.TagWidget extends App.Controller
render: (tags) =>
# insert data
@html App.view('tag_widget')(
@html App.view('widget/tag')(
tags: tags || [],
tag_id: @attribute_id
)
@el.find('#' + @attribute_id ).tagsInput(
width: '150px'
width: '100%'
defaultText: App.i18n.translateContent('add a Tag')
onAddTag: @onAddTag
onRemoveTag: @onRemoveTag
# height: '65px'
height: '45px'
)
@delay @siteUpdate, 250

View file

@ -1,4 +1,4 @@
class App.TemplateUI extends App.Controller
class App.WidgetTemplate extends App.ControllerDrox
events:
'click [data-type=template_save]': 'create',
'click [data-type=template_select]': 'select',
@ -21,8 +21,11 @@ class App.TemplateUI extends App.Controller
template = App.Template.find( @template_id )
# insert data
@html App.view('template_widget')(
template: template,
@html @template(
file: 'widget/template'
header: 'Templates'
params:
template: template
)
new App.ControllerForm(
el: @el.find('#form-template')
@ -54,6 +57,7 @@ class App.TemplateUI extends App.Controller
e.preventDefault()
# get params
form = @formParam( $('.ticket-create') )
params = @formParam(e.target)
name = params['template_name']
# delete params['template_name']
@ -62,10 +66,9 @@ class App.TemplateUI extends App.Controller
if !template
template = new App.Template
options = params
template.load(
name: params['template_name']
options: options
options: form
)
# validate form

View file

@ -1,4 +1,4 @@
class App.TextModuleUI extends App.Controller
class App.WidgetTextModule extends App.Controller
constructor: ->
super
@ -59,7 +59,7 @@ class App.TextModuleUI extends App.Controller
return values
class App.TextModuleUIOld extends App.Controller
class App.WidgetTextModuleOld extends App.Controller
events:
'click [data-type=save]': 'create',
'click [data-type=text_module_delete]': 'delete',
@ -191,7 +191,7 @@ class App.TextModuleUIOld extends App.Controller
)
# insert data
@html App.view('text_module_widget')(
@html App.view('widget/text_module')(
search: @search,
)

View file

@ -1,4 +1,4 @@
class App.UserInfo extends App.Controller
class App.WidgetUser extends App.ControllerDrox
events:
'focusout [data-type=update]': 'update',
'click [data-type=edit]': 'edit'
@ -25,7 +25,7 @@ class App.UserInfo extends App.Controller
user = @u
# get display data
data = []
userData = []
for item2 in App.User.configure_attributes
item = _.clone( item2 )
@ -36,25 +36,37 @@ class App.UserInfo extends App.Controller
item.name = itemNameValueNew
# add to show if value exists
if user[item.name]
if user[item.name] || item.tag is 'textarea'
# do not show firstname and lastname / already show via diplayName()
if item.name isnt 'firstname' && item.name isnt 'lastname' && item.name isnt 'organization'
if item.name isnt 'firstname' && item.name isnt 'lastname'
if item.info
data.push item
userData.push item
# insert data
@html App.view('user_info')(
user: user,
data: data,
# insert userData
@html @template(
file: 'widget/user'
header: 'Customer'
edit: true
params:
user: user
userData: userData
)
@userTicketPopups(
selector: '.user-tickets',
user_id: user.id,
selector: '.user-tickets'
user_id: user.id
position: 'right'
)
if user.organization_id
@el.append('<div class="org-info"></div>')
new App.WidgetOrganization(
organization_id: user.organization_id
el: @el.find('.org-info')
)
# update changes
update: (e) =>
note = $(e.target).parent().find('[data-type=update]').val()
user = App.User.find( @user_id )

View file

@ -42,7 +42,9 @@ class App extends Spine.Controller
# define linkify helper
params.L = ( item ) ->
window.linkify( item )
if item && typeof item is 'string'
return window.linkify( item )
item
# define config helper
params.C = ( key ) ->

View file

@ -25,18 +25,25 @@ class _collectionSingleton extends Spine.Module
for type, collections of data
if type is 'users'
type = 'User'
throw "BREAK, users"
if type is 'tickets'
type = 'Ticket'
throw "BREAK, tickets"
if type is 'ticket_article'
type = 'TicketArticle'
throw "BREAK, ticket_article"
if type is 'organization'
type = 'Organization'
throw "BREAK, organization"
if type is 'history_object'
type = 'HistoryObject'
throw "BREAK, history_object"
if type is 'history_type'
type = 'HistoryType'
throw "BREAK, history_type"
if type is 'history_attribute'
type = 'HistoryAttribute'
throw "BREAK, history_attribute"
@log 'debug', 'loadCollection:trigger', type, collections
@load( localStorage: data.localStorage, type: type, data: collections )

View file

@ -47,7 +47,7 @@ class App.Run extends App.Controller
App.Event.trigger( event + ':ready')
class App.Content extends App.Controller
className: 'container'
className: 'content'
constructor: ->
super

View file

@ -147,7 +147,7 @@ class _taskManagerSingleton extends App.Controller
# create div for permanent content
if !$("#content_permanent")[0]
$('#app section').append('<div id="content_permanent" class="container"></div>')
$('#app section').append('<div id="content_permanent" class="content"></div>')
# empty static content if task is shown
if active
@ -208,6 +208,7 @@ class _taskManagerSingleton extends App.Controller
worker = @worker( key )
if worker && worker.activate
worker.activate()
App.Event.trigger('ui:rerender:task')
# return if controller is already started
return if @workersStarted[key]

View file

@ -1,105 +0,0 @@
/* ============================================================
* bootstrap-button.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#buttons
* ============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"; // jshint ;_;
/* BUTTON PUBLIC CLASS DEFINITION
* ============================== */
var Button = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, $.fn.button.defaults, options)
}
Button.prototype.setState = function (state) {
var d = 'disabled'
, $el = this.$element
, data = $el.data()
, val = $el.is('input') ? 'val' : 'html'
state = state + 'Text'
data.resetText || $el.data('resetText', $el[val]())
$el[val](data[state] || this.options[state])
// push to event loop to allow forms to submit
setTimeout(function () {
state == 'loadingText' ?
$el.addClass(d).attr(d, d) :
$el.removeClass(d).removeAttr(d)
}, 0)
}
Button.prototype.toggle = function () {
var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
$parent && $parent
.find('.active')
.removeClass('active')
this.$element.toggleClass('active')
}
/* BUTTON PLUGIN DEFINITION
* ======================== */
var old = $.fn.button
$.fn.button = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('button')
, options = typeof option == 'object' && option
if (!data) $this.data('button', (data = new Button(this, options)))
if (option == 'toggle') data.toggle()
else if (option) data.setState(option)
})
}
$.fn.button.defaults = {
loadingText: 'loading...'
}
$.fn.button.Constructor = Button
/* BUTTON NO CONFLICT
* ================== */
$.fn.button.noConflict = function () {
$.fn.button = old
return this
}
/* BUTTON DATA-API
* =============== */
$(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
var $btn = $(e.target)
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
$btn.button('toggle')
})
}(window.jQuery);

View file

@ -1,167 +0,0 @@
/* =============================================================
* bootstrap-collapse.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#collapse
* =============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"; // jshint ;_;
/* COLLAPSE PUBLIC CLASS DEFINITION
* ================================ */
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, $.fn.collapse.defaults, options)
if (this.options.parent) {
this.$parent = $(this.options.parent)
}
this.options.toggle && this.toggle()
}
Collapse.prototype = {
constructor: Collapse
, dimension: function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
, show: function () {
var dimension
, scroll
, actives
, hasData
if (this.transitioning || this.$element.hasClass('in')) return
dimension = this.dimension()
scroll = $.camelCase(['scroll', dimension].join('-'))
actives = this.$parent && this.$parent.find('> .accordion-group > .in')
if (actives && actives.length) {
hasData = actives.data('collapse')
if (hasData && hasData.transitioning) return
actives.collapse('hide')
hasData || actives.data('collapse', null)
}
this.$element[dimension](0)
this.transition('addClass', $.Event('show'), 'shown')
$.support.transition && this.$element[dimension](this.$element[0][scroll])
}
, hide: function () {
var dimension
if (this.transitioning || !this.$element.hasClass('in')) return
dimension = this.dimension()
this.reset(this.$element[dimension]())
this.transition('removeClass', $.Event('hide'), 'hidden')
this.$element[dimension](0)
}
, reset: function (size) {
var dimension = this.dimension()
this.$element
.removeClass('collapse')
[dimension](size || 'auto')
[0].offsetWidth
this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
return this
}
, transition: function (method, startEvent, completeEvent) {
var that = this
, complete = function () {
if (startEvent.type == 'show') that.reset()
that.transitioning = 0
that.$element.trigger(completeEvent)
}
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
this.transitioning = 1
this.$element[method]('in')
$.support.transition && this.$element.hasClass('collapse') ?
this.$element.one($.support.transition.end, complete) :
complete()
}
, toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
}
/* COLLAPSE PLUGIN DEFINITION
* ========================== */
var old = $.fn.collapse
$.fn.collapse = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('collapse')
, options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.collapse.defaults = {
toggle: true
}
$.fn.collapse.Constructor = Collapse
/* COLLAPSE NO CONFLICT
* ==================== */
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return this
}
/* COLLAPSE DATA-API
* ================= */
$(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
var $this = $(this), href
, target = $this.attr('data-target')
|| e.preventDefault()
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
, option = $(target).data('collapse') ? 'toggle' : $this.data()
$this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
$(target).collapse(option)
})
}(window.jQuery);

View file

@ -1,169 +0,0 @@
/* ============================================================
* bootstrap-dropdown.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#dropdowns
* ============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"; // jshint ;_;
/* DROPDOWN CLASS DEFINITION
* ========================= */
var toggle = '[data-toggle=dropdown]'
, Dropdown = function (element) {
var $el = $(element).on('click.dropdown.data-api', this.toggle)
$('html').on('click.dropdown.data-api', function () {
$el.parent().removeClass('open')
})
}
Dropdown.prototype = {
constructor: Dropdown
, toggle: function (e) {
var $this = $(this)
, $parent
, isActive
if ($this.is('.disabled, :disabled')) return
$parent = getParent($this)
isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement) {
// if mobile we we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertBefore($(this)).on('click', clearMenus)
}
$parent.toggleClass('open')
}
$this.focus()
return false
}
, keydown: function (e) {
var $this
, $items
, $active
, $parent
, isActive
, index
if (!/(38|40|27)/.test(e.keyCode)) return
$this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
$parent = getParent($this)
isActive = $parent.hasClass('open')
if (!isActive || (isActive && e.keyCode == 27)) {
if (e.which == 27) $parent.find(toggle).focus()
return $this.click()
}
$items = $('[role=menu] li:not(.divider):visible a', $parent)
if (!$items.length) return
index = $items.index($items.filter(':focus'))
if (e.keyCode == 38 && index > 0) index-- // up
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items
.eq(index)
.focus()
}
}
function clearMenus() {
$('.dropdown-backdrop').remove()
$(toggle).each(function () {
getParent($(this)).removeClass('open')
})
}
function getParent($this) {
var selector = $this.attr('data-target')
, $parent
if (!selector) {
selector = $this.attr('href')
selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
$parent = selector && $(selector)
if (!$parent || !$parent.length) $parent = $this.parent()
return $parent
}
/* DROPDOWN PLUGIN DEFINITION
* ========================== */
var old = $.fn.dropdown
$.fn.dropdown = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('dropdown')
if (!data) $this.data('dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
$.fn.dropdown.Constructor = Dropdown
/* DROPDOWN NO CONFLICT
* ==================== */
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
/* APPLY TO STANDARD DROPDOWN ELEMENTS
* =================================== */
$(document)
.on('click.dropdown.data-api', clearMenus)
.on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
.on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
}(window.jQuery);

View file

@ -1,247 +0,0 @@
/* =========================================================
* bootstrap-modal.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#modals
* =========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================= */
!function ($) {
"use strict"; // jshint ;_;
/* MODAL CLASS DEFINITION
* ====================== */
var Modal = function (element, options) {
this.options = options
this.$element = $(element)
.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
}
Modal.prototype = {
constructor: Modal
, toggle: function () {
return this[!this.isShown ? 'show' : 'hide']()
}
, show: function () {
var that = this
, e = $.Event('show')
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
this.isShown = true
this.escape()
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(document.body) //don't move modals dom position
}
that.$element.show()
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
transition ?
that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
that.$element.focus().trigger('shown')
})
}
, hide: function (e) {
e && e.preventDefault()
var that = this
e = $.Event('hide')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
this.escape()
$(document).off('focusin.modal')
this.$element
.removeClass('in')
.attr('aria-hidden', true)
$.support.transition && this.$element.hasClass('fade') ?
this.hideWithTransition() :
this.hideModal()
}
, enforceFocus: function () {
var that = this
$(document).on('focusin.modal', function (e) {
if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
that.$element.focus()
}
})
}
, escape: function () {
var that = this
if (this.isShown && this.options.keyboard) {
this.$element.on('keyup.dismiss.modal', function ( e ) {
e.which == 27 && that.hide()
})
} else if (!this.isShown) {
this.$element.off('keyup.dismiss.modal')
}
}
, hideWithTransition: function () {
var that = this
, timeout = setTimeout(function () {
that.$element.off($.support.transition.end)
that.hideModal()
}, 500)
this.$element.one($.support.transition.end, function () {
clearTimeout(timeout)
that.hideModal()
})
}
, hideModal: function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.removeBackdrop()
that.$element.trigger('hidden')
})
}
, removeBackdrop: function () {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
, backdrop: function (callback) {
var that = this
, animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
this.$backdrop.click(
this.options.backdrop == 'static' ?
$.proxy(this.$element[0].focus, this.$element[0])
: $.proxy(this.hide, this)
)
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if (!callback) return
doAnimate ?
this.$backdrop.one($.support.transition.end, callback) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
$.support.transition && this.$element.hasClass('fade')?
this.$backdrop.one($.support.transition.end, callback) :
callback()
} else if (callback) {
callback()
}
}
}
/* MODAL PLUGIN DEFINITION
* ======================= */
var old = $.fn.modal
$.fn.modal = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('modal')
, options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option]()
else if (options.show) data.show()
})
}
$.fn.modal.defaults = {
backdrop: true
, keyboard: true
, show: true
}
$.fn.modal.Constructor = Modal
/* MODAL NO CONFLICT
* ================= */
$.fn.modal.noConflict = function () {
$.fn.modal = old
return this
}
/* MODAL DATA-API
* ============== */
$(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
, href = $this.attr('href')
, $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
, option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
e.preventDefault()
$target
.modal(option)
.one('hide', function () {
$this.focus()
})
})
}(window.jQuery);

View file

@ -1,114 +0,0 @@
/* ===========================================================
* bootstrap-popover.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#popovers
* ===========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* POPOVER PUBLIC CLASS DEFINITION
* =============================== */
var Popover = function (element, options) {
this.init('popover', element, options)
}
/* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
========================================== */
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
constructor: Popover
, setContent: function () {
var $tip = this.tip()
, title = this.getTitle()
, content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
$tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
$tip.removeClass('fade top bottom left right in')
}
, hasContent: function () {
return this.getTitle() || this.getContent()
}
, getContent: function () {
var content
, $e = this.$element
, o = this.options
content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
|| $e.attr('data-content')
return content
}
, tip: function () {
if (!this.$tip) {
this.$tip = $(this.options.template)
}
return this.$tip
}
, destroy: function () {
this.hide().$element.off('.' + this.type).removeData(this.type)
}
})
/* POPOVER PLUGIN DEFINITION
* ======================= */
var old = $.fn.popover
$.fn.popover = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('popover')
, options = typeof option == 'object' && option
if (!data) $this.data('popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.popover.Constructor = Popover
$.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
placement: 'right'
, trigger: 'click'
, content: ''
, template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})
/* POPOVER NO CONFLICT
* =================== */
$.fn.popover.noConflict = function () {
$.fn.popover = old
return this
}
}(window.jQuery);

View file

@ -1,144 +0,0 @@
/* ========================================================
* bootstrap-tab.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#tabs
* ========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* TAB CLASS DEFINITION
* ==================== */
var Tab = function (element) {
this.element = $(element)
}
Tab.prototype = {
constructor: Tab
, show: function () {
var $this = this.element
, $ul = $this.closest('ul:not(.dropdown-menu)')
, selector = $this.attr('data-target')
, previous
, $target
, e
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
if ( $this.parent('li').hasClass('active') ) return
previous = $ul.find('.active:last a')[0]
e = $.Event('show', {
relatedTarget: previous
})
$this.trigger(e)
if (e.isDefaultPrevented()) return
$target = $(selector)
this.activate($this.parent('li'), $ul)
this.activate($target, $target.parent(), function () {
$this.trigger({
type: 'shown'
, relatedTarget: previous
})
})
}
, activate: function ( element, container, callback) {
var $active = container.find('> .active')
, transition = callback
&& $.support.transition
&& $active.hasClass('fade')
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
element.addClass('active')
if (transition) {
element[0].offsetWidth // reflow for transition
element.addClass('in')
} else {
element.removeClass('fade')
}
if ( element.parent('.dropdown-menu') ) {
element.closest('li.dropdown').addClass('active')
}
callback && callback()
}
transition ?
$active.one($.support.transition.end, next) :
next()
$active.removeClass('in')
}
}
/* TAB PLUGIN DEFINITION
* ===================== */
var old = $.fn.tab
$.fn.tab = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('tab')
if (!data) $this.data('tab', (data = new Tab(this)))
if (typeof option == 'string') data[option]()
})
}
$.fn.tab.Constructor = Tab
/* TAB NO CONFLICT
* =============== */
$.fn.tab.noConflict = function () {
$.fn.tab = old
return this
}
/* TAB DATA-API
* ============ */
$(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
e.preventDefault()
$(this).tab('show')
})
}(window.jQuery);

View file

@ -1,361 +0,0 @@
/* ===========================================================
* bootstrap-tooltip.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#tooltips
* Inspired by the original jQuery.tipsy by Jason Frame
* ===========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* TOOLTIP PUBLIC CLASS DEFINITION
* =============================== */
var Tooltip = function (element, options) {
this.init('tooltip', element, options)
}
Tooltip.prototype = {
constructor: Tooltip
, init: function (type, element, options) {
var eventIn
, eventOut
, triggers
, trigger
, i
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.enabled = true
triggers = this.options.trigger.split(' ')
for (i = triggers.length; i--;) {
trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
, getOptions: function (options) {
options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay
, hide: options.delay
}
}
return options
}
, enter: function (e) {
var defaults = $.fn[this.type].defaults
, options = {}
, self
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
}, this)
self = $(e.currentTarget)[this.type](options).data(this.type)
if (!self.options.delay || !self.options.delay.show) return self.show()
clearTimeout(this.timeout)
self.hoverState = 'in'
this.timeout = setTimeout(function() {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
, leave: function (e) {
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
if (this.timeout) clearTimeout(this.timeout)
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.hoverState = 'out'
this.timeout = setTimeout(function() {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
, show: function () {
var $tip
, pos
, actualWidth
, actualHeight
, placement
, tp
, e = $.Event('show')
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip = this.tip()
this.setContent()
if (this.options.animation) {
$tip.addClass('fade')
}
placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
pos = this.getPosition()
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
switch (placement) {
case 'bottom':
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'top':
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'left':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
break
case 'right':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
break
}
this.applyPlacement(tp, placement)
this.$element.trigger('shown')
}
}
, applyPlacement: function(offset, placement){
var $tip = this.tip()
, width = $tip[0].offsetWidth
, height = $tip[0].offsetHeight
, actualWidth
, actualHeight
, delta
, replace
$tip
.offset(offset)
.addClass(placement)
.addClass('in')
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
replace = true
}
if (placement == 'bottom' || placement == 'top') {
delta = 0
if (offset.left < 0){
delta = offset.left * -2
offset.left = 0
$tip.offset(offset)
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
}
this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
} else {
this.replaceArrow(actualHeight - height, actualHeight, 'top')
}
if (replace) $tip.offset(offset)
}
, replaceArrow: function(delta, dimension, position){
this
.arrow()
.css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
}
, setContent: function () {
var $tip = this.tip()
, title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
, hide: function () {
var that = this
, $tip = this.tip()
, e = $.Event('hide')
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
function removeWithAnimation() {
var timeout = setTimeout(function () {
$tip.off($.support.transition.end).detach()
}, 500)
$tip.one($.support.transition.end, function () {
clearTimeout(timeout)
$tip.detach()
})
}
$.support.transition && this.$tip.hasClass('fade') ?
removeWithAnimation() :
$tip.detach()
this.$element.trigger('hidden')
return this
}
, fixTitle: function () {
var $e = this.$element
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
, hasContent: function () {
return this.getTitle()
}
, getPosition: function () {
var el = this.$element[0]
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
width: el.offsetWidth
, height: el.offsetHeight
}, this.$element.offset())
}
, getTitle: function () {
var title
, $e = this.$element
, o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
, tip: function () {
return this.$tip = this.$tip || $(this.options.template)
}
, arrow: function(){
return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
}
, validate: function () {
if (!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
, enable: function () {
this.enabled = true
}
, disable: function () {
this.enabled = false
}
, toggleEnabled: function () {
this.enabled = !this.enabled
}
, toggle: function (e) {
var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
self.tip().hasClass('in') ? self.hide() : self.show()
}
, destroy: function () {
this.hide().$element.off('.' + this.type).removeData(this.type)
}
}
/* TOOLTIP PLUGIN DEFINITION
* ========================= */
var old = $.fn.tooltip
$.fn.tooltip = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('tooltip')
, options = typeof option == 'object' && option
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.tooltip.Constructor = Tooltip
$.fn.tooltip.defaults = {
animation: true
, placement: 'top'
, selector: false
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
, trigger: 'hover focus'
, title: ''
, delay: 0
, html: false
, container: false
}
/* TOOLTIP NO CONFLICT
* =================== */
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
}(window.jQuery);

View file

@ -1,60 +0,0 @@
/* ===================================================
* bootstrap-transition.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#transitions
* ===================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
* ======================================================= */
$(function () {
$.support.transition = (function () {
var transitionEnd = (function () {
var el = document.createElement('bootstrap')
, transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd'
, 'MozTransition' : 'transitionend'
, 'OTransition' : 'oTransitionEnd otransitionend'
, 'transition' : 'transitionend'
}
, name
for (name in transEndEventNames){
if (el.style[name] !== undefined) {
return transEndEventNames[name]
}
}
}())
return transitionEnd && {
end: transitionEnd
}
})()
})
}(window.jQuery);

View file

@ -0,0 +1,109 @@
/* ========================================================================
* Bootstrap: button.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#buttons
* ========================================================================
* Copyright 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
var Button = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Button.DEFAULTS, options)
}
Button.DEFAULTS = {
loadingText: 'loading...'
}
Button.prototype.setState = function (state) {
var d = 'disabled'
var $el = this.$element
var val = $el.is('input') ? 'val' : 'html'
var data = $el.data()
state = state + 'Text'
if (!data.resetText) $el.data('resetText', $el[val]())
$el[val](data[state] || this.options[state])
// push to event loop to allow forms to submit
setTimeout(function () {
state == 'loadingText' ?
$el.addClass(d).attr(d, d) :
$el.removeClass(d).removeAttr(d);
}, 0)
}
Button.prototype.toggle = function () {
var $parent = this.$element.closest('[data-toggle="buttons"]')
if ($parent.length) {
var $input = this.$element.find('input')
.prop('checked', !this.$element.hasClass('active'))
.trigger('change')
if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')
}
this.$element.toggleClass('active')
}
// BUTTON PLUGIN DEFINITION
// ========================
var old = $.fn.button
$.fn.button = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.button')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.button', (data = new Button(this, options)))
if (option == 'toggle') data.toggle()
else if (option) data.setState(option)
})
}
$.fn.button.Constructor = Button
// BUTTON NO CONFLICT
// ==================
$.fn.button.noConflict = function () {
$.fn.button = old
return this
}
// BUTTON DATA-API
// ===============
$(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
var $btn = $(e.target)
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
$btn.button('toggle')
e.preventDefault()
})
}(window.jQuery);

View file

@ -0,0 +1,179 @@
/* ========================================================================
* Bootstrap: collapse.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#collapse
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.transitioning = null
if (this.options.parent) this.$parent = $(this.options.parent)
if (this.options.toggle) this.toggle()
}
Collapse.DEFAULTS = {
toggle: true
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var actives = this.$parent && this.$parent.find('> .panel > .in')
if (actives && actives.length) {
var hasData = actives.data('bs.collapse')
if (hasData && hasData.transitioning) return
actives.collapse('hide')
hasData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')
[dimension](0)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('in')
[dimension]('auto')
this.transitioning = 0
this.$element.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one($.support.transition.end, $.proxy(complete, this))
.emulateTransitionEnd(350)
[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element
[dimension](this.$element[dimension]())
[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse')
.removeClass('in')
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.trigger('hidden.bs.collapse')
.removeClass('collapsing')
.addClass('collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one($.support.transition.end, $.proxy(complete, this))
.emulateTransitionEnd(350)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
// COLLAPSE PLUGIN DEFINITION
// ==========================
var old = $.fn.collapse
$.fn.collapse = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.collapse.Constructor = Collapse
// COLLAPSE NO CONFLICT
// ====================
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return this
}
// COLLAPSE DATA-API
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {
var $this = $(this), href
var target = $this.attr('data-target')
|| e.preventDefault()
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
var $target = $(target)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $this.data()
var parent = $this.attr('data-parent')
var $parent = parent && $(parent)
if (!data || !data.transitioning) {
if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
}
$target.collapse(option)
})
}(window.jQuery);

View file

@ -0,0 +1,154 @@
/* ========================================================================
* Bootstrap: dropdown.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#dropdowns
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle=dropdown]'
var Dropdown = function (element) {
var $el = $(element).on('click.bs.dropdown', this.toggle)
}
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
}
$parent.trigger(e = $.Event('show.bs.dropdown'))
if (e.isDefaultPrevented()) return
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown')
$this.focus()
}
return false
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27)/.test(e.keyCode)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if (!isActive || (isActive && e.keyCode == 27)) {
if (e.which == 27) $parent.find(toggle).focus()
return $this.click()
}
var $items = $('[role=menu] li:not(.divider):visible a', $parent)
if (!$items.length) return
var index = $items.index($items.filter(':focus'))
if (e.keyCode == 38 && index > 0) index-- // up
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
if (!~index) index=0
$items.eq(index).focus()
}
function clearMenus() {
$(backdrop).remove()
$(toggle).each(function (e) {
var $parent = getParent($(this))
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown'))
if (e.isDefaultPrevented()) return
$parent.removeClass('open').trigger('hidden.bs.dropdown')
})
}
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
var old = $.fn.dropdown
$.fn.dropdown = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('dropdown')
if (!data) $this.data('dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
}(window.jQuery);

View file

@ -0,0 +1,246 @@
/* ========================================================================
* Bootstrap: modal.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#modals
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) {
this.options = options
this.$element = $(element)
this.$backdrop =
this.isShown = null
if (this.options.remote) this.$element.load(this.options.remote)
}
Modal.DEFAULTS = {
backdrop: true
, keyboard: true
, show: true
}
Modal.prototype.toggle = function (_relatedTarget) {
return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
}
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
this.isShown = true
this.escape()
this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(document.body) // don't move modals dom position
}
that.$element.show()
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$element.find('.modal-dialog') // wait for modal to slide in
.one($.support.transition.end, function () {
that.$element.focus().trigger(e)
})
.emulateTransitionEnd(300) :
that.$element.focus().trigger(e)
})
}
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
this.escape()
$(document).off('focusin.bs.modal')
this.$element
.removeClass('in')
.attr('aria-hidden', true)
.off('click.dismiss.modal')
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one($.support.transition.end, $.proxy(this.hideModal, this))
.emulateTransitionEnd(300) :
this.hideModal()
}
Modal.prototype.enforceFocus = function () {
$(document)
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.focus()
}
}, this))
}
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
this.$element.off('keyup.dismiss.bs.modal')
}
}
Modal.prototype.hideModal = function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.removeBackdrop()
that.$element.trigger('hidden.bs.modal')
})
}
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
Modal.prototype.backdrop = function (callback) {
var that = this
var animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
this.$element.on('click.dismiss.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if (!callback) return
doAnimate ?
this.$backdrop
.one($.support.transition.end, callback)
.emulateTransitionEnd(150) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
$.support.transition && this.$element.hasClass('fade')?
this.$backdrop
.one($.support.transition.end, callback)
.emulateTransitionEnd(150) :
callback()
} else if (callback) {
callback()
}
}
// MODAL PLUGIN DEFINITION
// =======================
var old = $.fn.modal
$.fn.modal = function (option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
}
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT
// =================
$.fn.modal.noConflict = function () {
$.fn.modal = old
return this
}
// MODAL DATA-API
// ==============
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
e.preventDefault()
$target
.modal(option, this)
.one('hide', function () {
$this.is(':visible') && $this.focus()
})
})
$(document)
.on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
.on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
}(window.jQuery);

View file

@ -0,0 +1,117 @@
/* ========================================================================
* Bootstrap: popover.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#popovers
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// POPOVER PUBLIC CLASS DEFINITION
// ===============================
var Popover = function (element, options) {
this.init('popover', element, options)
}
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right'
, trigger: 'click'
, content: ''
, template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})
// NOTE: POPOVER EXTENDS tooltip.js
// ================================
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
Popover.prototype.constructor = Popover
Popover.prototype.getDefaults = function () {
return Popover.DEFAULTS
}
Popover.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
$tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
$tip.removeClass('fade top bottom left right in')
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
// this manually by checking the contents.
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
}
Popover.prototype.hasContent = function () {
return this.getTitle() || this.getContent()
}
Popover.prototype.getContent = function () {
var $e = this.$element
var o = this.options
return $e.attr('data-content')
|| (typeof o.content == 'function' ?
o.content.call($e[0]) :
o.content)
}
Popover.prototype.arrow = function () {
return this.$arrow = this.$arrow || this.tip().find('.arrow')
}
Popover.prototype.tip = function () {
if (!this.$tip) this.$tip = $(this.options.template)
return this.$tip
}
// POPOVER PLUGIN DEFINITION
// =========================
var old = $.fn.popover
$.fn.popover = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.popover.Constructor = Popover
// POPOVER NO CONFLICT
// ===================
$.fn.popover.noConflict = function () {
$.fn.popover = old
return this
}
}(window.jQuery);

View file

@ -0,0 +1,135 @@
/* ========================================================================
* Bootstrap: tab.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#tabs
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// TAB CLASS DEFINITION
// ====================
var Tab = function (element) {
this.element = $(element)
}
Tab.prototype.show = function () {
var $this = this.element
var $ul = $this.closest('ul:not(.dropdown-menu)')
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
if ($this.parent('li').hasClass('active')) return
var previous = $ul.find('.active:last a')[0]
var e = $.Event('show.bs.tab', {
relatedTarget: previous
})
$this.trigger(e)
if (e.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.parent('li'), $ul)
this.activate($target, $target.parent(), function () {
$this.trigger({
type: 'shown.bs.tab'
, relatedTarget: previous
})
})
}
Tab.prototype.activate = function (element, container, callback) {
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
&& $active.hasClass('fade')
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
element.addClass('active')
if (transition) {
element[0].offsetWidth // reflow for transition
element.addClass('in')
} else {
element.removeClass('fade')
}
if (element.parent('.dropdown-menu')) {
element.closest('li.dropdown').addClass('active')
}
callback && callback()
}
transition ?
$active
.one($.support.transition.end, next)
.emulateTransitionEnd(150) :
next()
$active.removeClass('in')
}
// TAB PLUGIN DEFINITION
// =====================
var old = $.fn.tab
$.fn.tab = function ( option ) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tab')
if (!data) $this.data('bs.tab', (data = new Tab(this)))
if (typeof option == 'string') data[option]()
})
}
$.fn.tab.Constructor = Tab
// TAB NO CONFLICT
// ===============
$.fn.tab.noConflict = function () {
$.fn.tab = old
return this
}
// TAB DATA-API
// ============
$(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
e.preventDefault()
$(this).tab('show')
})
}(window.jQuery);

View file

@ -0,0 +1,386 @@
/* ========================================================================
* Bootstrap: tooltip.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function (element, options) {
this.type =
this.options =
this.enabled =
this.timeout =
this.hoverState =
this.$element = null
this.init('tooltip', element, options)
}
Tooltip.DEFAULTS = {
animation: true
, placement: 'top'
, selector: false
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
, trigger: 'hover focus'
, title: ''
, delay: 0
, html: false
, container: false
}
Tooltip.prototype.init = function (type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
var triggers = this.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
var trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function () {
return Tooltip.DEFAULTS
}
Tooltip.prototype.getOptions = function (options) {
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay
, hide: options.delay
}
}
return options
}
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
})
return options
}
Tooltip.prototype.enter = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
clearTimeout(self.timeout)
self.hoverState = 'in'
if (!self.options.delay || !self.options.delay.show) return self.show()
self.timeout = setTimeout(function () {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function () {
var e = $.Event('show.bs.'+ this.type)
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
var $tip = this.tip()
this.setContent()
if (this.options.animation) $tip.addClass('fade')
var placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
.addClass(placement)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var $parent = this.$element.parent()
var orgPlacement = placement
var docScroll = document.documentElement.scrollTop || document.body.scrollTop
var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(calculatedOffset, placement)
this.$element.trigger('shown.bs.' + this.type)
}
}
Tooltip.prototype.applyPlacement = function(offset, placement) {
var replace
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference
var marginTop = parseInt($tip.css('margin-top'), 10)
var marginLeft = parseInt($tip.css('margin-left'), 10)
// we must check for NaN for ie 8/9
if (isNaN(marginTop)) marginTop = 0
if (isNaN(marginLeft)) marginLeft = 0
offset.top = offset.top + marginTop
offset.left = offset.left + marginLeft
$tip
.offset(offset)
.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
replace = true
offset.top = offset.top + height - actualHeight
}
if (/bottom|top/.test(placement)) {
var delta = 0
if (offset.left < 0) {
delta = offset.left * -2
offset.left = 0
$tip.offset(offset)
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
}
this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
} else {
this.replaceArrow(actualHeight - height, actualHeight, 'top')
}
if (replace) $tip.offset(offset)
}
Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
}
Tooltip.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
Tooltip.prototype.hide = function () {
var that = this
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one($.support.transition.end, complete)
.emulateTransitionEnd(150) :
complete()
this.$element.trigger('hidden.bs.' + this.type)
return this
}
Tooltip.prototype.fixTitle = function () {
var $e = this.$element
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function () {
return this.getTitle()
}
Tooltip.prototype.getPosition = function () {
var el = this.$element[0]
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
width: el.offsetWidth
, height: el.offsetHeight
}, this.$element.offset())
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
Tooltip.prototype.tip = function () {
return this.$tip = this.$tip || $(this.options.template)
}
Tooltip.prototype.arrow = function () {
return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
}
Tooltip.prototype.validate = function () {
if (!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
Tooltip.prototype.disable = function () {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function (e) {
var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
Tooltip.prototype.destroy = function () {
this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
}
// TOOLTIP PLUGIN DEFINITION
// =========================
var old = $.fn.tooltip
$.fn.tooltip = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.tooltip.Constructor = Tooltip
// TOOLTIP NO CONFLICT
// ===================
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
}(window.jQuery);

View file

@ -0,0 +1,56 @@
/* ========================================================================
* Bootstrap: transition.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#transitions
* ========================================================================
* Copyright 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd'
, 'MozTransition' : 'transitionend'
, 'OTransition' : 'oTransitionEnd otransitionend'
, 'transition' : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false, $el = this
$(this).one($.support.transition.end, function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
})
}(window.jQuery);

View file

@ -13,6 +13,9 @@ class App.Model extends Spine.Model
App.Store.delete(key)
)
uiUrl: ->
'#'
displayName: ->
return @name if @name
if @realname
@ -26,6 +29,10 @@ class App.Model extends Spine.Model
return name
if @email
return @email
if @title
return @title
if @subject
return @subject
return '???'
displayNameLong: ->

View file

@ -17,3 +17,6 @@ class App.Group extends App.Model
@configure_overview = [
'name',
]
uiUrl: ->
'#group/zoom/' + @id

View file

@ -1,20 +0,0 @@
class App.History extends App.Model
@configure 'History', 'name'
@extend Spine.Model.Ajax
@url: @apiPath + '/histories'
@_fillUp: (data) ->
# add user
data.created_by = App.User.find( data.created_by_id )
# add possible actions
if data.history_attribute_id
data.attribute = App.HistoryAttribute.find( data.history_attribute_id )
if data.history_type_id
data.type = App.HistoryType.find( data.history_type_id )
if data.history_object_id
data.object = App.HistoryObject.find( data.history_object_id )
return data

View file

@ -1,4 +0,0 @@
class App.HistoryAttribute extends App.Model
@configure 'HistoryAttribute', 'name'
@extend Spine.Model.Ajax
@url: @apiPath + '/history_attributes'

View file

@ -1,4 +0,0 @@
class App.HistoryObject extends App.Model
@configure 'HistoryObject', 'name'
@extend Spine.Model.Ajax
@url: @apiPath + '/history_objects'

View file

@ -1,4 +0,0 @@
class App.HistoryType extends App.Model
@configure 'HistoryType', 'name'
@extend Spine.Model.Ajax
@url: @apiPath + '/history_types'

View file

@ -3,17 +3,20 @@ class App.Organization extends App.Model
@extend Spine.Model.Ajax
@url: @apiPath + '/organizations'
@configure_attributes = [
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, 'class': 'span4' },
{ name: 'shared', display: 'Shared organiztion', tag: 'boolean', note: 'Customers in the organiztion can view each other items.', type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' },
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1 },
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false, info: true, 'class': 'span4' },
{ name: 'shared', display: 'Shared organiztion', tag: 'boolean', note: 'Customers in the organiztion can view each other items.', type: 'boolean', 'default': true, 'null': false, info: false, 'class': 'span4' },
{ name: 'note', display: 'Note', tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, info: true, 'class': 'span4' },
{ name: 'updated_at', display: 'Updated', type: 'time', readonly: 1, info: false },
{ name: 'active', display: 'Active', tag: 'boolean', note: 'boolean', 'default': true, 'null': false, info: false, 'class': 'span4' },
]
@configure_overview = [
'name',
'shared',
]
uiUrl: ->
'#organization/zoom/' + @id
@_fillUp: (data) ->
# addd users of organization

View file

@ -20,6 +20,9 @@ class App.Ticket extends App.Model
{ name: 'article_count', display: 'Article#', style: 'width: 12%' },
]
uiUrl: ->
'#ticket/zoom/' + @id
@_fillUp: (data) ->
# priority

View file

@ -14,6 +14,9 @@ class App.TicketArticle extends App.Model
{ name: 'internal', display: 'Visibility', tag: 'radio', default: false, null: true, options: { true: 'internal', false: 'public' }, class: 'medium' },
]
uiUrl: ->
'#ticket/zoom/' + @ticket_id + '/' + @id
@_fillUp: (data) ->
# add created & updated

View file

@ -30,6 +30,9 @@ class App.User extends App.Model
'login', 'firstname', 'lastname',
]
uiUrl: ->
'#user/zoom/' + @id
@_fillUp: (data) ->
# set socal media links

View file

@ -1,21 +1,26 @@
<div class="page-header">
<div class="row">
<div class="span12">
<h1 class="pull-left"><%- @T( 'New Ticket' ) %> <small>(<%- @T( @title ) %>)<% if @admin: %> <a href="#" data-type="settings" class="icon-edit"></a><% end %></small></h1>
<div class="content-two">
<div class="sidebar">
<div class="ticket-widgets">
<div class="customer_info"></div>
<div class="ticket_template"></div>
<div class="text_module"></div>
</div>
</div>
</div>
<form class="form-horizontal ticket-create">
<div class="main">
<div class="page-header">
<h1><%- @T( 'New Ticket' ) %> <small>(<%- @T( @title ) %>)<% if @admin: %> <a href="#" data-type="settings" class="glyphicon glyphicon-edit"></a><% end %></small></h1>
</div>
<form class="form-horizontal form-large ticket-create">
<input type="hidden" value="" name="article_type"/>
<div class="row">
<div class="span9 ticket_create"></div>
<div class="span3">
<div data-id="customer_info"></div>
<div data-id="ticket_template"></div>
<div data-id="text_module"></div>
</div>
</div>
<div class="form-actions">
<button type="reset" class="btn cancel"><%- @T( 'Cancel' ) %></button>&nbsp;<button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button>
</div>
</form>
</form>
</div>
</div>
</div>

View file

@ -1,10 +1,14 @@
<form class="form-horizontal">
<div class="modal-header">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h2><%- @T( 'Change Customer' ) %></h2>
</div>
<div class="modal-body" id="form-customer"></div>
<div class="modal-footer">
<h2 class="modal-title"><%- @T( 'Change Customer' ) %></h2>
</div>
<div class="modal-body" id="form-customer"></div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary"><%- @T( 'Submit' ) %></button>
</div>
</div>
</div>
</form>

View file

@ -1,44 +1,48 @@
<div class="modal-header">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h2><%- @T( 'History' ) %></h2>
<a href="#" data-type="sortorder" id="sortorder" class="<%= @state %>"><%- @T( 'Change order' ) %></a>
</div>
<div class="modal-body">
<h2 class="modal-title"><%- @T( 'History' ) %></h2>
<a href="#" data-type="sortorder" class="<%= @orderClass %>"><%- @T( 'Change order' ) %></a>
</div>
<div class="modal-body">
<% open = false %>
<% for object in @objects: %>
<% object['history_object_display'] = object['history_object'] %>
<% if object['history_object'] is 'Ticket::Article': %>
<% object['history_object_display'] = 'Article' %>
<% end %>
<% if lasttime isnt object['created_at'] || last_user isnt object['created_by_id']: %>
<% for item in @items: %>
<% if lasttime isnt item['created_at'] || last_user isnt item['created_by_id']: %>
<% if open: %>
</ul>
<hr>
<% end %>
<% open = true %>
<% last_user = object['created_by_id'] %>
<% lasttime = object['created_at'] %>
<span class="user-data" data-id="<%= object.created_by.id %>"><%= object.created_by.displayName() %></span> -
<span class="humanTimeFromNow" data-time="<%- object.created_at %>">?</span>
<% last_user = item['created_by_id'] %>
<% lasttime = item['created_at'] %>
<span class="user-popover" data-id="<%= item.created_by.id %>"><%= item.created_by.displayName() %></span> -
<span class="humanTimeFromNow" data-time="<%- item.created_at %>">?</span>
<ul>
<% end %>
<li>
<% if ( object['history_type'] is 'notification' || object['history_type'] is 'email' ): %>
<%= object['history_type'] %>
<% if object['value_from']: %>
"<%= object['value_from'] %>" <%- @T( 'sent to' ) %>
<% if ( item['type'] is 'notification' || item['type'] is 'email' ): %>
<%- @T( item['type'] ) %>
<% if item['value_from']: %>
"<%= item['value_from'] %>" <%- @T( 'sent to' ) %>
<% end %>
<% if object['value_to']: %>
"<%= object['value_to'] %>"
<% if item['value_to']: %>
"<%= item['value_to'] %>"
<% end %>
<% else: %>
<%= object['history_type'] %> <%= object['history_object_display'] %> <% if object['history_attribute']: %>"<%= object['history_attribute'] %>"<% end %>
<% if object['value_from']: %>
<%- @T( 'from' ) %> "<%= object['value_from'] %>"
<%- @T( item['type'] ) %> <%= item['object'] %> <% if item['attribute']: %>"<%= item['attribute'] %>"<% end %>
<% if item['value_from']: %>
<% if item['value_to']: %>
<%- @T( 'from' ) %>
<% end %>
<% if object['value_to']: %>
<%- @T( 'to' ) %> "<%= object['value_to'] %>"
"<%= item['value_from'] %>"
<% end %>
<% if item['value_to']: %>
<% if item['value_from']: %>
<%- @T( 'to' ) %>
<% end %>
"<%= item['value_to'] %>"
<% end %>
<% end %>
</li>
@ -47,6 +51,9 @@
</ul>
<% end %>
</div>
<div class="modal-footer">
</div>
<div class="modal-footer">
</div>
</div>
</div>

View file

@ -1,19 +1,23 @@
<form class="form-horizontal">
<div class="modal-header">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h2><%- @T( 'Merge' ) %></h2>
</div>
<div class="modal-body">
<h2 class="modal-title"><%- @T( 'Merge' ) %></h2>
</div>
<div class="modal-body">
<h4><%- @T( 'Merge to Ticket#' ) %></h4>
<input type="text" name="master_ticket_number" value=""/>
<input type="text" name="master_ticket_number" class="form-control" value=""/>
<hr>
<h4><%- @T( 'Recent Customer Tickets' ) %></h4>
<div id="ticket-merge-customer-tickets"></div>
<hr>
<h4><%- @T( 'Recent Views Tickets' ) %></h4>
<div id="ticket-merge-recent-tickets"></div>
</div>
<div class="modal-footer">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary"><%- @T( 'Submit' ) %></button>
</div>
</div>
</div>
</form>

View file

@ -1,43 +1,4 @@
<div class="page-header">
<div class="row">
<div class="span9">
<h1><%- @T( @overview.name ) %> <% if @edit: %><small><a href="#" data-type="settings" class="icon-edit"></a></small><% end %></h1>
</div>
<div class="span3">
<div class="pagination pagination-small pagination-right">
<ul>
<% for item in @view_modes: %>
<li class="<%= item.class %>">
<a href="#" data-type="viewmode" data-mode="<%= item.type %>"><%= item.name %></a>
</li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
<!--
<div class="pagination pull-left">
<ul>
<% if @start_page != 1: %>
<li><a href="#" data-id="<%= @start_page - 1 %>" data-type="page">«</a></li>
<% end %>
<% for item in [1..@pages_total]: %>
<li>
<a href="#" data-id="<%= item %>" data-type="page"><%= item %></a>
</li>
<% end %>
<% if @start_page != @pages_total: %>
<li><a href="#" data-id="<%= @start_page + 1 %>" data-type="page">»</a></li>
<% end %>
</ul>
</div>
-->
<div class="row">
<div class="span12 table-overview"></div>
</div>
<div class="row">
<div class="span12 bulk-action hide well"></div>
<div class="content-two">
<div class="sidebar"></div>
<div class="main"></div>
</div>

View file

@ -0,0 +1,35 @@
<div class="page-header clearfix">
<div class="page-header-title">
<h1><%- @T( @overview.name ) %> <% if @edit: %><small><a href="#" data-type="settings" class="glyphicon glyphicon-edit"></a></small><% end %></h1>
</div>
<div class="page-header-meta">
<ul class="pagination">
<% for item in @view_modes: %>
<li class="<%= item.class %>">
<a href="#" data-type="viewmode" data-mode="<%= item.type %>"><%= item.name %></a>
</li>
<% end %>
</ul>
</div>
</div>
<!--
<div class="pagination pull-left">
<ul>
<% if @start_page != 1: %>
<li><a href="#" data-id="<%= @start_page - 1 %>" data-type="page">«</a></li>
<% end %>
<% for item in [1..@pages_total]: %>
<li>
<a href="#" data-id="<%= item %>" data-type="page"><%= item %></a>
</li>
<% end %>
<% if @start_page != @pages_total: %>
<li><a href="#" data-id="<%= @start_page + 1 %>" data-type="page">»</a></li>
<% end %>
</ul>
</div>
-->
<div class="table-overview"></div>
<div class="bulk-action hide well"></div>

View file

@ -11,7 +11,7 @@
<input type="checkbox" value="<%= ticket.id %>" name="bulk" class="pull-left"/>
</td>
<td class="span1">
<img class="thumbnail user-data" data-id="<%= ticket.customer_id %>" src="<%= ticket.customer.image %>" alt="">
<img class="thumbnail user-popover" data-id="<%= ticket.customer_id %>" src="<%= ticket.customer.image %>" alt="">
</td>
<td class="span10">
<h3><a href="#" data-type="edit"><%= ticket.title %></a> <small><%= ticket.number %> <span class="humanTimeFromNow" data-time="<%= ticket.created_at %>">?</span></small></h3>

View file

@ -0,0 +1,7 @@
<ul class="nav nav-pills nav-stacked">
<% if @items: %>
<% for item in @items: %>
<li <% if item.active: %>class="active"<% end %>><a href="<%= item.target %>"><span class="local"><%- @T(item.name) %></span><span class="badge pull-right"><%= item.count %></span></a></li>
<% end %>
<% end %>
</ul>

View file

@ -1,11 +1,15 @@
<form class="form-horizontal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h2><%- @T( @head ) %></h2>
<h2 class="modal-title"><%- @T( @head ) %></h2>
</div>
<div class="modal-body" id="form-user"></div>
<div class="modal-footer">
<button class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
<button class="btn secondary cancel"><%- @T( 'Cancel' ) %></button>
</div>
</div>
</div>
</form>

View file

@ -1,17 +1,26 @@
<div class="page-header">
<div class="row">
<div class="span12">
<div class="content-two">
<div class="sidebar">
</div>
<div class="main">
<div class="ticket-create">
<div class="page-header clearfix">
<div class="page-header-title">
<h1 class="pull-left"><%- @T( 'New Ticket' ) %></h1>
</div>
</div>
</div>
<form class="form-horizontal ticket-create">
<div class="page-content">
<form class="form-horizontal form-large">
<input type="hidden" value="" name="article_type"/>
<div class="row">
<div class="span9" id="form_create"></div>
<div class="span3"></div>
</div>
<div id="form_create"></div>
<div class="form-actions">
<button type="reset" class="btn cancel"><%- @T( 'Cancel' ) %></button>&nbsp;<button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button>
<button type="reset" class="btn btn-default cancel"><%- @T( 'Cancel' ) %></button>
<button type="submit" class="btn btn-primary submit"><%- @T( 'Create' ) %></button>
</div>
</form>
</form>
</div>
</div>
</div>
</div>

View file

@ -1,8 +1,13 @@
<div class="page-header">
<h1><%- @T( @head ) %> <small><!--<a href="#" data-type="settings" class="icon-edit">--></a></small></h1>
</div>
<div class="content-two">
<div class="sidebar">
<div class="side-overviews" id="sortable-sidebar"></div>
</div>
<div class="main">
<div class="page-header">
<h1><%- @T( @head ) %> <small><!--<a href="#" data-type="settings" class="glyphicon glyphicon-edit">--></a></small></h1>
</div>
<div class="row">
<div class="span9">
<!--
<div class="row">
@ -15,7 +20,4 @@
-->
<div class="main-overviews" id="sortable"></div>
</div>
<div class="span3">
<div class="side-overviews" id="sortable-sidebar"></div>
</div>
</div>

View file

@ -1,11 +1,9 @@
<div class="row">
<div class="span3">
<div class="span3">
<h2 class="can-move"><%- @T( @head ) %></h2>
<dl>
<% for item in @items: %>
<dt><span class="user-data" data-id="<%= item.updated_by_id %>">"<%= item.updated_by.displayName() %>"</span></dt>
<dd><%- @T( item.history_type ) %> <a href="<%- item.link %>"><%= item.type %><% if item.title: %> (<%= item.title %>)<% end %></a>.</dd>
<dt><span class="user-popover" data-id="<%= item.created_by_id %>">"<%= item.created_by.displayName() %>"</span></dt>
<dd><%- @T( item.type ) %> <a href="<%- item.link %>"><%= item.object %><% if item.title: %> (<%= item.title %>)<% end %></a> <span class="humanTimeFromNow" data-time="<%- item.created_at %>">?</span> <%- @T('ago') %>.</dd>
<% end %>
</dl>
</div>
</div>

View file

@ -1,10 +1,8 @@
<div class="row">
<div class="span3">
<div class="span3">
<h2 class="can-move"><%- @T( @head ) %></h2>
<ul>
<% for item in @items: %>
<li><span data-id="<%= item.o_id %>"><a href="<%= item.link %>"><%= item.type %> (<%= item.title %>)</a></span></li>
<% end %>
</ul>
</div>
</div>

View file

@ -1,5 +1,4 @@
<div class="row">
<div class="span3">
<div class="span3">
<h2 class="can-move"><%- @T( @head ) %></h2>
<% if @message: %>
<%- @T(@message) %>
@ -9,5 +8,4 @@
<li><a href="<%= item.link %>" title="<%= item.summary %>" target="_blank"><%= item.title %>"</a></li>
<% end %>
</ul>
</div>
</div>

View file

@ -1,12 +1,10 @@
<div class="row">
<div class="span9">
<div class="row">
<div class="span6">
<h2 class="can-move"><%- @T( @overview.name ) %> <small><a href="#" data-type="settings" class="icon-edit"></a></small></h2>
<div class="page-header clearfix">
<div class="page-header-title">
<h2 class="can-move"><%- @T( @overview.name ) %> <small><a href="#" data-type="settings" class="glyphicon glyphicon-edit"></a></small></h2>
</div>
<div class="span3">
<div class="pagination pagination-small pagination-right">
<ul>
<div class="page-header-meta">
<ul class="pagination">
<li>
<% if @start_page != 1: %>
<a href="#" data-id="<%= @start_page - 1 %>" data-type="page">«</a>
@ -29,7 +27,5 @@
</ul>
</div>
</div>
</div>
<div class="table-overview"></div>
</div>
</div>

View file

@ -1,13 +1,17 @@
<form class="form-horizontal">
<div class="modal-header">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close">&times;</a>
<h2><%- @T( 'Edit' ) %>: <%- @T( @overview.name ) %></h2>
</div>
<div class="modal-body">
<h2 class="modal-title"><%- @T( 'Edit' ) %>: <%- @T( @overview.name ) %></h2>
</div>
<div class="modal-body">
<div id="form-setting"></div>
</div>
<div class="modal-footer">
</div>
<div class="modal-footer">
<button class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
<button class="btn cancel"><%- @T( 'Cancel' ) %></button>
</div>
</div>
</div>
</form>

View file

@ -1,11 +1,16 @@
<form class="form-horizontal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close" title="<%- @Ti( 'close' ) %>">&times;</a>
<h2><%- @T( 'Edit' ) %>: <%- @T( @head ) %></h2>
<h2 class="modal-title"><%- @T( 'Edit' ) %>: <%- @T( @head ) %></h2>
</div>
<div class="modal-body" id="object_edit"></div>
<div class="modal-footer">
<button class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
<button class="btn cancel"><%- @T( 'Cancel' ) %></button>
</div>
</div>
</div>
</div>
</form>

View file

@ -1,13 +1,24 @@
<div class="page-header">
<div class="page-header clearfix">
<div class="page-header-title">
<h1><%- @T( @head ) %> <small><%- @T( 'Management' ) %></small></h1>
</div>
<div class="page-header-meta">
<% if @buttons: %>
<% for button in @buttons: %>
<a data-type="<%= button['data-type'] %>" class="btn btn-default <%= button['class'] %>"><%- @T( button.name ) %></a>
<% end %>
<% end %>
</div>
</div>
<!--
<div class="row">
<div class="span3">
<ul class="nav nav-tabs nav-stacked">
<% if @menus: %>
<% for menu in @menus: %>
<li class="<%= menu['class'] %>"><a data-type="<%= menu['data-type'] %>" ><%= menu.name %></a></li>
-->
<!--
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><%= menu.name %><b class="caret"></b></a>
@ -18,6 +29,7 @@
</ul>
</li>
-->
<!--
<% end %>
<% end %>
</ul>
@ -25,15 +37,12 @@
<% for note in @notes: %>
<p><%- @T( note ) %></p>
<% end %>
<% if @buttons: %>
<% for button in @buttons: %>
<p><a data-type="<%= button['data-type'] %>" class="btn <%= button['class'] %>"><%- @T( button.name ) %></a></p>
<% end %>
<% end %>
-->
<!--
</div>
-->
<div class="span9 table-overview"></div>
<!--
</div>
-->

View file

@ -1,11 +1,15 @@
<form class="form-horizontal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a href="#" class="close" title="<%- @Ti( 'close' ) %>">&times;</a>
<h2><%- @T( 'Neu' ) %>: <%- @T( @head ) %></h2>
<h2 class="modal-title"><%- @T( 'Neu' ) %>: <%- @T( @head ) %></h2>
</div>
<div class="modal-body" id="object_new"></div>
<div class="modal-footer">
<button class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
<button class="btn cancel"><%- @T( 'Cancel' ) %></button>
</div>
</div>
</div>
</form>

View file

@ -1,16 +1,21 @@
<div class="page-header">
<h1><%- @T( @page.head ) %> <small><%- @T( @page.sub_head ) %></small></h1>
</div>
<div class="content-two">
<div class="sidebar">
<div class="row">
<div class="span3">
<ul class="nav nav-tabs nav-stacked">
<ul class="nav nav-pills nav-stacked">
<% if @menus: %>
<% for menu in @menus: %>
<li class="<%= menu['class'] %>"><a href="<%= @page.nav %>/<%= menu.target %>" data-toggle="tabnav" data-target="<%= menu['target'] %>" ><%- @T( menu.name ) %></a></li>
<% end %>
<% end %>
</ul>
</div>
<div class="main">
<div class="page-header">
<h1><%- @T( @page.head ) %> <small><%- @T( @page.sub_head ) %></small></h1>
</div>
<div class="nav-tab-content"></div>
</div>
<div class="span9 nav-tab-content"></div>
</div>

View file

@ -1,9 +1,9 @@
<div class="control-group <%= @attribute.item_class %>">
<label class="control-label" for="<%= @attribute.id %>"><%- @T( @attribute.display ) %><% if !@attribute.null: %> *<% end %></label>
<div class="form-group <%= @attribute.item_class %>">
<label for="<%= @attribute.id %>"><%- @T( @attribute.display ) %><% if !@attribute.null: %> *<% end %></label>
<div class="controls">
<%- @item %><% if @attribute.note: %><span class="icon-question-sign" title="<%- @Ti( @attribute.note ) + ' ' %>"></span><% end %>
<% if @attribute.remove: %><span><a href="#" class="icon-minus"></a></span><% end %>
<% if @attribute.add: %><span><a href="#" class="icon-plus"></a></span><% end %>
<%- @item %><% if @attribute.note: %><span class="glyphicon glyphicon-question-sign help-message" title="<%- @Ti( @attribute.note ) + ' ' %>"></span><% end %>
<% if @attribute.remove: %><span><a href="#" class="glyphicon glyphicon-minus"></a></span><% end %>
<% if @attribute.add: %><span><a href="#" class="glyphicon glyphicon-plus"></a></span><% end %>
<span class="help-inline"></span>
<span class="help-block"><% if @attribute.help: %><%- @T( @attribute.help ) + ' ' %><% end %><%- @attribute.link %></span>
</div>

View file

@ -1,3 +1,3 @@
<input id="<%= @attribute.id %>" type="hidden" name="<%= @attribute.name %>" value="<%= @attribute.value %>" <%= @attribute.required %> />
<input id="<%= @attribute.id %>_autocompletion" type="text" name="<%= @attribute.name %>_autocompletion" value="<%= @attribute.valueShown %>" class="<%= @attribute.class %>" <%= @attribute.required %> <%= @attribute.autofocus %> <%- @attribute.autocapitalize %>/>
<input id="<%= @attribute.id %>_autocompletion" type="text" name="<%= @attribute.name %>_autocompletion" value="<%= @attribute.valueShown %>" class="form-control <%= @attribute.class %>" <%= @attribute.required %> <%= @attribute.autofocus %> <%- @attribute.autocapitalize %>/>
<input id="<%= @attribute.id %>_autocompletion_value_shown" type="hidden" name="<%= @attribute.name %>_autocompletion_value_shown" value="<%= @attribute.valueShown %>"/>

Some files were not shown because too many files have changed in this diff Show more