<%- @T('With form you can add a form to your web page which directly generates a ticket for you.') %>
+diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0fe78e959..99741dc47 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ before_script: - which ruby - env - test -n "$RNAME" && script/build/test_db_config.sh - - test -n "$RNAME" && bundle install + - test -n "$RNAME" && bundle install --jobs 8 stages: - pre @@ -229,7 +229,7 @@ test:integration:slack: - rake db:create - rake db:migrate - echo "gem 'slack-api'" >> Gemfile.local - - bundle install + - bundle install --jobs 8 - ruby -I test test/integration/slack_test.rb - rake db:drop @@ -281,6 +281,7 @@ test:integration:es_mysql: - ruby -I test/ test/integration/elasticsearch_test.rb - ruby -I test/ test/controllers/search_controller_test.rb - ruby -I test/ test/integration/report_test.rb + - ruby -I test/ test/controllers/form_controller_test.rb - rake db:drop test:integration:es_postgresql: @@ -297,6 +298,7 @@ test:integration:es_postgresql: - ruby -I test/ test/integration/elasticsearch_test.rb - ruby -I test/ test/controllers/search_controller_test.rb - ruby -I test/ test/integration/report_test.rb + - ruby -I test/ test/controllers/form_controller_test.rb - rake db:drop test:integration:zendesk_mysql: @@ -427,7 +429,7 @@ test:browser:integration:api_client_ruby: - script/build/test_startup.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 1 - git clone git@github.com:zammad/zammad-api-client-ruby.git || script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 1 1 - cd zammad-api-client-ruby - - bundle install + - bundle install --jobs 8 - export TEST_URL=http://$IP:$BROWSER_PORT - rspec || (cd .. && script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 1 1) - cd .. && script/build/test_shutdown.sh $RAILS_ENV $BROWSER_PORT $WS_PORT 0 1 diff --git a/.travis.yml b/.travis.yml index c8153f76e..510217e74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ notifications: env: - DB=mysql - DB=postgresql + - BUNDLE_JOBS=8 addons: postgresql: "9.4" apt: diff --git a/Gemfile b/Gemfile index f38dbef72..2695e13bb 100644 --- a/Gemfile +++ b/Gemfile @@ -45,7 +45,7 @@ gem 'twitter' gem 'telegramAPI' gem 'koala' gem 'mail' -gem 'email_verifier' +gem 'valid_email2' gem 'htmlentities' gem 'mime-types' diff --git a/Gemfile.lock b/Gemfile.lock index 1632ea661..5b161264b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -93,7 +93,6 @@ GEM delayed_job (>= 3.0, < 5) diff-lcs (1.2.5) diffy (3.1.0) - dnsruby (1.59.3) docile (1.1.5) domain_name (0.5.20170404) unf (>= 0.0.5, < 1.0.0) @@ -107,8 +106,6 @@ GEM em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) - email_verifier (0.1.0) - dnsruby (>= 1.5) equalizer (0.0.10) erubis (2.7.0) eventmachine (1.2.3) @@ -403,6 +400,9 @@ GEM unicorn (5.2.0) kgio (~> 2.6) raindrops (~> 0.7) + valid_email2 (1.2.17) + activemodel (>= 3.2) + mail (~> 2.5) webmock (2.3.2) addressable (>= 2.3.6) crack (>= 0.3.2) @@ -439,7 +439,6 @@ DEPENDENCIES doorkeeper eco em-websocket - email_verifier eventmachine execjs factory_girl_rails @@ -491,6 +490,7 @@ DEPENDENCIES twitter uglifier unicorn + valid_email2 webmock writeexcel zendesk_api diff --git a/app/assets/javascripts/app/controllers/_channel/email.coffee b/app/assets/javascripts/app/controllers/_channel/email.coffee index c22b4814d..99a71620e 100644 --- a/app/assets/javascripts/app/controllers/_channel/email.coffee +++ b/app/assets/javascripts/app/controllers/_channel/email.coffee @@ -531,8 +531,8 @@ class App.ChannelEmailAccountWizard extends App.WizardModal # base configureAttributesBase = [ - { name: 'realname', display: 'Organization & Department Name', tag: 'input', type: 'text', limit: 160, null: false, placeholder: 'Organization Support', autocomplete: 'new-password' }, - { name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 120, null: false, placeholder: 'support@example.com', autocapitalize: false, autocomplete: 'new-password' }, + { name: 'realname', display: 'Organization & Department Name', tag: 'input', type: 'text', limit: 160, null: false, placeholder: 'Organization Support', autocomplete: 'off' }, + { name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 120, null: false, placeholder: 'support@example.com', autocapitalize: false, autocomplete: 'off' }, { name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true }, { name: 'group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true }, ] @@ -562,7 +562,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal configureAttributesInbound = [ { name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound }, { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false }, - { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', }, + { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', }, { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true }, { name: 'options::ssl', display: 'SSL', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' }, { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' }, @@ -616,7 +616,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal if adapter is 'smtp' configureAttributesOutbound = [ { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true }, - { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', }, + { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', }, { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true }, { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false }, ] @@ -930,7 +930,7 @@ class App.ChannelEmailNotificationWizard extends App.WizardModal if adapter is 'smtp' configureAttributesOutbound = [ { name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true }, - { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password' }, + { name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off' }, { name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true }, { name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false }, ] diff --git a/app/assets/javascripts/app/controllers/_channel/form.coffee b/app/assets/javascripts/app/controllers/_channel/form.coffee index d9697b132..6955b3b60 100644 --- a/app/assets/javascripts/app/controllers/_channel/form.coffee +++ b/app/assets/javascripts/app/controllers/_channel/form.coffee @@ -3,12 +3,14 @@ class App.ChannelForm extends App.ControllerSubContent requiredPermission: 'admin.channel_formular' header: 'Form' events: - 'change form.js-params': 'updateParams' - 'keyup form.js-params': 'updateParams' + 'change form.js-paramsDesigner': 'updateParamsDesigner' + 'keyup form.js-paramsDesigner': 'updateParamsDesigner' 'change .js-formSetting input': 'toggleFormSetting' + 'change .js-paramsSetting select': 'updateGroup' elements: '.js-paramsBlock': 'paramsBlock' + '.js-paramsSetting': 'paramsSetting' '.js-formSetting input': 'formSetting' constructor: -> @@ -20,22 +22,38 @@ class App.ChannelForm extends App.ControllerSubContent render: => setting = App.Setting.get('form_ticket_create') - @html App.view('channel/form')( + + element = $(App.view('channel/form')( baseurl: window.location.origin formSetting: setting + )) + + group_id = App.Setting.get('form_ticket_create_group_id') + selection = App.UiElement.select.render( + name: 'group_id' + multiple: false + null: false + relation: 'Group' + nulloption: false + value: group_id + #class: 'form-control--small' ) + console.log('s', element.find('.js-groupSelector'), selection) + element.find('.js-groupSelector').html(selection) + + @html element @paramsBlock.each (i, block) -> hljs.highlightBlock block - @updateParams() + @updateParamsDesigner() - updateParams: -> + updateParamsDesigner: -> quote = (string) -> string = string.replace('\'', '\\\'') .replace(/\/g, '>') - params = @formParam(@$('.js-params')) + params = @formParam(@$('.js-paramsDesigner')) paramString = '' for key, value of params if value != '' @@ -63,4 +81,8 @@ class App.ChannelForm extends App.ControllerSubContent value = @formSetting.prop('checked') App.Setting.set('form_ticket_create', value) + updateGroup: => + value = @paramsSetting.find('[name=group_id]').val() + App.Setting.set('form_ticket_create_group_id', value) + App.Config.set('Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: App.ChannelForm, permission: ['admin.formular'] }, 'NavBarAdmin') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.coffee index d523501f2..067618d68 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -404,7 +404,7 @@ class App.TicketZoom extends App.Controller ) new App.TicketZoomOverviewNavigator( - el: elLocal.find('.overview-navigator') + el: elLocal.find('.js-overviewNavigatorContainer') ticket_id: @ticket_id overview_id: @overview_id ) @@ -412,13 +412,13 @@ class App.TicketZoom extends App.Controller new App.TicketZoomTitle( object_id: @ticket_id overview_id: @overview_id - el: elLocal.find('.ticket-title') + el: elLocal.find('.js-ticketTitleContainer') task_key: @task_key ) new App.TicketZoomMeta( object_id: @ticket_id - el: elLocal.find('.ticket-meta') + el: elLocal.find('.js-ticketMetaContainer') ) @attributeBar = new App.TicketZoomAttributeBar( @@ -445,7 +445,12 @@ class App.TicketZoom extends App.Controller ) @highligher = new App.TicketZoomHighlighter( - el: elLocal.find('.highlighter') + el: elLocal.find('.js-highlighterContainer') + ticket_id: @ticket_id + ) + + new App.TicketZoomSetting( + el: elLocal.find('.js-settingContainer') ticket_id: @ticket_id ) @@ -557,14 +562,16 @@ class App.TicketZoom extends App.Controller return if !@ticket currentStoreTicket = @ticket.attributes() delete currentStoreTicket.article + internal = @Config.get('ui_ticket_zoom_article_note_new_internal') currentStore = ticket: currentStoreTicket article: to: '' cc: '' + subject: '' type: 'note' body: '' - internal: 'true' + internal: internal in_reply_to: '' if @permissionCheck('ticket.customer') @@ -575,7 +582,7 @@ class App.TicketZoom extends App.Controller formCurrent: => currentParams = ticket: @formParam(@el.find('.edit')) - article: @formParam(@el.find('.article-add')) + article: @articleNew.params() # add attachments if exist attachmentCount = @$('.article-add .textBubble .attachments .attachment').length diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee index c42c5ba7a..60fd1b1bf 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee @@ -28,107 +28,9 @@ class App.TicketZoomArticleNew extends App.Controller constructor: -> super - # set possble article types - possibleArticleType = - note: true - phone: true - if @ticket && @ticket.create_article_type_id - articleTypeCreate = App.TicketArticleType.find(@ticket.create_article_type_id).name - if articleTypeCreate is 'twitter status' - possibleArticleType['twitter status'] = true - else if articleTypeCreate is 'twitter direct-message' - possibleArticleType['twitter direct-message'] = true - else if articleTypeCreate is 'email' - possibleArticleType['email'] = true - else if articleTypeCreate is 'facebook feed post' - possibleArticleType['facebook feed comment'] = true - else if articleTypeCreate is 'telegram personal-message' - possibleArticleType['telegram personal-message'] = true - if @ticket && @ticket.customer_id - customer = App.User.find(@ticket.customer_id) - if customer.email - possibleArticleType['email'] = true - - # gets referenced in @setArticleType @internalSelector = true @type = @defaults['type'] || 'note' - @articleTypes = [] - if possibleArticleType.note - internal = @Config.get('ui_ticket_zoom_article_new_internal') - - @articleTypes.push { - name: 'note' - icon: 'note' - attributes: [] - internal: internal, - features: ['attachment'] - } - if possibleArticleType.email - @articleTypes.push { - name: 'email' - icon: 'email' - attributes: ['to', 'cc'] - internal: false, - features: ['attachment'] - } - if possibleArticleType['facebook feed comment'] - @articleTypes.push { - name: 'facebook feed comment' - icon: 'facebook' - attributes: [] - internal: false, - features: [] - } - if possibleArticleType['twitter status'] - @articleTypes.push { - name: 'twitter status' - icon: 'twitter' - attributes: [] - internal: false, - features: ['body:limit', 'body:initials'] - maxTextLength: 140 - warningTextLength: 30 - } - if possibleArticleType['twitter direct-message'] - @articleTypes.push { - name: 'twitter direct-message' - icon: 'twitter' - attributes: ['to'] - internal: false, - features: ['body:limit', 'body:initials'] - maxTextLength: 10000 - warningTextLength: 500 - } - if possibleArticleType.phone - @articleTypes.push { - name: 'phone' - icon: 'phone' - attributes: [] - internal: false, - features: ['attachment'] - } - if possibleArticleType['telegram personal-message'] - @articleTypes.push { - name: 'telegram personal-message' - icon: 'telegram' - attributes: [] - internal: false, - features: ['attachment'] - maxTextLength: 10000 - warningTextLength: 5000 - } - - if @permissionCheck('ticket.customer') - @type = 'note' - @articleTypes = [ - { - name: 'note' - icon: 'note' - attributes: [] - internal: false, - features: ['attachment'] - }, - ] + @setPossibleArticleTypes() if @permissionCheck('ticket.customer') @internalSelector = false @@ -181,6 +83,114 @@ class App.TicketZoomArticleNew extends App.Controller @render() ) + setPossibleArticleTypes: => + possibleArticleType = + note: true + phone: true + if @ticket && @ticket.create_article_type_id + articleTypeCreate = App.TicketArticleType.find(@ticket.create_article_type_id).name + if articleTypeCreate is 'twitter status' + possibleArticleType['twitter status'] = true + else if articleTypeCreate is 'twitter direct-message' + possibleArticleType['twitter direct-message'] = true + else if articleTypeCreate is 'email' + possibleArticleType['email'] = true + else if articleTypeCreate is 'facebook feed post' + possibleArticleType['facebook feed comment'] = true + else if articleTypeCreate is 'telegram personal-message' + possibleArticleType['telegram personal-message'] = true + if @ticket && @ticket.customer_id + customer = App.User.find(@ticket.customer_id) + if customer.email + possibleArticleType['email'] = true + + # gets referenced in @setArticleType + @articleTypes = [] + if possibleArticleType.note + internal = @Config.get('ui_ticket_zoom_article_note_new_internal') + @articleTypes.push { + name: 'note' + icon: 'note' + attributes: [] + internal: internal, + features: ['attachment'] + } + if possibleArticleType.email + attributes = ['to', 'cc', 'subject'] + if !@Config.get('ui_ticket_zoom_article_email_subject') + attributes = ['to', 'cc'] + @articleTypes.push { + name: 'email' + icon: 'email' + attributes: attributes + internal: false, + features: ['attachment'] + } + if possibleArticleType['facebook feed comment'] + @articleTypes.push { + name: 'facebook feed comment' + icon: 'facebook' + attributes: [] + internal: false, + features: [] + } + if possibleArticleType['twitter status'] + attributes = ['body:limit', 'body:initials'] + if !@Config.get('ui_ticket_zoom_article_twitter_initials') + attributes = ['body:limit'] + @articleTypes.push { + name: 'twitter status' + icon: 'twitter' + attributes: [] + internal: false, + features: ['body:limit', 'body:initials'] + maxTextLength: 140 + warningTextLength: 30 + } + if possibleArticleType['twitter direct-message'] + attributes = ['body:limit', 'body:initials'] + if !@Config.get('ui_ticket_zoom_article_twitter_initials') + attributes = ['body:limit'] + @articleTypes.push { + name: 'twitter direct-message' + icon: 'twitter' + attributes: ['to'] + internal: false, + features: ['body:limit', 'body:initials'] + maxTextLength: 10000 + warningTextLength: 500 + } + if possibleArticleType.phone + @articleTypes.push { + name: 'phone' + icon: 'phone' + attributes: [] + internal: false, + features: ['attachment'] + } + if possibleArticleType['telegram personal-message'] + @articleTypes.push { + name: 'telegram personal-message' + icon: 'telegram' + attributes: [] + internal: false, + features: ['attachment'] + maxTextLength: 10000 + warningTextLength: 5000 + } + + if @permissionCheck('ticket.customer') + @type = 'note' + @articleTypes = [ + { + name: 'note' + icon: 'note' + attributes: [] + internal: false, + features: ['attachment'] + }, + ] + placeCaretAtEnd: (el) -> el.focus() if typeof window.getSelection isnt 'undefined' && typeof document.createRange isnt 'undefined' @@ -318,9 +328,6 @@ class App.TicketZoomArticleNew extends App.Controller params.form_id = @form_id params.content_type = 'text/html' - if !params['internal'] - params['internal'] = false - if @permissionCheck('ticket.customer') sender = App.TicketArticleSender.findByAttribute('name', 'Customer') type = App.TicketArticleType.findByAttribute('name', 'web') @@ -332,6 +339,11 @@ class App.TicketZoomArticleNew extends App.Controller params.sender_id = sender.id params.type_id = type.id + if params.internal + params.internal = true + else + params.internal = false + if params.type is 'twitter status' App.Utils.htmlRemoveRichtext(@$('[data-name=body]'), false) params.content_type = 'text/plain' @@ -478,6 +490,8 @@ class App.TicketZoomArticleNew extends App.Controller @articleNewEdit.attr('data-type', type) @$('.js-selectableTypes').addClass('hide').filter("[data-type='#{type}']").removeClass('hide') + @setPossibleArticleTypes() + # get config config = {} for articleTypeConfig in @articleTypes diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/higlighter.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/highlighter.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/ticket_zoom/higlighter.coffee rename to app/assets/javascripts/app/controllers/ticket_zoom/highlighter.coffee diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/setting.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/setting.coffee new file mode 100644 index 000000000..1103f9e3c --- /dev/null +++ b/app/assets/javascripts/app/controllers/ticket_zoom/setting.coffee @@ -0,0 +1,35 @@ +class App.TicketZoomSetting extends App.Controller + events: + 'click .js-setting': 'show' + + constructor: -> + super + return if !@permissionCheck('admin') + @render() + + render: -> + @html(App.view('ticket_zoom/setting')()) + + show: -> + new Modal() + +class Modal extends App.ControllerModal + buttonClose: true + buttonCancel: true + buttonSubmit: false + head: 'Settings' + + constructor: -> + super + + render: => + super + + post: => + new App.SettingsArea( + area: 'UI::TicketZoom' + el: @el.find('.modal-body') + ) + + content: -> + App.view('generic/page_loading')() diff --git a/app/assets/javascripts/app/lib/app_post/i18n.coffee b/app/assets/javascripts/app/lib/app_post/i18n.coffee index 1b138bf4e..3dd198b70 100644 --- a/app/assets/javascripts/app/lib/app_post/i18n.coffee +++ b/app/assets/javascripts/app/lib/app_post/i18n.coffee @@ -96,12 +96,15 @@ class _i18nSingleton extends Spine.Module # prepare locale localeToSet = localeToSet.toLowerCase() + dirToSet = 'ltr' # check if locale exists localeFound = false locales = App.Locale.all() for locale in locales if locale.locale is localeToSet + localeToSet = locale.locale + dirToSet = locale.dir localeFound = true # try aliases @@ -109,6 +112,8 @@ class _i18nSingleton extends Spine.Module for locale in locales if locale.alias is localeToSet localeToSet = locale.locale + dirToSet = locale.dir + localeFound = true # if no locale and no alias was found, try to find correct one if !localeFound @@ -118,15 +123,9 @@ class _i18nSingleton extends Spine.Module for locale in locales if locale.alias is localeToSet localeToSet = locale.locale + dirToSet = locale.dir localeFound = true - # try to find by locale - if !localeFound - for locale in locales - if locale.locale is localeToSet - localeToSet = locale.locale - localeFound = true - # check if locale need to be changed return if localeToSet is @locale @@ -136,8 +135,9 @@ class _i18nSingleton extends Spine.Module # set if not translated should be logged @_notTranslatedLog = @notTranslatedFeatureEnabled(@locale) - # set lang attribute of html tag - $('html').prop('lang', @locale.substr(0, 2) ) + # set lang and dir attribute of html tag + $('html').prop('lang', localeToSet.substr(0, 2)) + $('html').prop('dir', dirToSet) @mapString = {} App.Ajax.request( diff --git a/app/assets/javascripts/app/lib/app_post/searchable_select.coffee b/app/assets/javascripts/app/lib/app_post/searchable_select.coffee index ce1e3713e..905e02885 100644 --- a/app/assets/javascripts/app/lib/app_post/searchable_select.coffee +++ b/app/assets/javascripts/app/lib/app_post/searchable_select.coffee @@ -12,6 +12,7 @@ class App.SearchableSelect extends Spine.Controller 'mouseenter .js-back': 'highlightItem' 'shown.bs.dropdown': 'onDropdownShown' 'hidden.bs.dropdown': 'onDropdownHidden' + 'keyup .js-input': 'onKeyUp' elements: '.js-dropdown': 'dropdown' @@ -120,6 +121,10 @@ class App.SearchableSelect extends Spine.Controller $(document).off 'keydown.searchable_select' @isOpen = false + onKeyUp: => + return if @input.val().trim() isnt '' + @shadowInput.val('') + toggle: => @currentItem = null @$('[data-toggle="dropdown"]').dropdown('toggle') diff --git a/app/assets/javascripts/app/lib/base/jquery.textmodule.js b/app/assets/javascripts/app/lib/base/jquery.textmodule.js index 492229a00..6236f42d3 100644 --- a/app/assets/javascripts/app/lib/base/jquery.textmodule.js +++ b/app/assets/javascripts/app/lib/base/jquery.textmodule.js @@ -180,7 +180,7 @@ Plugin.prototype.renderBase = function() { this.$element.after('
<%- @T('With form you can add a form to your web page which directly generates a ticket for you.') %>
+