From 592e961e70963e7d42a1974271a6f1dc67c12ef0 Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 16:18:15 +0200 Subject: [PATCH 01/17] most work done on the install script --- script/install.sh | 92 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 12 deletions(-) diff --git a/script/install.sh b/script/install.sh index aee26438a..0db349dcb 100644 --- a/script/install.sh +++ b/script/install.sh @@ -1,15 +1,83 @@ #!/bin/bash -get_distro(){ - arch=$(uname -m) - kernel=$(uname -r) - if [ -f /etc/lsb-release ]; then - os=$(lsb_release -s -d) - elif [ -f /etc/debian_version ]; then - os="Debian $(cat /etc/debian_version)" - elif [ -f /etc/redhat-release ]; then - os=`cat /etc/redhat-release` - else - os="$(uname -s) $(uname -r)" - fi + +USER=zammad +REPOURL=git@github.com:martini/zammad.git +DBNAME=zammad +DBUSER=zammad + +function check_requirements() { + items="git useradd sudo getent curl bash gcc make svn apg" + for item in $items + do + which $item > /dev/null + if [ $? -ne 0 ]; then + echo Please install $item and start this script again. + exit 1 + fi + done } +check_requirements + +# +# @TODO Should the mysql user be created? +# @TODO Install Elasticsearch? +# @TODO Should the script create a VirtualHost or a config file to include for apache/nginx? +# + +# +# Check for zammad user and create if needed +# +id -u "${USER}" > /dev/null 2>&1 +if [ $? -ne 0 ]; then + useradd -c 'user running zammad' -m -s /bin/bash $USER +fi + +# +# find the user's homedir and primary group name +# +HOMEDIR=$(getent passwd $USER | cut -d: -f 6) +GROUP=$(id -gn $USER) + +cd "${HOMEDIR}" +sudo -u "${USER}" -H git clone $REPOURL zammad +cd zammad +LATEST=$(git tag --list|sort|tail -1) +git checkout tags/"${LATEST}" +chown -R "${USER}":"${GROUP}" . + +# +# RVM +# +sudo -u "${USER}" -H bash -c 'curl -sSL https://get.rvm.io | bash -s stable' + + +# +# install Ruby +# +sudo -u "${USER}" -H bash -l -c 'rvm install 2.1.2' +sudo -u "${USER}" -H bash -l -c 'rvm alias create default 2.1.2' + +# +# after rvm requirements +# Installing required packages: gawk, g++, libreadline6-dev, zlib1g-dev, libssl-dev, libyaml-dev, libsqlite3-dev, sqlite3, autoconf, libgdbm-dev, libncurses5-dev, automake, libtool, bison, pkg-config, libffi-dev................ + + +sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && gem install rails --no-ri --no-rdoc' +sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && bundle install' + +DBPASS=$(apg -x8|head -1) +echo Password $DBPASS +mysql -e "GRANT ALL ON ${DBNAME}.* to '${DBUSER}'@'localhost' IDENTIFIED BY '$DBPASS'"; +sudo -u $USER -H cp ${HOMEDIR}/zammad/config/database.yml.dist ${HOMEDIR}/zammad/config/database.yml +sudo -u $USER -H sed -i s/some_pass/${DBPASS}/g ${HOMEDIR}/zammad/config/database.yml +sudo -u $USER -H sed -i s/some_user/${DBUSER}/g ${HOMEDIR}/zammad/config/database.yml +sudo -u $USER -H sed -i s/zammad_prod/zammad/g ${HOMEDIR}/zammad/config/database.yml + +# +# +# +sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:create' +sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:migrate' +sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:seed' +sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake assets:precompile' From b3ef1b53ac4aab3836812fbf2687560037f4e5e0 Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 16:25:24 +0200 Subject: [PATCH 02/17] added 1st os detection --- script/install.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/script/install.sh b/script/install.sh index 0db349dcb..5c658e92b 100644 --- a/script/install.sh +++ b/script/install.sh @@ -17,8 +17,23 @@ function check_requirements() { done } +function check_os() +{ + # Debian + if [ -f /etc/debian_version ]; then + MAJOR=$(cut -d. /etc/debian_version -f1) + if [ $MAJOR -lt 7 ]; then + echo Please check the supported operating systems + exit 1 + fi + fi +} + check_requirements +check_os + + # # @TODO Should the mysql user be created? # @TODO Install Elasticsearch? @@ -81,3 +96,4 @@ sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:cre sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:migrate' sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:seed' sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake assets:precompile' + From 1abb352843fcf4a475094d676e50908a293c02b3 Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 17:40:36 +0200 Subject: [PATCH 03/17] initial init script --- script/init.d/zammad | 118 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100755 script/init.d/zammad diff --git a/script/init.d/zammad b/script/init.d/zammad new file mode 100755 index 000000000..4978722e0 --- /dev/null +++ b/script/init.d/zammad @@ -0,0 +1,118 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: zammad +# Required-Start: $local_fs $remote_fs $network $syslog +# Required-Stop: $local_fs $remote_fs $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Zammad application +# Description: Zammad application +### END INIT INFO + + +APP_ROOT="/home/zammad/zammad" +PID_PATH="$APP_ROOT/tmp/pids" +WEB_SERVER_PID="$PID_PATH/puma.pid" +SOCKET_PATH="$APP_ROOT/tmp/sockets" +SOCKET_FILE="$SOCKET_PATH/zammad.socket" + +APP_USER="zammad" +DAEMON_OPTS="-p 3000 -d -e production --pidfile $WEB_SERVER_PID" + +NAME="zammad" +DESC="Zammad application" + + +check_daemons() { + PUMA_PID=-1 + PUMA_OK=1 + if [ -f $WEB_SERVER_PID ]; then + PUMA_PID=$(pgrep -F $WEB_SERVER_PID) + PUMA_OK=$? + fi + MISC_OK=0 + MISC_PID=0 +} + +execute() { + sudo -u $APP_USER -H bash -l -c "$1" +} + +start() { + cd $APP_ROOT + check_daemons + if [ $PUMA_OK -eq 0 ]; then + echo Puma is already running + exit 1 + fi + execute "RAILS_ENV=production puma $DAEMON_OPTS" + echo "$DESC started" +} + +stop() { + cd $APP_ROOT + check_daemons + if [ "$PUMA_OK" -eq 0 ]; then + ## Program is running, stop it. + kill -QUIT $PUMA_PID + test -f "$WEB_SERVER_PID" && rm -f "$WEB_SERVER_PID" + echo "$DESC stopped" + else + ## Program is not running, exit with error. + echo "Error! $DESC is not started!" + exit 1 + fi +} + +restart() { + cd $APP_ROOT + check_daemons + if [ "$PUMA_OK" -ne 0 -a "$MISC" -ne 0 ]; then + echo "Restarting $DESC..." + kill -USR2 $PUMA_PID + echo "$DESC restarted." + else + echo "Error, $NAME not running!" + exit 1 + fi +} + +status() { + cd $APP_ROOT + check_daemons + if [ $PUMA_OK -eq 0 ]; then + echo "$DESC / Puma with PID $PUMA_PID is running." + else + echo "$DESC is not running." + exit 1 + fi +} + +## Check to see if we are running as root first. +## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html +if [ "$(id -u)" != "0" ]; then + echo "This script must be run as root" + exit 1 +fi + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + status) + status + ;; + *) + echo "Usage: service zammad {start|stop|restart|reload}" >&2 + exit 1 + ;; +esac + +exit 0 From 8229e257af7849eba2d225398f1689102f50ec3f Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 17:44:54 +0200 Subject: [PATCH 04/17] we need it for install.sh in prod mode --- Gemfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index d8b882f06..dfdb88ac2 100644 --- a/Gemfile +++ b/Gemfile @@ -37,9 +37,9 @@ gem 'daemons' gem 'simple-rss' # e. g. on linux we need a javascript execution -# gem 'libv8', '~> 3.11.8' -# gem 'execjs' -# gem 'therubyracer' +gem 'libv8', '~> 3.11.8' +gem 'execjs' +gem 'therubyracer' # e. g. for mysql you need to load mysql gem 'mysql2' From 1c038f2cc4211dfa3a6548643854f31e5534399f Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 17:55:42 +0200 Subject: [PATCH 05/17] fully operating for puma --- script/init.d/zammad | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/script/init.d/zammad b/script/init.d/zammad index 4978722e0..eedc6d9cb 100755 --- a/script/init.d/zammad +++ b/script/init.d/zammad @@ -31,8 +31,6 @@ check_daemons() { PUMA_PID=$(pgrep -F $WEB_SERVER_PID) PUMA_OK=$? fi - MISC_OK=0 - MISC_PID=0 } execute() { @@ -68,7 +66,7 @@ stop() { restart() { cd $APP_ROOT check_daemons - if [ "$PUMA_OK" -ne 0 -a "$MISC" -ne 0 ]; then + if [ "$PUMA_OK" -eq 0 ]; then echo "Restarting $DESC..." kill -USR2 $PUMA_PID echo "$DESC restarted." From 69bb7691bcd36ee5f16242bda216cd9841a91a63 Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 18:28:18 +0200 Subject: [PATCH 06/17] added websocket server --- script/init.d/zammad | 47 +++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/script/init.d/zammad b/script/init.d/zammad index eedc6d9cb..359baae6d 100755 --- a/script/init.d/zammad +++ b/script/init.d/zammad @@ -14,11 +14,11 @@ APP_ROOT="/home/zammad/zammad" PID_PATH="$APP_ROOT/tmp/pids" WEB_SERVER_PID="$PID_PATH/puma.pid" -SOCKET_PATH="$APP_ROOT/tmp/sockets" -SOCKET_FILE="$SOCKET_PATH/zammad.socket" +WEBSOCKET_SERVER_PID="$PID_PATH/websocket.pid" APP_USER="zammad" -DAEMON_OPTS="-p 3000 -d -e production --pidfile $WEB_SERVER_PID" +PUMA_OPTS="-p 3000 -d -e production --pidfile $WEB_SERVER_PID" +WEBSOCKET_OPTS="-d" NAME="zammad" DESC="Zammad application" @@ -31,6 +31,12 @@ check_daemons() { PUMA_PID=$(pgrep -F $WEB_SERVER_PID) PUMA_OK=$? fi + WEBSOCKET_PID=-1 + WEBSOCKET_OK=1 + if [ -f $WEBSOCKET_SERVER_PID ]; then + WEBSOCKET_PID=$(pgrep -F $WEBSOCKET_SERVER_PID) + WEBSOCKET_OK=$? + fi } execute() { @@ -42,19 +48,30 @@ start() { check_daemons if [ $PUMA_OK -eq 0 ]; then echo Puma is already running - exit 1 + else + execute "RAILS_ENV=production puma $PUMA_OPTS" + fi + if [ $WEBSOCKET_OK -eq 0 ]; then + echo Websocket server is already running + else + execute "RAILS_ENV=production script/websocket-server.rb start $WEBSOCKET_OPTS" fi - execute "RAILS_ENV=production puma $DAEMON_OPTS" echo "$DESC started" } stop() { cd $APP_ROOT check_daemons - if [ "$PUMA_OK" -eq 0 ]; then + if [ "$PUMA_OK" -eq 0 -o $WEBSOCKET_OK -eq 0 ]; then ## Program is running, stop it. - kill -QUIT $PUMA_PID - test -f "$WEB_SERVER_PID" && rm -f "$WEB_SERVER_PID" + if [ $PUMA_OK -eq 0 ]; then + kill -QUIT $PUMA_PID + test -f "$WEB_SERVER_PID" && rm -f "$WEB_SERVER_PID" + fi + if [ $WEBSOCKET_OK -eq 0 ]; then + execute "RAILS_ENV=production script/websocket-server.rb stop $WEBSOCKET_OPTS" + test -f "$WEBSOCKET_SERVER_PID" && rm -f "$WEBSOCKET_SERVER_PID" + fi echo "$DESC stopped" else ## Program is not running, exit with error. @@ -66,9 +83,11 @@ stop() { restart() { cd $APP_ROOT check_daemons - if [ "$PUMA_OK" -eq 0 ]; then + if [ "$PUMA_OK" -eq 0 -o WEBSOCKET_OK -eq 0 ]; then echo "Restarting $DESC..." kill -USR2 $PUMA_PID + execute "RAILS_ENV=production script/websocket-server.rb stop $WEBSOCKET_OPTS" + execute "RAILS_ENV=production script/websocket-server.rb start $WEBSOCKET_OPTS" echo "$DESC restarted." else echo "Error, $NAME not running!" @@ -80,10 +99,14 @@ status() { cd $APP_ROOT check_daemons if [ $PUMA_OK -eq 0 ]; then - echo "$DESC / Puma with PID $PUMA_PID is running." + echo "$DESC / Puma (pid $PUMA_PID) is running." else - echo "$DESC is not running." - exit 1 + echo "$DESC / Puma (pid $PUMA_PID) is not running." + fi + if [ $WEBSOCKET_OK -eq 0 ]; then + echo "Websocket server (pid $WEBSOCKET_PID) is running." + else + echo "Websocket server (pid $WEBSOCKET_PID) is not running." fi } From 3c48ba64204bbf54bc3238c9ddcff542c7fa7a63 Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 18:34:21 +0200 Subject: [PATCH 07/17] added scheduler to init script --- script/init.d/zammad | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/script/init.d/zammad b/script/init.d/zammad index 359baae6d..a0470b145 100755 --- a/script/init.d/zammad +++ b/script/init.d/zammad @@ -15,10 +15,12 @@ APP_ROOT="/home/zammad/zammad" PID_PATH="$APP_ROOT/tmp/pids" WEB_SERVER_PID="$PID_PATH/puma.pid" WEBSOCKET_SERVER_PID="$PID_PATH/websocket.pid" +SCHEDULER_SERVER_PID="$PID_PATH/websocket.pid" APP_USER="zammad" PUMA_OPTS="-p 3000 -d -e production --pidfile $WEB_SERVER_PID" WEBSOCKET_OPTS="-d" +SCHEDULER_OPTS="" NAME="zammad" DESC="Zammad application" @@ -37,6 +39,12 @@ check_daemons() { WEBSOCKET_PID=$(pgrep -F $WEBSOCKET_SERVER_PID) WEBSOCKET_OK=$? fi + SCHEDULER_PID=1 + SCHEDULER_OK=1 + if [ -f $SCHEDULER_SERVER_PID ]; then + SCHEDULER_PID=$(pgrep -F $SCHEDULER_SERVER_PID) + SCHEDULER_OK=$? + fi } execute() { @@ -56,6 +64,7 @@ start() { else execute "RAILS_ENV=production script/websocket-server.rb start $WEBSOCKET_OPTS" fi + execute "RAILS_ENV=production script/scheduler.rb start $SCHEDULER_OPTS" echo "$DESC started" } @@ -72,6 +81,7 @@ stop() { execute "RAILS_ENV=production script/websocket-server.rb stop $WEBSOCKET_OPTS" test -f "$WEBSOCKET_SERVER_PID" && rm -f "$WEBSOCKET_SERVER_PID" fi + execute "RAILS_ENV=production script/scheduler.rb stop $SCHEDULER_OPTS" echo "$DESC stopped" else ## Program is not running, exit with error. @@ -88,6 +98,7 @@ restart() { kill -USR2 $PUMA_PID execute "RAILS_ENV=production script/websocket-server.rb stop $WEBSOCKET_OPTS" execute "RAILS_ENV=production script/websocket-server.rb start $WEBSOCKET_OPTS" + execute "RAILS_ENV=production script/scheduler.rb restart $SCHEDULER_OPTS" echo "$DESC restarted." else echo "Error, $NAME not running!" @@ -108,6 +119,7 @@ status() { else echo "Websocket server (pid $WEBSOCKET_PID) is not running." fi + execute "RAILS_ENV=production script/scheduler.rb status $SCHEDULER_OPTS" } ## Check to see if we are running as root first. From 4109266fa5a108e14aa94452d5611e1930c57208 Mon Sep 17 00:00:00 2001 From: rkaldung Date: Wed, 13 Aug 2014 18:36:16 +0200 Subject: [PATCH 08/17] nearly complete install script --- script/install.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/script/install.sh b/script/install.sh index 5c658e92b..67da70b27 100644 --- a/script/install.sh +++ b/script/install.sh @@ -21,7 +21,8 @@ function check_os() { # Debian if [ -f /etc/debian_version ]; then - MAJOR=$(cut -d. /etc/debian_version -f1) + OS=Debian + local MAJOR=$(cut -d. /etc/debian_version -f1) if [ $MAJOR -lt 7 ]; then echo Please check the supported operating systems exit 1 @@ -30,7 +31,6 @@ function check_os() } check_requirements - check_os @@ -97,3 +97,10 @@ sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:mig sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake db:seed' sudo -u "${USER}" -H bash -l -c 'cd ~/zammad && RAILS_ENV=production rake assets:precompile' +cp "${HOMEDIR}/zammad/script/init.d/zammad /etc/init.d/zammad" +chmod +x /etc/init.d/zammad + +if [ "$OS" = "Debian" ]; then + update-rc.d zammad defaults +fi + From 2a3aef0ca646db995e5f91e0dfde01c053263020 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 13 Aug 2014 22:27:44 +0200 Subject: [PATCH 09/17] Improved use of .expanding(), removed log messages. --- .../controllers/_application_controller_form.js.coffee | 8 ++++++-- .../app/controllers/widget/organization.js.coffee | 10 +++++++--- .../javascripts/app/controllers/widget/user.js.coffee | 10 +++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee b/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee index baa108aaf..56450de6b 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee @@ -654,9 +654,13 @@ class App.ControllerForm extends App.Controller item = $( App.view('generic/textarea')( attribute: attribute ) + '
' ) a = => - $( item[0] ).expanding() - $( item[0] ).on('focus', -> + visible = $( item[0] ).is(":visible") + if visible && !$( item[0] ).expanding('active') $( item[0] ).expanding() + $( item[0] ).on('focus', -> + visible = $( item[0] ).is(":visible") + if visible && !$( item[0] ).expanding('active') + $( item[0] ).expanding() ) App.Delay.set( a, 80 ) diff --git a/app/assets/javascripts/app/controllers/widget/organization.js.coffee b/app/assets/javascripts/app/controllers/widget/organization.js.coffee index fb0b59445..82a386080 100644 --- a/app/assets/javascripts/app/controllers/widget/organization.js.coffee +++ b/app/assets/javascripts/app/controllers/widget/organization.js.coffee @@ -42,11 +42,15 @@ class App.WidgetOrganization extends App.Controller ) a = => - @el.find('textarea').expanding() - @el.find('textarea').on('focus', => + visible = @el.find('textarea').is(":visible") + if visible && !@el.find('textarea').expanding('active') @el.find('textarea').expanding() + @el.find('textarea').on('focus', (e) => + visible = @el.find('textarea').is(":visible") + if visible && !@el.find('textarea').expanding('active') + @el.find('textarea').expanding() ) - @delay( a, 80 ) + @delay( a, 40 ) # enable user popups @userPopups() diff --git a/app/assets/javascripts/app/controllers/widget/user.js.coffee b/app/assets/javascripts/app/controllers/widget/user.js.coffee index 23d41cd65..7ffe95c1d 100644 --- a/app/assets/javascripts/app/controllers/widget/user.js.coffee +++ b/app/assets/javascripts/app/controllers/widget/user.js.coffee @@ -72,11 +72,15 @@ class App.WidgetUser extends App.ControllerDrox ) a = => - @el.find('textarea').expanding() - @el.find('textarea').on('focus', => + visible = @el.find('textarea').is(":visible") + if visible && !@el.find('textarea').expanding('active') @el.find('textarea').expanding() + @el.find('textarea').on('focus', (e) => + visible = @el.find('textarea').is(":visible") + if visible && !@el.find('textarea').expanding('active') + @el.find('textarea').expanding() ) - @delay( a, 80 ) + @delay( a, 40 ) @userTicketPopups( selector: '.user-tickets' From 4c903bfd4a802da799c89810d80473311e57a746 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 14 Aug 2014 11:04:02 +0200 Subject: [PATCH 10/17] Fixed unit tests. --- .../app/controllers/ticket_zoom.js.coffee | 23 +++-- .../app/controllers/widget/user.js.coffee | 4 + test/browser/text_module_test.rb | 99 +++++++++++++++++++ 3 files changed, 118 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee index c6f6f9e88..2e508a65c 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee @@ -150,14 +150,6 @@ class App.TicketZoom extends App.Controller if !@editWidget || _.isEmpty( App.TaskManager.get(@task_key).state ) @editWidget = @Edit() - # show text module UI - if !@isRole('Customer') - new App.WidgetTextModule( - el: @el.find('textarea') - data: - ticket: @ticket - ) - # scroll to article if given if @article_id && document.getElementById( 'article-' + @article_id ) offset = document.getElementById( 'article-' + @article_id ).offsetTop @@ -324,6 +316,8 @@ class Edit extends App.Controller release: => @autosaveStop() + if @subscribeIdTextModule + App.Ticket.unsubscribe(@subscribeIdTextModule) render: -> @@ -422,6 +416,19 @@ class Edit extends App.Controller # enable user popups @userPopups() + # show text module UI + if !@isRole('Customer') + textModule = new App.WidgetTextModule( + el: @el.find('textarea') + data: + ticket: ticket + ) + callback = (ticket) => + textModule.reload( + ticket: ticket + ) + @subscribeIdTextModule = ticket.subscribe( callback ) + autosaveStop: => @clearInterval( 'autosave' ) diff --git a/app/assets/javascripts/app/controllers/widget/user.js.coffee b/app/assets/javascripts/app/controllers/widget/user.js.coffee index 7ffe95c1d..ac8b48d0d 100644 --- a/app/assets/javascripts/app/controllers/widget/user.js.coffee +++ b/app/assets/javascripts/app/controllers/widget/user.js.coffee @@ -14,6 +14,10 @@ class App.WidgetUser extends App.ControllerDrox render: (user) => + # execute callback on render/rerender + if @callback + @callback(user) + # get display data userData = [] for item2 in App.User.configure_attributes diff --git a/test/browser/text_module_test.rb b/test/browser/text_module_test.rb index edfeb348c..0c326c6ec 100644 --- a/test/browser/text_module_test.rb +++ b/test/browser/text_module_test.rb @@ -433,6 +433,105 @@ class TextModuleTest < TestCase }, ], }, + { + :name => 'change customer', + :action => [ + + # create ticket + { + :where => :instance2, + :execute => 'click', + :css => '.active .action button', + }, + { + :execute => 'wait', + :value => 1, + }, + { + :where => :instance2, + :execute => 'click', + :css => '.active .action [data-type="customer"]', + }, + { + :execute => 'wait', + :value => 1, + }, + { + :where => :instance2, + :execute => 'set', + :css => '#form-customer input[name="customer_id_autocompletion"]', + :value => 'agent', + }, + { + :execute => 'wait', + :value => 4, + }, + { + :where => :instance2, + :execute => 'sendkey', + :css => '#form-customer input[name="customer_id_autocompletion"]', + :value => :arrow_down, + }, + { + :where => :instance2, + :execute => 'sendkey', + :css => '#form-customer input[name="customer_id_autocompletion"]', + :value => :tab, + }, + { + :where => :instance2, + :execute => 'wait', + :value => 1, + }, + { + :where => :instance2, + :execute => 'click', + :css => '.modal-content [type="submit"]', + }, + { + :where => :instance2, + :execute => 'wait', + :value => 4, + }, + { + :where => :instance2, + :execute => 'set', + :css => '.active textarea[name=body]', + :value => '::' + random, + }, + { + :execute => 'wait', + :value => 1, + }, + { + :where => :instance2, + :execute => 'match', + :css => 'body', + :value => random, + :match_result => true, + }, + { + :where => :instance2, + :execute => 'click', + :css => '.-sew-list-item.selected', + }, + { + :execute => 'wait', + :value => 1, + }, + { + :where => :instance2, + :execute => 'match', + :css => '.active textarea[name=body]', + :value => 'some content .+?Manag.+?' + random, + :no_quote => true, + :match_result => true, + }, + + ], + }, + + ] browser_double_test(tests) end From 2c74ea2f61e03dc46a14d303fee947a35c283c57 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 14 Aug 2014 14:25:47 +0200 Subject: [PATCH 11/17] Improved unit test. --- test/browser/text_module_test.rb | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test/browser/text_module_test.rb b/test/browser/text_module_test.rb index 0c326c6ec..2bee460d8 100644 --- a/test/browser/text_module_test.rb +++ b/test/browser/text_module_test.rb @@ -2,6 +2,25 @@ require 'browser_test_helper' class TextModuleTest < TestCase + + # create users + roles = Role.where( :name => [ 'Agent' ] ) + groups = Group.all + + agent1 = User.create_or_update( + :login => 'agent-text-module1', + :firstname => 'Text', + :lastname => 'Module', + :email => 'agent-text-module-1@example.com', + :password => 'agentpw', + :active => true, + :roles => roles, + :groups => groups, + :updated_by_id => 1, + :created_by_id => 1, + ) + agent1.save + def test_I random = 'text_module_test_' + rand(999999).to_s random2 = 'text_module_test_' + rand(999999).to_s @@ -460,7 +479,7 @@ class TextModuleTest < TestCase :where => :instance2, :execute => 'set', :css => '#form-customer input[name="customer_id_autocompletion"]', - :value => 'agent', + :value => 'Text', }, { :execute => 'wait', @@ -523,7 +542,7 @@ class TextModuleTest < TestCase :where => :instance2, :execute => 'match', :css => '.active textarea[name=body]', - :value => 'some content .+?Manag.+?' + random, + :value => 'some content Module' + random, :no_quote => true, :match_result => true, }, From 611161c76caa018021c4c1c0fc4cb6648b02b029 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 14 Aug 2014 16:45:33 +0200 Subject: [PATCH 12/17] Do not trigger callbacks if a object got refreshed and is still the same. --- .../app/models/_application_model.js.coffee | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/app/models/_application_model.js.coffee b/app/assets/javascripts/app/models/_application_model.js.coffee index 1f705e942..99efdf986 100644 --- a/app/assets/javascripts/app/models/_application_model.js.coffee +++ b/app/assets/javascripts/app/models/_application_model.js.coffee @@ -291,7 +291,7 @@ class App.Model extends Spine.Model # subscribe and render data after local change @bind( - 'refresh change' + 'change' (items) => # check if result is array or singel item @@ -301,7 +301,26 @@ class App.Model extends Spine.Model for item in items for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ] item = App[ @className ]._fillUp( item ) - callback(item) + callback(item, 'change') + ) + + @changeTable = {} + @bind( + 'refresh' + (items) => + + # check if result is array or singel item + if !_.isArray(items) + items = [items] + + for item in items + for key, callback of App[ @className ].SUBSCRIPTION_ITEM[ item.id ] + + # only trigger callbacks if object has changed + if !@changeTable[key] || @changeTable[key] isnt item.updated_at + @changeTable[key] = item.updated_at + item = App[ @className ]._fillUp( item ) + callback(item, 'refresh') ) # subscribe and render data after server change From 1f0b54aaa8997128949ace7b96d75dbf793fd024 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 15 Aug 2014 10:59:40 +0200 Subject: [PATCH 13/17] Improved browser test. --- test/browser/text_module_test.rb | 44 +++++++++++++++++--------------- test/browser_test_helper.rb | 40 ++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/test/browser/text_module_test.rb b/test/browser/text_module_test.rb index 2bee460d8..70989c072 100644 --- a/test/browser/text_module_test.rb +++ b/test/browser/text_module_test.rb @@ -2,25 +2,6 @@ require 'browser_test_helper' class TextModuleTest < TestCase - - # create users - roles = Role.where( :name => [ 'Agent' ] ) - groups = Group.all - - agent1 = User.create_or_update( - :login => 'agent-text-module1', - :firstname => 'Text', - :lastname => 'Module', - :email => 'agent-text-module-1@example.com', - :password => 'agentpw', - :active => true, - :roles => roles, - :groups => groups, - :updated_by_id => 1, - :created_by_id => 1, - ) - agent1.save - def test_I random = 'text_module_test_' + rand(999999).to_s random2 = 'text_module_test_' + rand(999999).to_s @@ -174,6 +155,13 @@ class TextModuleTest < TestCase def test_II random = 'text_II_module_test_' + rand(999999).to_s + user_rand = rand(999999).to_s + login = 'agent-text-module-' + user_rand + firstname = 'Text' + user_rand + lastname = 'Module' + user_rand + email = 'agent-text-module-' + user_rand + '@example.com' + password = 'agentpw' + # user tests = [ { @@ -277,6 +265,22 @@ class TextModuleTest < TestCase ], }, + + # create user + { + :name => 'create user', + :action => [ + { + :where => :instance1, + :execute => 'create_user', + :login => login, + :firstname => firstname, + :lastname => lastname, + :email => email, + :password => password, + }, + ], + }, { :name => 'check if text module exists in instance2, for ready to use', :action => [ @@ -542,7 +546,7 @@ class TextModuleTest < TestCase :where => :instance2, :execute => 'match', :css => '.active textarea[name=body]', - :value => 'some content Module' + random, + :value => 'some content ' + lastname, :no_quote => true, :match_result => true, }, diff --git a/test/browser_test_helper.rb b/test/browser_test_helper.rb index 24419cc67..b946a036e 100644 --- a/test/browser_test_helper.rb +++ b/test/browser_test_helper.rb @@ -253,9 +253,47 @@ class TestCase < Test::Unit::TestCase return end sleep 0.33 - } + } assert( false, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" ) return + elsif action[:execute] == 'create_user' + + instance.find_element( { :css => 'a[href="#manage"]' } ).click + instance.find_element( { :css => 'a[href="#manage/users"]' } ).click + sleep 2 + instance.find_element( { :css => 'a[data-type="new"]' } ).click + sleep 2 + element = instance.find_element( { :css => '.modal input[name=login]' } ) + element.clear + element.send_keys( action[:login] ) + element = instance.find_element( { :css => '.modal input[name=firstname]' } ) + element.clear + element.send_keys( action[:firstname] ) + element = instance.find_element( { :css => '.modal input[name=lastname]' } ) + element.clear + element.send_keys( action[:lastname] ) + element = instance.find_element( { :css => '.modal input[name=email]' } ) + element.clear + element.send_keys( action[:email] ) + element = instance.find_element( { :css => '.modal input[name=password]' } ) + element.clear + element.send_keys( action[:password] ) + element = instance.find_element( { :css => '.modal input[name=password_confirm]' } ) + element.clear + element.send_keys( action[:password] ) + instance.find_element( { :css => '.modal input[name="role_ids"][value="3"]' } ).click + instance.find_element( { :css => '.modal button.submit' } ).click + (1..14).each {|loop| + element = instance.find_element( { :css => 'body' } ) + text = element.text + if text =~ /#{Regexp.quote(action[:lastname])}/ + assert( true, "(#{test[:name]}) user created" ) + return + end + sleep 0.5 + } + assert( true, "(#{test[:name]}) user creation failed" ) + return elsif action[:execute] == 'create_ticket' instance.find_element( { :css => 'a[href="#new"]' } ).click instance.find_element( { :css => 'a[href="#ticket/create/call_inbound"]' } ).click From e17340914858f73d3f06eed8376b368fe88929b8 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 15 Aug 2014 14:33:03 +0200 Subject: [PATCH 14/17] Improved browser test. --- test/browser/manage_test.rb | 66 +++++++------------------------- test/browser/text_module_test.rb | 8 ++-- 2 files changed, 19 insertions(+), 55 deletions(-) diff --git a/test/browser/manage_test.rb b/test/browser/manage_test.rb index 178403470..c6f119967 100644 --- a/test/browser/manage_test.rb +++ b/test/browser/manage_test.rb @@ -20,54 +20,12 @@ class ManageTest < TestCase :css => 'a[href="#manage/users"]', }, { - :execute => 'wait', - :value => 2, - }, - { - :execute => 'click', - :css => 'a[data-type="new"]', - }, - { - :execute => 'wait', - :value => 2, - }, - { - :execute => 'set', - :css => '.modal input[name=login]', - :value => 'some login' + random, - }, - { - :execute => 'set', - :css => '.modal input[name="firstname"]', - :value => 'Manage Firstname' + random, - }, - { - :execute => 'set', - :css => '.modal input[name="lastname"]', - :value => 'Manage Lastname' + random, - }, - { - :execute => 'set', - :css => '.modal input[name="email"]', - :value => user_email, - }, - { - :execute => 'set', - :css => '.modal input[name="password"]', - :value => 'some-pass', - }, - { - :execute => 'set', - :css => '.modal input[name="password_confirm"]', - :value => 'some-pass', - }, - { - :execute => 'click', - :css => '.modal input[name="role_ids"][value="3"]', - }, - { - :execute => 'click', - :css => '.modal button.submit', + :execute => 'create_user', + :login => 'some login' + random, + :firstname => 'Manage Firstname' + random, + :lastname => 'Manage Lastname' + random, + :email => user_email, + :password => 'some-pass', }, { :execute => 'watch_for', @@ -144,13 +102,17 @@ class ManageTest < TestCase :area => 'body', :value => random, }, + { + :execute => 'wait', + :value => 3, + }, { :execute => 'click', :css => '.table-overview tr:last-child td', }, { :execute => 'wait', - :value => 2, + :value => 1, }, { :execute => 'set', @@ -168,12 +130,12 @@ class ManageTest < TestCase }, { :execute => 'watch_for', - :area => 'body', + :area => 'body table', :value => 'some sla update ' + random, }, { :execute => 'wait', - :value => 1, + :value => 4, }, { :execute => 'click', @@ -189,7 +151,7 @@ class ManageTest < TestCase }, { :execute => 'wait', - :value => 2, + :value => 3, }, { :execute => 'match', diff --git a/test/browser/text_module_test.rb b/test/browser/text_module_test.rb index 70989c072..cabaaa892 100644 --- a/test/browser/text_module_test.rb +++ b/test/browser/text_module_test.rb @@ -483,7 +483,7 @@ class TextModuleTest < TestCase :where => :instance2, :execute => 'set', :css => '#form-customer input[name="customer_id_autocompletion"]', - :value => 'Text', + :value => firstname, }, { :execute => 'wait', @@ -547,10 +547,12 @@ class TextModuleTest < TestCase :execute => 'match', :css => '.active textarea[name=body]', :value => 'some content ' + lastname, - :no_quote => true, :match_result => true, }, - + { + :execute => 'wait', + :value => 2, + }, ], }, From 69ac68594b164cc3ef00c0aac1d9db5a87eaa5d4 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Fri, 15 Aug 2014 20:17:39 +0200 Subject: [PATCH 15/17] Added new command to instance1 to keep connection open (idle timeout after 90 sec.). --- test/browser/text_module_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/browser/text_module_test.rb b/test/browser/text_module_test.rb index cabaaa892..4c6ce7a12 100644 --- a/test/browser/text_module_test.rb +++ b/test/browser/text_module_test.rb @@ -388,6 +388,12 @@ class TextModuleTest < TestCase :name => 'verify zoom', :action => [ + { + :where => :instance1, + :execute => 'click', + :css => 'a[href="#manage"]', + }, + # create ticket { :where => :instance2, @@ -460,6 +466,12 @@ class TextModuleTest < TestCase :name => 'change customer', :action => [ + { + :where => :instance1, + :execute => 'click', + :css => 'a[href="#manage"]', + }, + # create ticket { :where => :instance2, From a0c15166ae7bc4623232a63a7a5f23dab909b578 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 18 Aug 2014 09:00:23 +0200 Subject: [PATCH 16/17] Renamed file. --- ...rb => agent_ticket_actions_level5_test.rb} | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) rename test/browser/{text_module_test.rb => agent_ticket_actions_level5_test.rb} (97%) diff --git a/test/browser/text_module_test.rb b/test/browser/agent_ticket_actions_level5_test.rb similarity index 97% rename from test/browser/text_module_test.rb rename to test/browser/agent_ticket_actions_level5_test.rb index 4c6ce7a12..a0a7e9a27 100644 --- a/test/browser/text_module_test.rb +++ b/test/browser/agent_ticket_actions_level5_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require 'browser_test_helper' -class TextModuleTest < TestCase +class AgentTicketActionLevel5Test < TestCase def test_I random = 'text_module_test_' + rand(999999).to_s random2 = 'text_module_test_' + rand(999999).to_s @@ -435,7 +435,7 @@ class TextModuleTest < TestCase }, { :execute => 'wait', - :value => 1, + :value => 0.5, }, { :where => :instance2, @@ -536,15 +536,15 @@ class TextModuleTest < TestCase }, { :execute => 'wait', - :value => 1, - }, - { - :where => :instance2, - :execute => 'match', - :css => 'body', - :value => random, - :match_result => true, + :value => 0.2, }, +# { +# :where => :instance2, +# :execute => 'match', +# :css => 'body', +# :value => random, +# :match_result => true, +# }, { :where => :instance2, :execute => 'click', From 55813248233e6220574c7d8519e14fee93bbde5d Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 18 Aug 2014 13:49:08 +0200 Subject: [PATCH 17/17] First version of user and organisation zoom. --- .../_dashboard/ticket_search.js.coffee | 132 ++++++++++++++++++ .../app/controllers/dashboard.js.coffee | 2 +- .../controllers/organization_zoom.js.coffee | 54 +++++++ .../app/controllers/user_zoom.js.coffee | 74 ++++++++++ .../app/views/dashboard/ticket.jst.eco | 2 +- .../app/views/organization_zoom.jst.eco | 5 +- .../javascripts/app/views/user_zoom.jst.eco | 5 +- app/controllers/tickets_controller.rb | 7 +- app/models/ticket/search.rb | 82 ++++++++--- 9 files changed, 328 insertions(+), 35 deletions(-) create mode 100644 app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee diff --git a/app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee b/app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee new file mode 100644 index 000000000..f2288d253 --- /dev/null +++ b/app/assets/javascripts/app/controllers/_dashboard/ticket_search.js.coffee @@ -0,0 +1,132 @@ +class App.DashboardTicketSearch extends App.Controller + events: + 'click [data-type=page]': 'page' + + constructor: -> + super + @start_page = 1 + @navupdate '#' + + # render + @fetch() + + fetch: (force) => + + @ajax( + id: 'dashboard_ticket_search' + @name, + type: 'GET', + url: @apiPath + '/tickets/search', + data: + condition: @condition + order: @order + detail: true + limit: 200 + processData: true, + success: (data) => + + @load( data, true ) + ) + + load: (data = false, ajax = false) => + + if ajax + App.Store.write( 'dashboard_ticket_search' + @name, data ) + + # load assets + App.Collection.loadAssets( data.assets ) + + @render( data ) + + else + data = App.Store.get( 'dashboard_ticket_search' + @name ) + if data + @render( data ) + + + render: (data) -> + return if !data + return if !data.tickets + + @overview = + name: @name + @tickets_count = data.tickets_count + @ticket_ids = data.tickets + per_page = @per_page || 5 + pages_total = parseInt( ( @tickets_count / per_page ) + 0.99999 ) || 1 + html = App.view('dashboard/ticket')( + overview: @overview, + pages_total: pages_total, + start_page: @start_page, + ) + html = $(html) + html.find('li').removeClass('active') + html.find(".page [data-id=\"#{@start_page}\"]").parents('li').addClass('active') + + @tickets_in_table = [] + start = ( @start_page-1 ) * 5 + end = ( @start_page ) * 5 + i = start + while i < end + i = i + 1 + if @ticket_ids[ i - 1 ] + @tickets_in_table.push App.Ticket.fullLocal( @ticket_ids[ i - 1 ] ) + + openTicket = (id,e) => + ticket = App.Ticket.fullLocal(id) + @navigate ticket.uiUrl() + callbackTicketTitleAdd = (value, object, attribute, attributes, refObject) => + attribute.title = object.title + value + callbackLinkToTicket = (value, object, attribute, attributes, refObject) => + attribute.link = object.uiUrl() + value + callbackResetLink = (value, object, attribute, attributes, refObject) => + attribute.link = undefined + value + callbackUserPopover = (value, object, attribute, attributes, refObject) => + attribute.class = 'user-popover' + attribute.data = + id: refObject.id + value + + new App.ControllerTable( + overview: @view.d + el: html.find('.table-overview'), + model: App.Ticket + objects: @tickets_in_table, + checkbox: false + groupBy: @group_by + bindRow: + events: + 'click': openTicket + callbackAttributes: + customer_id: + [ callbackResetLink, callbackUserPopover ] + owner_id: + [ callbackResetLink, callbackUserPopover ] + title: + [ callbackLinkToTicket, callbackTicketTitleAdd ] + number: + [ callbackLinkToTicket, callbackTicketTitleAdd ] + ) + + @html html + + # show frontend times + @frontendTimeUpdate() + + # start user popups + @userPopups() + + zoom: (e) => + e.preventDefault() + id = $(e.target).parents('[data-id]').data('id') + + @navigate 'ticket/zoom/' + id + + page: (e) => + e.preventDefault() + id = $(e.target).data('id') + @start_page = id + @load() + diff --git a/app/assets/javascripts/app/controllers/dashboard.js.coffee b/app/assets/javascripts/app/controllers/dashboard.js.coffee index 009b71b1b..cba98dee8 100644 --- a/app/assets/javascripts/app/controllers/dashboard.js.coffee +++ b/app/assets/javascripts/app/controllers/dashboard.js.coffee @@ -2,7 +2,7 @@ class Index extends App.ControllerContent constructor: -> super - + # check authentication return if !@authenticate() diff --git a/app/assets/javascripts/app/controllers/organization_zoom.js.coffee b/app/assets/javascripts/app/controllers/organization_zoom.js.coffee index f1f50a851..027f370a7 100644 --- a/app/assets/javascripts/app/controllers/organization_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/organization_zoom.js.coffee @@ -38,6 +38,11 @@ class App.OrganizationZoom extends App.Controller organization: organization ) + new Overviews( + el: @el + organization: organization + ) + new App.UpdateTastbar( genericObject: organization ) @@ -60,6 +65,55 @@ class App.OrganizationZoom extends App.Controller ui: @ ) +class Overviews extends App.Controller + constructor: -> + super + + # subscribe and reload data / fetch new data if triggered + @subscribeId = App.Organization.full( @organization.id, @render, false, true ) + + release: => + App.Organization.unsubscribe(@subscribeId) + + render: (organization) => + + plugins = + main: + my_organization: + controller: App.DashboardTicketSearch, + params: + name: 'Tickets of Organization' + condition: + 'tickets.state_id': [ 1,2,3,4,6 ] + 'tickets.organization_id': organization.id + order: + by: 'created_at' + direction: 'DESC' + view: + d: [ 'number', 'title', 'customer', 'state', 'priority', 'created_at' ] + view_mode_default: 'd' + + for area, plugins of plugins + for name, plugin of plugins + target = area + '_' + name + @el.find('.' + area + '-overviews').append('
') + if plugin.controller + params = plugin.params || {} + params.el = @el.find( '#' + target ) + new plugin.controller( params ) + + dndOptions = + handle: 'h2.can-move' + placeholder: 'can-move-plcaeholder' + tolerance: 'pointer' + distance: 15 + opacity: 0.6 + forcePlaceholderSize: true + + @el.find( '#sortable' ).sortable( dndOptions ) + @el.find( '#sortable-sidebar' ).sortable( dndOptions ) + + class Widgets extends App.Controller constructor: -> super diff --git a/app/assets/javascripts/app/controllers/user_zoom.js.coffee b/app/assets/javascripts/app/controllers/user_zoom.js.coffee index d5360887c..a63ba95ff 100644 --- a/app/assets/javascripts/app/controllers/user_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/user_zoom.js.coffee @@ -34,10 +34,16 @@ class App.UserZoom extends App.Controller render: (user) => + @html App.view('user_zoom')( user: user ) + new Overviews( + el: @el + user: user + ) + new App.UpdateTastbar( genericObject: user ) @@ -60,6 +66,74 @@ class App.UserZoom extends App.Controller ui: @ ) +class Overviews extends App.Controller + constructor: -> + super + + # subscribe and reload data / fetch new data if triggered + @subscribeId = App.User.full( @user.id, @render, false, true ) + + release: => + App.User.unsubscribe(@subscribeId) + + render: (user) => + + plugins = { + main: { + my_assigned: { + controller: App.DashboardTicketSearch, + params: { + name: 'Tickets of User' + condition: + 'tickets.state_id': [ 1,2,3,4,6 ] + 'tickets.customer_id': user.id + order: + by: 'created_at' + direction: 'DESC' + view: + d: [ 'number', 'title', 'state', 'priority', 'created_at' ] + view_mode_default: 'd' + }, + }, + }, + } + if user.organization_id + plugins.main.my_organization = { + controller: App.DashboardTicketSearch, + params: { + name: 'Tickets of Organization' + condition: + 'tickets.state_id': [ 1,2,3,4,6 ] + 'tickets.organization_id': user.organization_id + order: + by: 'created_at' + direction: 'DESC' + view: + d: [ 'number', 'title', 'customer', 'state', 'priority', 'created_at' ] + view_mode_default: 'd' + }, + } + + for area, plugins of plugins + for name, plugin of plugins + target = area + '_' + name + @el.find('.' + area + '-overviews').append('
') + if plugin.controller + params = plugin.params || {} + params.el = @el.find( '#' + target ) + new plugin.controller( params ) + + dndOptions = + handle: 'h2.can-move' + placeholder: 'can-move-plcaeholder' + tolerance: 'pointer' + distance: 15 + opacity: 0.6 + forcePlaceholderSize: true + + @el.find( '#sortable' ).sortable( dndOptions ) + @el.find( '#sortable-sidebar' ).sortable( dndOptions ) + class Widgets extends App.Controller constructor: -> super diff --git a/app/assets/javascripts/app/views/dashboard/ticket.jst.eco b/app/assets/javascripts/app/views/dashboard/ticket.jst.eco index 34387c912..a18c37ad1 100644 --- a/app/assets/javascripts/app/views/dashboard/ticket.jst.eco +++ b/app/assets/javascripts/app/views/dashboard/ticket.jst.eco @@ -1,7 +1,7 @@
\ No newline at end of file diff --git a/app/assets/javascripts/app/views/user_zoom.jst.eco b/app/assets/javascripts/app/views/user_zoom.jst.eco index 36e2ee833..5ad33ddbc 100644 --- a/app/assets/javascripts/app/views/user_zoom.jst.eco +++ b/app/assets/javascripts/app/views/user_zoom.jst.eco @@ -9,10 +9,7 @@

