Added general support of attachments.

This commit is contained in:
Martin Edenhofer 2012-12-02 11:18:55 +01:00
parent 4e1d519575
commit 5ca42745ab
13 changed files with 129 additions and 86 deletions

View file

@ -284,6 +284,20 @@ class App.ControllerForm extends App.Controller
# textarea
else if attribute.tag is 'textarea'
item = $( App.view('generic/textarea')( attribute: attribute ) )
if attribute.upload
fileUploaderId = 'file-uploader-' + new Date().getTime() + '-' + Math.floor( Math.random() * 99999 )
item.after('<div class="' + attribute.class + '" id="' + fileUploaderId + '"></div>')
# add file uploader
u = =>
uploader = new qq.FileUploader(
element: document.getElementById(fileUploaderId)
action: '/api/ticket_attachment_new'
debug: false
params:
form_id: @form_id
)
@delay( u, 200 )
# tag
else if attribute.tag is 'tag'
@ -643,6 +657,9 @@ class App.ControllerForm extends App.Controller
App.Log.log 'ControllerForm', 'notice', 'formParam', form, param
return param
@formId: ->
formId = new Date().getTime() + Math.floor( Math.random() * 99999 )
formId.toString().substr formId.toString().length-9, 9
@disable: (form) ->
App.Log.log 'ControllerForm', 'notice', 'disable...', $(form.target).parent()

View file

@ -15,6 +15,7 @@ class Index extends App.Controller
# set title
@title 'New Ticket'
@form_id = App.ControllerForm.formId()
@fetch(params)
@navupdate '#ticket_create'
@ -105,20 +106,20 @@ class Index extends App.Controller
{ name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, filter: @edit_form, nulloption: true, relation: 'User', default: defaults['owner_id'], class: 'span7', },
{ name: 'tags', display: 'Tags', tag: 'tag', type: 'text', null: true, default: defaults['tags'], class: 'span7', },
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 200, null: false, default: defaults['subject'], class: 'span7', },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, null: false, default: defaults['body'], class: 'span7', },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 8, null: false, default: defaults['body'], class: 'span7', upload: true },
{ name: 'ticket_state_id', display: 'State', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketState', default: defaults['ticket_state_id'], translate: true, class: 'medium' },
{ name: 'ticket_priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketPriority', default: defaults['ticket_priority_id'], translate: true, class: 'medium' },
]
@html App.view('agent_ticket_create')( head: 'New Ticket' )
new App.ControllerForm(
el: @el.find('#form_create'),
model: {
configure_attributes: configure_attributes,
className: 'create',
},
autofocus: true,
form_data: @edit_form,
el: @el.find('#form_create')
form_id: @form_id
model:
configure_attributes: configure_attributes
className: 'create'
autofocus: true
form_data: @edit_form
)
# add elastic to textarea
@ -176,15 +177,14 @@ class Index extends App.Controller
# create article
params['article'] = {
from: params.customer_id_autocompletion,
to: (group && group.name) || '',
subject: params.subject,
body: params.body,
ticket_article_type_id: type.id,
ticket_article_sender_id: sender.id,
created_by_id: params.customer_id,
from: params.customer_id_autocompletion
to: (group && group.name) || ''
subject: params.subject
body: params.body
ticket_article_type_id: type.id
ticket_article_sender_id: sender.id
form_id: @form_id
}
# console.log('params', params)
object.load(params)

View file

