Browse Source

Init form feature.

Martin Edenhofer 9 years ago
parent
commit
23001f9921

+ 15 - 0
app/assets/javascripts/app/controllers/_channel/form.js.coffee

@@ -0,0 +1,15 @@
+class App.ChannelForm extends App.Controller
+  constructor: ->
+    super
+    @title 'Form'
+    @render()
+
+    new App.SettingsArea(
+      el:   @el.find('.js-settings')
+      area: 'Form::Base'
+    )
+
+  render: ->
+    @html App.view('channel/form')(
+      baseurl: window.location.origin
+    )

+ 5 - 4
app/assets/javascripts/app/controllers/channel.js.coffee

@@ -6,8 +6,9 @@
 #App.Config.set( 'Channels', { prio: 2500, parent: '#admin', name: 'Channels', target: '#channels', role: ['Admin'] }, 'NavBar' )
 
 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' )
+App.Config.set( 'Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: App.ChannelForm, role: ['Admin'] }, 'NavBarAdmin' )
+App.Config.set( 'Email', { prio: 3000, name: 'Email', parent: '#channels', target: '#channels/email', controller: App.ChannelEmail, role: ['Admin'] }, 'NavBarAdmin' )
+App.Config.set( 'Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, role: ['Admin'] }, 'NavBarAdmin' )
+App.Config.set( 'Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: App.ChannelTwitter, role: ['Admin'] }, 'NavBarAdmin' )
+App.Config.set( 'Facebook', { prio: 6000, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: App.ChannelFacebook, role: ['Admin'] }, 'NavBarAdmin' )
 

+ 42 - 0
app/assets/javascripts/app/views/channel/form.jst.eco

@@ -0,0 +1,42 @@
+<div class="page-header">
+  <div class="page-header-title">
+    <h1><%- @T('Form') %> <small></small></h1>
+  </div>
+</div>
+<div>
+  <p><%- @T('With form you can add a formular to your web page witch directly generates a Ticket for you.') %></p>
+
+  <div class="js-settings"></div>
+
+  <h2><%- @T('Settings') %></h2>
+  <table class="settings-list">
+    <thead>
+      <tr>
+        <th style="white-space: nowrap;"><%- @T('Option') %></th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td><label><input type="checkbox" name="debug"/> <%- @T('Debug') %></label></td>
+      </tr>
+      <tr>
+        <td><label><input type="checkbox" name="modal"/> <%- @T('Modal Dialog') %></label></td>
+      </tr>
+      <tr>
+        <td><label><input type="checkbox"/> <%- @T('Debug') %></label></td>
+      </tr>
+    </tbody>
+  </table>
+
+  <p><%- @T('You need to add the following Java Script code snipped to your web page') %>:
+
+  <pre>
+&lt;script id="zammad_form_script" src="<%= @baseurl %>/assets/form/form.js"&gt;&lt;/script&gt;
+&lt;script&gt;
+$('#feedback-form').zammad_form({
+  lang: 'de-de',
+  debug: true,
+  modal: false,
+});
+&lt;/script&gt;</pre>
+</div>

+ 99 - 0
app/controllers/form_controller.rb

@@ -0,0 +1,99 @@
+# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
+
+class FormController < ApplicationController
+
+  def config
+    return if !enabled?
+
+    api_path  = Rails.configuration.api_path
+    http_type = Setting.get('http_type')
+    fqdn      = Setting.get('fqdn')
+
+    endpoint = "#{http_type}://#{fqdn}#{api_path}/form_submit"
+
+    config = {
+      enabled:  Setting.get('form_ticket_create'),
+      endpoint: endpoint,
+    }
+
+    render json: config, status: :ok
+  end
+
+  def submit
+    return if !enabled?
+
+    # validate input
+    errors = {}
+    if !params[:name] || params[:name].empty?
+      errors['name'] = 'required'
+    end
+    if !params[:email] || params[:email].empty?
+      errors['email'] = 'required'
+    end
+    if params[:email] !~ /@/
+      errors['email'] = 'invalid'
+    end
+    if !params[:body] || params[:body].empty?
+      errors['body'] = 'required'
+    end
+
+    if errors && !errors.empty?
+      render json: {
+        errors: errors
+      }, status: :ok
+      return
+    end
+
+    name = params[:name].strip
+    email = params[:email].strip.downcase
+
+    customer = User.find_by(email: email)
+    if !customer
+      roles = Role.where( name: 'Customer' )
+      customer = User.create(
+        firstname: name,
+        lastname: '',
+        email: email,
+        password: '',
+        active: true,
+        roles: roles,
+        updated_by_id: 1,
+        created_by_id: 1,
+      )
+    end
+
+    ticket = Ticket.create(
+      group_id: 1,
+      customer_id: customer.id,
+      title: '',
+      state_id: Ticket::State.find_by( name: 'new' ).id,
+      priority_id: Ticket::Priority.find_by( name: '2 normal' ).id,
+      updated_by_id: customer.id,
+      created_by_id: customer.id,
+    )
+
+    article = Ticket::Article.create(
+      ticket_id: ticket.id,
+      type_id: Ticket::Article::Type.find_by( name: 'web' ).id,
+      sender_id: Ticket::Article::Sender.find_by( name: 'Customer' ).id,
+      body: params[:body],
+      from: email,
+      subject: '',
+      internal: false,
+      updated_by_id: customer.id,
+      created_by_id: customer.id,
+    )
+
+    result = {}
+    render json: result, status: :ok
+  end
+
+  private
+
+  def enabled?
+    return true if Setting.get('form_ticket_create')
+    response_access_deny
+    false
+  end
+
+end

+ 8 - 0
config/routes/form.rb

@@ -0,0 +1,8 @@
+Zammad::Application.routes.draw do
+  api_path = Rails.configuration.api_path
+
+  # forms
+  match api_path + '/form_submit',      to: 'form#submit',    via: :post
+  match api_path + '/form_config',      to: 'form#config',    via: :get
+
+end

+ 30 - 0
db/migrate/20150810000001_update_form.rb

@@ -0,0 +1,30 @@
+class UpdateForm < ActiveRecord::Migration
+  def up
+
+    Setting.create_if_not_exists(
+      title: 'Enable Ticket creation',
+      name: 'form_ticket_create',
+      area: 'Form::Base',
+      description: 'Defines if ticket can get created via web form.',
+      options: {
+        form: [
+          {
+            display: '',
+            null: true,
+            name: 'form_ticket_create',
+            tag: 'boolean',
+            options: {
+              true  => 'yes',
+              false => 'no',
+            },
+          },
+        ],
+      },
+      state: false,
+      frontend: false,
+      updated_by_id: 1,
+      created_by_id: 1,
+    )
+
+  end
+end

+ 23 - 0
db/seeds.rb

@@ -992,6 +992,29 @@ Setting.create_if_not_exists(
   frontend: true
 )
 
+Setting.create_if_not_exists(
+  title: 'Enable Ticket creation',
+  name: 'form_ticket_create',
+  area: 'Form::Base',
+  description: 'Defines if ticket can get created via web form.',
+  options: {
+    form: [
+      {
+        display: '',
+        null: true,
+        name: 'form_ticket_create',
+        tag: 'boolean',
+        options: {
+          true  => 'yes',
+          false => 'no',
+        },
+      },
+    ],
+  },
+  state: false,
+  frontend: false,
+)
+
 Setting.create_if_not_exists(
   title: 'Sender Format',
   name: 'ticket_define_email_from',

+ 19 - 0
public/assets/form/form.css

@@ -0,0 +1,19 @@
+.zammad-form {
+  width: 300px;
+}
+
+.zammad-form .form-group {
+  margin-bottom: 15px;
+}
+
+.zammad-form .form-control {
+  display: block;
+  width: 100%;
+}
+
+.zammad-form .has-error .form-control {
+  border-color: #a94442;
+}
+.zammad-form .has-error label {
+  color: #a94442;
+}

+ 19 - 0
public/assets/form/form.html

@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Example Form</title>
+</head>
+<body>
+
+<div id="example_form"></div>
+
+<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
+<script id="zammad_form_script" src="http://localhost:3000/assets/form/form.js"></script>
+
+<script>
+ $('#example_form').zammad_form({debug:true});
+</script>
+
+
+</body>
+</html>

+ 179 - 0
public/assets/form/form.js

@@ -0,0 +1,179 @@
+(function ($) {
+
+/*
+  provides feedback form for zammad
+*/
+
+  var pluginName = 'zammad_form',
+  defaults = {
+    debug: false,
+    loadCss: true,
+  };
+
+  function Plugin( element, options ) {
+    this.element  = element;
+    this.$element = $(element)
+
+    this.options = $.extend( {}, defaults, options) ;
+
+    this._defaults = defaults;
+    this._name     = pluginName;
+
+    this._endpoint_config = '/api/v1/form_config'
+    this._script_location = '/assets/form/form.js'
+
+    this._config  = {}
+
+    this.attributes = [
+      {
+        display: 'Name',
+        name: 'name',
+        tag: 'input',
+        type: 'text',
+        placeholder: 'Your Name',
+      },
+      {
+        display: 'Email',
+        name: 'email',
+        tag: 'input',
+        type: 'email',
+        placeholder: 'Your Email',
+      },
+      {
+        display: 'Message',
+        name: 'body',
+        tag: 'textarea',
+        placeholder: 'Your Message...',
+      },
+    ]
+
+    this.init();
+  }
+
+
+  Plugin.prototype.init = function () {
+    var _this = this,
+      src = document.getElementById("zammad_form_script").src,
+      endpoint_config = src.replace(this._script_location, this._endpoint_config)
+
+    _this.log('init')
+
+    if (_this.options.loadCss) {
+      _this.loadCss('form.css')
+    }
+
+    _this.log('endpoint_config: ' + endpoint_config)
+
+    // load config
+    $.ajax({
+      url: endpoint_config,
+    }).done(function(data) {
+      _this.log('config:', data)
+      _this._config = data
+      _this.render()
+    }).fail(function() {
+      alert('Faild to load form config!')
+    });
+
+    // bind form submit
+    this.$element.on('submit', function (e) {
+      e.preventDefault()
+      _this.submit()
+      return true
+    })
+  }
+
+  // load css
+  Plugin.prototype.loadCss = function(filename) {
+    if (document.createStyleSheet) {
+      document.createStyleSheet(filename)
+    }
+    else {
+      $('<link rel="stylesheet" type="text/css" href="' + filename + '" />').appendTo('head')
+    }
+  }
+
+  // send
+  Plugin.prototype.submit = function() {
+    var _this = this
+
+    _this.log('submit form', _this.getParams())
+
+    $.ajax({
+      method: 'post',
+      url: _this._config.endpoint,
+      data: _this.getParams(),
+    }).done(function(data) {
+      _this.log('ok done', _this._config.endpoint)
+
+      // removed errors
+      _this.$element.find('.has-error').removeClass('has-error')
+
+      // set errors
+      if (data.errors) {
+        $.each(data.errors, function( key, value ) {
+          _this.$element.find('[name=' + key + ']').closest('.form-group').addClass('has-error')
+        })
+        return
+      }
+
+      // ticket has been created
+      _this.thanks()
+    }).fail(function() {
+      alert('Faild to submit form!')
+    });
+  }
+
+  // get params
+  Plugin.prototype.getParams = function() {
+    var _this = this,
+      params = {}
+
+    $.each( _this.$element.find('form').serializeArray(), function( index, item ) {
+      params[item.name] = item.value
+    })
+    return params
+  }
+
+  // render form
+  Plugin.prototype.render = function(e) {
+    var form = $('<form class="zammad-form"></form>')
+    $.each(this.attributes, function( index, value ) {
+      var item = $('<div class="form-group"><label>' + value.display + '</label></div>')
+      if (value.tag == 'input') {
+        item.append('<input class="form-control" name="' + value.name + '" type="' + value.type + '" placeholder="' + value.placeholder + '">')
+      }
+      else if (value.tag == 'textarea') {
+        item.append('<textarea class="form-control" name="' + value.name + '" placeholder="' + value.placeholder + '"></textarea>')
+      }
+      form.append(item)
+    })
+    form.append('<button type="submit">' + 'Submit' + '</button')
+    this.$element.html(form)
+    return form
+  }
+
+  // thanks
+  Plugin.prototype.thanks = function(e) {
+    var form = $('<div>Thank you for your inquery!</div>')
+    this.$element.html(form)
+    return form
+  }
+
+  // log method
+  Plugin.prototype.log = function() {
+    if (this.options.debug) {
+      console.log(this._name, arguments)
+    }
+  }
+
+  $.fn[pluginName] = function ( options ) {
+    return this.each(function () {
+      if (!$.data(this, 'plugin_' + pluginName)) {
+        $.data(this, 'plugin_' + pluginName,
+        new Plugin( this, options ));
+      }
+    });
+  }
+
+}(jQuery));