diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.js.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.js.coffee index a355a560d..7cec42683 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_generic.js.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_generic.js.coffee @@ -98,8 +98,9 @@ class App.ControllerGenericEdit extends App.ControllerModal class App.ControllerGenericIndex extends App.Controller events: - 'click [data-type = edit]': 'edit' - 'click [data-type = new]': 'new' + 'click [data-type=edit]': 'edit' + 'click [data-type=new]': 'new' + 'click .js-description': 'description' constructor: -> super @@ -147,13 +148,25 @@ class App.ControllerGenericIndex extends App.Controller return item ) + # show description button, only if content exists + showDescription = false + if App[ @genericObject ].description && !_.isEmpty(objects) + showDescription = true + @html App.view('generic/admin/index')( - head: @pageData.objects - notes: @pageData.notes - buttons: @pageData.buttons - menus: @pageData.menus + head: @pageData.objects + notes: @pageData.notes + buttons: @pageData.buttons + menus: @pageData.menus + showDescription: showDescription ) + # show description in content if no no content exists + if _.isEmpty(objects) && App[ @genericObject ].description + description = marked(App[ @genericObject ].description) + @$('.table-overview').html(description) + return + # append content table params = _.extend( { @@ -193,6 +206,26 @@ class App.ControllerGenericIndex extends App.Controller container: @container ) + description: (e) => + new App.ControllerGenericDescription( + description: App[ @genericObject ].description + container: @container + ) + +class App.ControllerGenericDescription extends App.ControllerModal + constructor: -> + super + @head = 'Description' + @cancel = false + @button = 'Close' + description = marked(@description) + + @show(description) + + onSubmit: (e) -> + e.preventDefault() + @hide() + class App.ControllerGenericDestroyConfirm extends App.ControllerModal constructor: -> super diff --git a/app/assets/javascripts/app/controllers/_channel/email.js.coffee b/app/assets/javascripts/app/controllers/_channel/email.js.coffee index 9e7079093..e3a2cf74e 100644 --- a/app/assets/javascripts/app/controllers/_channel/email.js.coffee +++ b/app/assets/javascripts/app/controllers/_channel/email.js.coffee @@ -45,6 +45,10 @@ class App.ChannelEmailFilter extends App.Controller template = $( '
' ) + description = ''' +With Filters you can e. g. dispatch new Tickets into certain groups or set a certain priority for Tickets of an VIP customer. +''' + new App.ControllerTable( el: template.find('.overview') model: App.PostmasterFilter @@ -52,6 +56,7 @@ class App.ChannelEmailFilter extends App.Controller bindRow: events: 'click': @edit + explanation: description ) @html template @@ -135,6 +140,13 @@ class App.ChannelEmailSignature extends App.Controller data = App.Signature.search( sortBy: 'name' ) template = $( '' ) + + description = ''' +You can define differenct signatures for each group. So you can have different email signatures for different departments. + +Once you have created a signature here, you need also to edit the groups where you want to use it. +''' + new App.ControllerTable( el: template.find('.overview') model: App.Signature @@ -142,6 +154,7 @@ class App.ChannelEmailSignature extends App.Controller bindRow: events: 'click': @edit + explanation: description ) @html template diff --git a/app/assets/javascripts/app/controllers/calendar.js.coffee b/app/assets/javascripts/app/controllers/calendar.js.coffee index 19fcc39b2..1f0a496a5 100644 --- a/app/assets/javascripts/app/controllers/calendar.js.coffee +++ b/app/assets/javascripts/app/controllers/calendar.js.coffee @@ -1,6 +1,8 @@ class Index extends App.ControllerContent events: - 'click .js-new': 'newDialog' + 'click .js-new': 'newDialog' + 'click .js-description': 'description' + constructor: -> super @@ -11,7 +13,9 @@ class Index extends App.ControllerContent App.Calendar.fetch() render: => - calendars = App.Calendar.all() + calendars = App.Calendar.search( + sortBy: 'name' + ) for calendar in calendars # get preview public holidays @@ -27,8 +31,18 @@ class Index extends App.ControllerContent public_holidays_preview[day] = calendar.public_holidays[day] calendar.public_holidays_preview = public_holidays_preview + # show description button, only if content exists + showDescription = false + if App.Calendar.description + if !_.isEmpty(calendars) + showDescription = true + else + description = marked(App[ @genericObject ].description) + @html App.view('calendar')( - calendars: calendars + calendars: calendars + showDescription: showDescription + description: description ) release: => @@ -50,4 +64,10 @@ class Index extends App.ControllerContent @$('.js-time').timepicker showMeridian: true # show am/pm + description: (e) => + new App.ControllerGenericDescription( + description: App.Calendar.description + container: @el.closest('.content') + ) + App.Config.set( 'Calendars', { prio: 2400, name: 'Calendars', parent: '#manage', target: '#manage/calendars', controller: Index, role: ['Admin'] }, 'NavBarAdmin' ) \ No newline at end of file diff --git a/app/assets/javascripts/app/controllers/text_module.js.coffee b/app/assets/javascripts/app/controllers/text_module.js.coffee index ca0eb3cdf..22e37abb1 100644 --- a/app/assets/javascripts/app/controllers/text_module.js.coffee +++ b/app/assets/javascripts/app/controllers/text_module.js.coffee @@ -21,7 +21,6 @@ class Index extends App.ControllerContent buttons: [ { name: 'New TextModule', 'data-type': 'new', class: 'btn--success' } ] - explanation: 'Create Text Modules to spend less time writing responses. TextModules can include smart variables like the users name or email address.' container: @el.closest('.content') ) diff --git a/app/assets/javascripts/app/index.js.coffee b/app/assets/javascripts/app/index.js.coffee index 4a32b39c7..903beea27 100644 --- a/app/assets/javascripts/app/index.js.coffee +++ b/app/assets/javascripts/app/index.js.coffee @@ -241,6 +241,15 @@ class App extends Spine.Controller params.Icon = (name, className = '') -> "" + # define richtext helper + params.RichText = ( string ) -> + if string.match(/@T\('/) + string = string.replace(/@T\('(.+?)'\)/g, (match, capture) -> + App.i18n.translateContent(capture) + ) + return marked(string) + App.i18n.translateContent(string) + # define template JST["app/views/#{name}"](params) template diff --git a/app/assets/javascripts/app/lib/base/marked.js b/app/assets/javascripts/app/lib/base/marked.js new file mode 100644 index 000000000..03251f3c5 --- /dev/null +++ b/app/assets/javascripts/app/lib/base/marked.js @@ -0,0 +1,1285 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +;(function() { + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^( *[-*_]){3,} *(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + table: noop, + paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, + text: /^[^\n]+/ +}; + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = replace(block.item, 'gm') + (/bull/g, block.bullet) + (); + +block.list = replace(block.list) + (/bull/g, block.bullet) + ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') + ('def', '\\n+(?=' + block.def.source + ')') + (); + +block.blockquote = replace(block.blockquote) + ('def', block.def) + (); + +block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; + +block.html = replace(block.html) + ('comment', //) + ('closed', /<(tag)[\s\S]+?<\/\1>/) + ('closing', /'
+ + (escaped ? code : escape(code, true))
+ + '\n
';
+ }
+
+ return ''
+ + (escaped ? code : escape(code, true))
+ + '\n
\n';
+};
+
+Renderer.prototype.blockquote = function(quote) {
+ return '\n' + quote + '\n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + return '
' + text + '
\n'; +}; + +Renderer.prototype.table = function(header, body) { + return '' + text + '
';
+};
+
+Renderer.prototype.br = function() {
+ return this.options.xhtml ? 'An error occured:
' + + escape(e.message + '', true) + + ''; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + sanitizer: null, + mangle: true, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer, + xhtml: false +}; + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; +} else if (typeof define === 'function' && define.amd) { + define(function() { return marked; }); +} else { + this.marked = marked; +} + +}).call(function() { + return this || (typeof window !== 'undefined' ? window : global); +}()); diff --git a/app/assets/javascripts/app/models/calendar.js.coffee b/app/assets/javascripts/app/models/calendar.js.coffee index 8de639031..759a999e0 100644 --- a/app/assets/javascripts/app/models/calendar.js.coffee +++ b/app/assets/javascripts/app/models/calendar.js.coffee @@ -5,3 +5,11 @@ class App.Calendar extends App.Model displayName: -> "#{@name} - #{@timezone}" + + @description = ''' +Ein **Kalender** wird benötigt um Eskalationen oder Auswertungen anhand von Geschäftszeiten zu berechnen. + +Definieren Sie einen **"Standard"-Kalender** welcher Systemweit gültig ist. Nur in den angegebenen Geschäftszeiten werden Eskalations-Benachrichtigungen an Agenten versendet. + +Haben Sie Kunden für welche Sie unterschiedliche Geschäftszeiten einhalten müssen, so können Sie mehrere Kalender anlegen. Die Zuweisung zu den Kunden-Tickets geschieht über die **SLAs**. +''' \ No newline at end of file diff --git a/app/assets/javascripts/app/models/organization.js.coffee b/app/assets/javascripts/app/models/organization.js.coffee index 68a60be0e..910a6cafb 100644 --- a/app/assets/javascripts/app/models/organization.js.coffee +++ b/app/assets/javascripts/app/models/organization.js.coffee @@ -14,6 +14,13 @@ class App.Organization extends App.Model 'shared', ] + @description = ''' +Mit **Organisationen** können Sie Kunden **gruppieren**. Dies hat u. a. zwei bedeutende Vorteile. + +1. Als **Agent** haben Sie nicht nur die Übersicht über die Tickets eines Kunden sondern zusätzlich die **Übersicht über die gesamte Organisation**. Z. B. über die Suchen nach der Organisation, diese per einfachen klick öffnen. +2. Als **Kunde** können Sie die **Tickets ihrer Kollegen mit einsehen** und bearbeiten (sofern die Organisation eine "teilende" ist, dies können Sie je Organisation als Parameter einstellen). +''' + uiUrl: -> '#organization/profile/' + @id @@ -36,4 +43,4 @@ class App.Organization extends App.Model id: @id class: "organization organization-popover" url: @uiUrl() - iconClass: "organization" \ No newline at end of file + iconClass: "organization" diff --git a/app/assets/javascripts/app/models/overview.js.coffee b/app/assets/javascripts/app/models/overview.js.coffee index 7e699df40..9fc733d37 100644 --- a/app/assets/javascripts/app/models/overview.js.coffee +++ b/app/assets/javascripts/app/models/overview.js.coffee @@ -144,3 +144,9 @@ class App.Overview extends App.Model 'role', 'prio', ] + + @description = ''' +Übersichten können Sie Ihren Agenten und Kunden bereitstellen. Sie dienen als eine Art Arbeitslisten von Aufgaben welche der Agent abarbeiten soll. + +Sie können auch individuelle Übersichten für einzelne Agenten oder agenten Gruppen erstellen. +''' diff --git a/app/assets/javascripts/app/models/sla.js.coffee b/app/assets/javascripts/app/models/sla.js.coffee index cebe59f3e..e621675a7 100644 --- a/app/assets/javascripts/app/models/sla.js.coffee +++ b/app/assets/javascripts/app/models/sla.js.coffee @@ -18,3 +18,11 @@ class App.Sla extends App.Model @configure_overview = [ 'name', ] + + @description = ''' +**Service-Level-Agreements**, abgekürzt **SLAs**, unterstützen Sie gegenüber Kunden gewisse zeitliche Reaktionen einzuhalten. Somit können Sie z. B. sagen Kunden sollen immer nach spätestens 8 Stunden eine Reaktion von Ihnen bekommen. Falls es zu einer drohenden Unterschreitung oder einer Unterschreitung kommt, weißt Zammad Sie auf solche Ereignisse hin. + +Es können **Reaktionszeit** (Zeit zwischen Erstellung eines Tickets und erster Reaktion eines Agenten), **Aktualisierungszeit** (Zeit zwischen Nachfrage eines Kunden und Reaktion eines Agenten) und **Lösungszeit** (Zeit zwischen Erstellung und schließen eines Tickets) definiert werden. + +Drohenden Unterschreitungen oder Unterschreitungen werden in einer eigenen Ansicht in den Übersichten angezeigt. Zudem können **E-Mail Benachrichtigungen** konfiguriert werden. +''' \ No newline at end of file diff --git a/app/assets/javascripts/app/models/text_module.js.coffee b/app/assets/javascripts/app/models/text_module.js.coffee index e43e68315..94be8a362 100644 --- a/app/assets/javascripts/app/models/text_module.js.coffee +++ b/app/assets/javascripts/app/models/text_module.js.coffee @@ -15,3 +15,22 @@ class App.TextModule extends App.Model 'keywords', 'content', ] + + @description = ''' +Create Text Modules to **spend less time writing responses**. TextModules can include smart variables like the users name or email address. + +Examples of snippets are: + +* Hallo Frau <%= @ticket.customer.lastname %>, +* Hallo Herr <%= @ticket.customer.lastname %>, +* Hallo <%= @ticket.customer.firstname %>, + +Of course you can also use multi line snippets. + +Available objects are: +* @ticket (e. g. @ticket.state, @ticket.group) +* @ticket.customer (e. g. @ticket.customer.firstname, @ticket.customer.lastname) +* @ticket.owner (e. g. @ticket.owner.firstname, @ticket.owner.lastname) +* @ticket.organization (e. g. @ticket.organization.name) + +''' \ No newline at end of file diff --git a/app/assets/javascripts/app/views/calendar.jst.eco b/app/assets/javascripts/app/views/calendar.jst.eco index b56e57595..338994e79 100644 --- a/app/assets/javascripts/app/views/calendar.jst.eco +++ b/app/assets/javascripts/app/views/calendar.jst.eco @@ -4,10 +4,17 @@ +<% if _.isEmpty(@calendars): %> +<%- @description %> +<% end %> + <% for calendar in @calendars: %>
<%= @Ti( @explanation ) %>
\ No newline at end of file +<%= @T(@explanation) %>
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/generic/admin/index.jst.eco b/app/assets/javascripts/app/views/generic/admin/index.jst.eco index 3e20007da..69c72e481 100644 --- a/app/assets/javascripts/app/views/generic/admin/index.jst.eco +++ b/app/assets/javascripts/app/views/generic/admin/index.jst.eco @@ -3,10 +3,13 @@