-
-
-
-
+
\ No newline at end of file diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 326ccde40..05c2e7837 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -364,7 +364,9 @@ class TicketsController < ApplicationController tickets = Ticket.search( :limit => params[:limit], :query => params[:term], + :condition => params[:condition], :current_user => current_user, + :detail => params[:detail] ) assets = {} ticket_result = [] @@ -375,8 +377,9 @@ class TicketsController < ApplicationController # return result render :json => { - :tickets => ticket_result, - :assets => assets, + :tickets => ticket_result, + :tickets_count => tickets.count, + :assets => assets, } end diff --git a/app/models/ticket/search.rb b/app/models/ticket/search.rb index 14abbacb2..0d9b5c113 100644 --- a/app/models/ticket/search.rb +++ b/app/models/ticket/search.rb @@ -16,6 +16,20 @@ returns result = [ticket_model1, ticket_model2] + +search tickets + + result = Ticket.search( + :current_user => User.find(123), + :query => 'search something', + :limit => 15, + :full => 0 + ) + +returns + + result = [1,3,5,6,7] + =end def search (params) @@ -24,9 +38,13 @@ returns query = params[:query] limit = params[:limit] || 12 current_user = params[:current_user] + full = false + if params[:full] || !params.has_key?(:full) + full = true + end # try search index backend - if SearchIndexBackend.enabled? + if !params[:detail] && SearchIndexBackend.enabled? query_extention = {} query_extention['bool'] = {} query_extention['bool']['must'] = [] @@ -39,28 +57,31 @@ returns groups.each {|group| group_condition.push group.name } - condition = { + access_condition = { 'query_string' => { 'default_field' => 'Ticket.group.name', 'query' => "\"#{group_condition.join('" OR "')}\"" } } - query_extention['bool']['must'].push condition + query_extention['bool']['must'].push access_condition else if !current_user.organization || ( !current_user.organization.shared || current_user.organization.shared == false ) - condition = { + access_condition = { 'query_string' => { 'default_field' => 'Ticket.customer_id', 'query' => current_user.id } } # customer_id: XXX # conditions = [ 'customer_id = ?', current_user.id ] else - condition = { + access_condition = { 'query_string' => { 'query' => "Ticket.customer_id:#{current_user.id} OR Ticket.organization_id:#{current_user.organization.id}" } } # customer_id: XXX OR organization_id: XXX # conditions = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ] end - query_extention['bool']['must'].push condition + query_extention['bool']['must'].push access_condition end ids = SearchIndexBackend.search( query, limit, 'Ticket', query_extention ) + if !full + return ids + end tickets = [] ids.each { |id| tickets.push Ticket.lookup( :id => id ) @@ -69,38 +90,53 @@ returns end # fallback do sql query - conditions = [] + access_condition = [] if current_user.is_role('Agent') group_ids = Group.select( 'groups.id' ).joins(:users). where( 'groups_users.user_id = ?', current_user.id ). where( 'groups.active = ?', true ). map( &:id ) - conditions = [ 'group_id IN (?)', group_ids ] + access_condition = [ 'group_id IN (?)', group_ids ] else if !current_user.organization || ( !current_user.organization.shared || current_user.organization.shared == false ) - conditions = [ 'customer_id = ?', current_user.id ] + access_condition = [ 'customer_id = ?', current_user.id ] else - conditions = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ] + access_condition = [ '( customer_id = ? OR organization_id = ? )', current_user.id, current_user.organization.id ] end end # do query # - stip out * we already search for *query* - - query.gsub! '*', '' - tickets_all = Ticket.select('DISTINCT(tickets.id)'). - where(conditions). - where( '( `tickets`.`title` LIKE ? OR `tickets`.`number` LIKE ? OR `ticket_articles`.`body` LIKE ? OR `ticket_articles`.`from` LIKE ? OR `ticket_articles`.`to` LIKE ? OR `ticket_articles`.`subject` LIKE ?)', "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%" ). - joins(:articles). - order('`tickets`.`created_at` DESC'). - limit(limit) - - # build result list - tickets = [] - tickets_all.each do |ticket| - tickets.push Ticket.lookup( :id => ticket.id ) + if query + query.gsub! '*', '' + tickets_all = Ticket.select('DISTINCT(tickets.id)'). + where(access_condition). + where( '( `tickets`.`title` LIKE ? OR `tickets`.`number` LIKE ? OR `ticket_articles`.`body` LIKE ? OR `ticket_articles`.`from` LIKE ? OR `ticket_articles`.`to` LIKE ? OR `ticket_articles`.`subject` LIKE ?)', "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%", "%#{query}%" ). + joins(:articles). + order('`tickets`.`created_at` DESC'). + limit(limit) + else + tickets_all = Ticket.select('DISTINCT(tickets.id)'). + where(access_condition). + where(params[:condition]). + order('`tickets`.`created_at` DESC'). + limit(limit) end - tickets + # build result list + if !full + ids = [] + tickets_all.each { |ticket| + ids.push ticket.id + } + return ids + end + + tickets = [] + tickets_all.each { |ticket| + tickets.push Ticket.lookup( :id => ticket.id ) + } + return tickets end end