@ -20,6 +20,7 @@ class Index extends App.Controller
@navupdate '#'
@form_id = App.ControllerForm.formId()
@edit_form = undefined
@ticket_id = params.ticket_id
@article_id = params.article_id
@ -105,7 +106,7 @@ class Index extends App.Controller
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ 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: 5, limit: 100, null: true, class: 'span7', item_class: '' },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true },
{ name: 'internal', display: 'Visability', tag: 'select', default: false, null: true, options: { true: 'internal', false: 'public' }, class: 'medium', item_class: '' },
]
if @isRole('Customer')
@ -114,7 +115,7 @@ class Index extends App.Controller
{ name: 'cc', display: 'Cc', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: true, class: 'span7', item_class: 'hide' },
{ 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: 5, limit: 100, null: true, class: 'span7', item_class: '' },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 6, limit: 100, null: true, class: 'span7', item_class: '', upload: true },
]
@html App.view('agent_ticket_zoom')(
@ -125,6 +126,7 @@ class Index extends App.Controller
new App.ControllerForm(
el: @el.find('#form-ticket-update')
form_id: @form_id
model:
configure_attributes: @configure_attributes_ticket
className: 'create'
@ -134,6 +136,7 @@ class Index extends App.Controller
new App.ControllerForm(
el: @el.find('#form-article-update')
form_id: @form_id
model:
configure_attributes: @configure_attributes_article
form_data: @edit_form
@ -158,18 +161,6 @@ class Index extends App.Controller
@scrollTo( 0, offset )
@delay( scrollTo, 100 )
@delay(@u, 200)
u: =>
uploader = new qq.FileUploader(
element: document.getElementById('file-uploader')
action: '/api/ticket_attachment_new'
params:
form: 'TicketZoom'
form_id: @ticket.id
debug: false
)
ticket_action_row: =>
# start customer info controller
@ -410,8 +401,10 @@ class Index extends App.Controller
# create article
if params['body']
article = new App.TicketArticle
params.from = @Session.get( 'firstname' ) + ' ' + @Session.get( 'lastname' )
params.from = @Session.get( 'firstname' ) + ' ' + @Session.get( 'lastname' )
params.ticket_id = @ticket.id
params.form_id = @form_id
if !params['internal']
params['internal'] = false

View file

@ -11,9 +11,10 @@ class Index extends App.Controller
# check authentication
return if !@authenticate()
# set title
@title 'New Ticket'
@form_id = App.ControllerForm.formId()
@fetch(params)
@navupdate '#customer_ticket_new'
@ -98,20 +99,20 @@ class Index extends App.Controller
{ name: 'group_id', display: 'Group', tag: 'select', multiple: false, null: false, filter: groupFilter, nulloption: true, relation: 'Group', default: defaults['group_id'], class: 'span7', },
# { name: 'owner_id', display: 'Owner', tag: 'select', multiple: false, null: true, filter: @edit_form, nulloption: true, relation: 'User', default: defaults['owner_id'], class: 'span7', },
{ name: 'subject', display: 'Subject', tag: 'input', type: 'text', limit: 100, null: false, default: defaults['subject'], class: 'span7', },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 10, null: false, default: defaults['body'], class: 'span7', },
{ name: 'body', display: 'Text', tag: 'textarea', rows: 10, null: false, default: defaults['body'], class: 'span7', upload: true },
# { name: 'ticket_state_id', display: 'State', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketState', default: defaults['ticket_state_id'], translate: true, class: 'medium' },
# { name: 'ticket_priority_id', display: 'Priority', tag: 'select', multiple: false, null: false, filter: @edit_form, relation: 'TicketPriority', default: defaults['ticket_priority_id'], translate: true, class: 'medium' },
]
@html App.view('agent_ticket_create')( head: 'New Ticket' )
new App.ControllerForm(
el: @el.find('#form_create'),
model: {
configure_attributes: configure_attributes,
className: 'create',
},
autofocus: true,
form_data: @edit_form,
el: @el.find('#form_create')
form_id: @form_id
model:
configure_attributes: configure_attributes
className: 'create'
autofocus: true
form_data: @edit_form
)
# add elastic to textarea
@ -157,13 +158,13 @@ class Index extends App.Controller
# create article
params['article'] = {
from: "#{ @Session.get('firstname') } #{ @Session.get('lastname') }",
to: (group && group.name) || '',
subject: params.subject,
body: params.body,
ticket_article_type_id: type.id,
ticket_article_sender_id: sender.id,
created_by_id: @Session.get('id'),
from: "#{ @Session.get('firstname') } #{ @Session.get('lastname') }"
to: (group && group.name) || ''
subject: params.subject
body: params.body
ticket_article_type_id: type.id
ticket_article_sender_id: sender.id
form_id: @form_id
}
# console.log('params', params)

View file

@ -485,8 +485,8 @@ qq.FileUploader = function(o){
listElement: null,
template: '<div class="qq-uploader">' +
'<div class="qq-upload-drop-area btn"><i class="icon-attachment"></i> Drop to attach files</div>' +
'<div class="qq-upload-button btn"><i class="icon-attachment"></i> Attach files</div>' +
'<div class="qq-upload-icon qq-upload-drop-area btn keepright"><i class="icon-attachment"></i> Drop to attach files</div>' +
'<div class="qq-upload-icon qq-upload-button btn keepright"><i class="icon-attachment"></i></div>' +
'<ul class="qq-upload-list"></ul>' +
'</div>',

View file

@ -1,5 +1,5 @@
class App.TicketArticle extends App.Model
@configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'ticket_id', 'ticket_article_type_id', 'ticket_article_sender_id', 'internal', 'in_reply_to'
@configure 'TicketArticle', 'from', 'to', 'cc', 'subject', 'body', 'ticket_id', 'ticket_article_type_id', 'ticket_article_sender_id', 'internal', 'in_reply_to', 'form_id'
@extend Spine.Model.Ajax
@url: '/api/ticket_articles'
@configure_attributes = [

View file

@ -81,8 +81,6 @@
<form class="form-stacked keepleft">
<div id="form-ticket-update"></div>
<div id="form-article-update"></div>
<div class="keepleft" id="file-uploader"></div>
&nbsp;
<button type="submit" class="btn btn-primary submit"><%- @T( 'Submit' ) %></button>
</form>
</div>

View file

@ -7,6 +7,27 @@ label, input, button, select, textarea {
font-size: 13px;
}
select,
textarea,
input[type="text"],
input[type="password"],
input[type="datetime"],
input[type="datetime-local"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="week"],
input[type="number"],
input[type="email"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"],
.uneditable-input {
margin-bottom: 1px;
}
.spinner {
float: left;
background:url("/assets/spinner.gif") no-repeat;
@ -351,3 +372,12 @@ footer {
text-shadow: 0 1px 0 #fff;
opacity: 0.9;
}
.qq-upload-list {
margin: 5px 10px 0px;
padding: 0;
list-style: disc;
}
.qq-upload-icon {
margin: 0px 20px;
}

View file

@ -17,22 +17,26 @@ class TicketArticlesController < ApplicationController
# POST /articles
def create
@article = Ticket::Article.new(params[:ticket_article])
form_id = params[:ticket_article][:form_id]
params[:ticket_article].delete(:form_id)
@article = Ticket::Article.new( params[:ticket_article] )
@article.created_by_id = current_user.id
@article.updated_by_id = current_user.id
# find attachments in upload cache
@article['attachments'] = Store.list(
:object => 'UploadCache::TicketZoom::' + current_user.id.to_s,
:o_id => @article.ticket_id
)
if form_id
@article['attachments'] = Store.list(
:object => 'UploadCache',
:o_id => form_id,
)
end
if @article.save
# remove attachments from upload cache
Store.remove(
:object => 'UploadCache::TicketZoom::' + current_user.id.to_s,
:o_id => @article.ticket_id
:object => 'UploadCache',
:o_id => form_id,
)
render :json => @article, :status => :created
@ -61,12 +65,8 @@ class TicketArticlesController < ApplicationController
head :ok
end
# POST /ticket_attachment/new
def attachment_new
# puts '-------'
# puts params.inspect
# store file
# content_type = request.content_type
@ -83,7 +83,7 @@ class TicketArticlesController < ApplicationController
'Content-Type' => content_type
}
Store.add(
:object => 'UploadCache::' + params[:form] + '::' + current_user.id.to_s,
:object => 'UploadCache',
:o_id => params[:form_id],
:data => request.body.read,
:filename => params[:qqfile],
@ -95,7 +95,7 @@ class TicketArticlesController < ApplicationController
:success => true,
}
end
# GET /ticket_attachment/1
def attachment

View file

@ -51,26 +51,32 @@ class TicketsController < ApplicationController
# create article if given
if params[:article]
@article = Ticket::Article.new(params[:article])
form_id = params[:article][:form_id]
params[:article].delete(:form_id)
@article = Ticket::Article.new( params[:article] )
@article.created_by_id = params[:article][:created_by_id] || current_user.id
@article.updated_by_id = params[:article][:updated_by_id] || current_user.id
@article.ticket_id = @ticket.id
# find attachments in upload cache
@article['attachments'] = Store.list(
:object => 'UploadCache::TicketZoom::' + current_user.id.to_s,
:o_id => @article.ticket_id
)
if form_id
@article['attachments'] = Store.list(
:object => 'UploadCache',
:o_id => form_id,
)
end
if !@article.save
render :json => @article.errors, :status => :unprocessable_entity
return
end
# remove attachments from upload cache
Store.remove(
:object => 'UploadCache::TicketZoom::' + current_user.id.to_s,
:o_id => @article.ticket_id
)
if params[:form_id]
Store.remove(
:object => 'UploadCache',
:o_id => form_id,
)
end
end
render :json => @ticket, :status => :created

View file

@ -17,19 +17,19 @@ class Store < ActiveRecord::Base
)
end
data['store_object_id'] = store_object.id
# check if record already exists
# store = Store.where( :store_object_id => store_object.id, :o_id => data['o_id'], ).first
# if store != nil
# return store
# end
# check real store
md5 = Digest::MD5.hexdigest( data['data'] )
data['size'] = data['data'].to_s.to_blob.bytesize
file = Store::File.where( :md5 => md5 ).first
# store attachment
if file == nil
file = Store::File.create(
@ -37,7 +37,7 @@ class Store < ActiveRecord::Base
:md5 => md5
)
end
data['store_file_id'] = file.id
data['created_by_id'] = 1
@ -50,11 +50,10 @@ class Store < ActiveRecord::Base
return store
end
def self.list(data)
# search
stores = Store.where( :store_object_id => Store::Object.where( :name => data[:object] ) ).
where( :o_id => data[:o_id] ).
stores = Store.where( :store_object_id => Store::Object.where( :name => data[:object] ), :o_id => data[:o_id].to_i ).
order('created_at ASC, id ASC')
return stores
end
@ -67,10 +66,9 @@ class Store < ActiveRecord::Base
stores.each do |store|
store.destroy
end
return 1
return true
end
class Object < ActiveRecord::Base
validates :name, :presence => true
end

View file

@ -3,7 +3,7 @@ class CreateStorage < ActiveRecord::Migration
create_table :stores do |t|
t.references :store_object, :null => false
t.references :store_file, :null => false
t.column :o_id, :integer, :null => false
t.column :o_id, :integer, :limit => 8, :null => false
t.column :preferences, :string, :limit => 2500, :null => true
t.column :size, :string, :limit => 50, :null => true
t.column :filename, :string, :limit => 250, :null => false

View file

@ -1812,7 +1812,7 @@ Translation.create( :locale => 'de', :source => "The way to communicate with us
Translation.create( :locale => 'de', :source => "or", :target => "oder", :updated_by_id => 1, :created_by_id => 1 )
Translation.create( :locale => 'de', :source => "yes", :target => "ja", :updated_by_id => 1, :created_by_id => 1 )
Translation.create( :locale => 'de', :source => "no", :target => "nein", :updated_by_id => 1, :created_by_id => 1 )
Translation.create( :locale => 'de', :source => "Attachment", :target => "Anhang", :updated_by_id => 1, :created_by_id => 1 )
Translation.create( :locale => 'de', :source => "Attachment", :target => "Anhang", :updated_by_id => 1, :created_by_id => 1 )
#Translation.create( :locale => 'de', :source => "", :target => "", :updated_by_id => 1, :created_by_id => 1 )