Compare commits

..

86 commits

Author SHA1 Message Date
f
af9baadea7 Merge branch 'develop' into antifascista 2021-10-14 10:40:22 -03:00
Rolf Schmidt
4b0fa96cc9 Fixes #3790 - Support workflow mechanism to do pending reminder state hide pending time use case. 2021-10-14 13:00:42 +02:00
Thorsten Eckel
fc4ab53c1a Follow up - b125b3603e - Maintenance: Docker Chat build image misses yarn installation of dependencies. 2021-10-14 08:59:37 +00:00
Thorsten Eckel
405b80cbe2 Fixes #3808 - Regression of #3797 causes installation of new instances from package to fail. 2021-10-14 08:31:04 +02:00
f
6c1a6b48a4 Merge branch 'develop' into antifascista 2021-10-13 12:39:26 -03:00
Dominik Klein
2bd4ceeedf Fixes #3733 - Simple quote characters (') not properly displayed. 2021-10-13 11:27:28 +00:00
Thorsten Eckel
c435fa4b23 Maintenance: Bumped Puma to 4.3.10 to resolve CVE-2021-41136. 2021-10-13 08:44:52 +02:00
Thorsten Eckel
16870853e1 Follow up - d7cdb308dd - Maintenance: Remove wrongly re-added switch_to_user_test.rb in browser slicing. 2021-10-12 17:18:07 +02:00
Martin Gruner
54417cd416 Fixes #3794 - Example payload in webhook view leads to 500 error 2021-10-12 14:34:42 +00:00
Bola Ahmed Buari
e6c3b07b0d Maintenance: Port old cti integration tests to capybara. 2021-10-12 16:16:59 +02:00
Bola Ahmed Buari
d7cdb308dd Maintenance: Port old preferences permission language tests to capybara. 2021-10-12 16:11:47 +02:00
Dominik Klein
3036453a0f Maintenance: Ported auth test to capybara. 2021-10-12 16:02:34 +02:00
Mantas Masalskis
55e99d7aa8 Fixes #3800 - Sort order group_by broken (alphabetical) 2021-10-12 15:46:46 +02:00
Dominik Klein
61996989b0 Maintenance: Deleted already ported switch to user test. 2021-10-11 10:58:01 +02:00
Dominik Klein
587f36d220 Maintenance: Try to improve the stabilzation of the maintenance app version selenium test. 2021-10-08 18:48:08 +02:00
Martin Gruner
52587ca9e2 Maintenance: Port System > Monitoring test to capybara. 2021-10-08 11:47:47 +00:00
Martin Gruner
1de9c8d803 Maintenance: Ported admin_permissions_granular_vs_full_test.rb to Capybara. 2021-10-08 11:42:56 +00:00
Dominik Klein
22cd8f3376 Maintenance: Port maintenance session message test to capybara. 2021-10-08 12:34:31 +02:00
Martin Edenhofer
df6fe54b66 Fixes #3797 - OS package upgrade fails (activity_stream_object_id) 2021-10-08 09:30:34 +02:00
Martin Gruner
da22f4b1bd Maintenance: Ported Manage > Channels > Email test to capybara. 2021-10-08 08:41:05 +02:00
Martin Gruner
445700d0aa Follow-up: 276c45b2e9 - Improved ticket policy scope handling. 2021-10-07 16:37:57 +02:00
Romit Choudhary
c5ba0563a5 Fixes #3737 - Bug Report 4.1.x Overview Sort - Grouped by user 2021-10-07 15:43:44 +02:00
Dominik Klein
4a2c8dd234 Maintenance: Try to improve the stabilzation of the ticket create selenium test. 2021-10-07 13:20:51 +02:00
Martin Gruner
73cb552846 Maintenance: Bump rubocop-rails from 2.12.2 to 2.12.3
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.12.2 to 2.12.3.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.12.2...v2.12.3)
2021-10-07 08:12:42 +00:00
Rolf Schmidt
a7e0d460aa Fixes #3789 - Article box opening on tickets with no changes. 2021-10-07 09:01:07 +02:00
Martin Gruner
9f9ec58230 Maintenance: Bump twilio-ruby from 5.58.3 to 5.59.0
Bumps [twilio-ruby](https://github.com/twilio/twilio-ruby) from 5.58.3 to 5.59.0.
- [Release notes](https://github.com/twilio/twilio-ruby/releases)
- [Changelog](https://github.com/twilio/twilio-ruby/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-ruby/compare/5.58.3...5.59.0)
2021-10-07 03:05:18 +02:00
Dominik Klein
3c2cea9a22 Fixes #3000 - Login site wording could be better. 2021-10-06 15:06:49 +02:00
Dominik Klein
c1cb4fdd43 Maintenance: Port maintenance app version test to capybara. 2021-10-06 08:35:18 +00:00
Martin Gruner
45cbbde2be Maintenance: Updated argon2 and doorkeeper gems. 2021-10-06 07:44:50 +02:00
f
ea2cf81ab4 makefile 2021-10-05 20:21:45 -03:00
Rolf Schmidt
3df384c758 Fixes #3787 - UploadCacheCleanupJob does not execute. 2021-10-05 17:18:31 +02:00
Martin Gruner
b33bca9910 Fixes: #3788 - lib/fill_db.rb fails to work in production environments. 2021-10-05 14:00:33 +02:00
Martin Edenhofer
9df0aaed7c Prepared 5.1. 2021-10-05 11:10:44 +02:00
Martin Gruner
de30a5c1b1 Maintenance: Improve template rendering. 2021-10-05 08:52:23 +02:00
Dominik Klein
7f178484c7 Maintenance: Refactoring of Avatar storage logic. 2021-10-05 06:42:26 +00:00
Rolf Schmidt
867b36baa8 Maintenance: Add assets level to have different data sets based on permissions 2021-10-05 06:42:26 +00:00
Thorsten Eckel
acc93a23fb Maintenance: Enhance attachment preview capabilities 2021-10-05 06:42:26 +00:00
Rolf Schmidt
7dbd1c1b15 Maintenance: Remove while loop user check login. 2021-10-05 06:42:26 +00:00
Dominik Klein
57b9ac91f3 Maintenance: Improve package installation. 2021-10-05 06:42:26 +00:00
Thorsten Eckel
f86576c1e4 Maintenance: Improve application boot time by reducing initial asset payload 2021-10-05 06:42:26 +00:00
Dominik Klein
1285c88ca3 Maintenance: Increase performance of ticket creation via form. 2021-10-05 06:42:26 +00:00
Thorsten Eckel
ecbda834bc Maintenance: Improve clipboard handling of website chat 2021-10-05 06:42:26 +00:00
Martin Gruner
0f5807d6fe Maintenance: Improved updating of user records in the front end. 2021-10-05 06:42:26 +00:00
Rolf Schmidt
6602d19dbf Maintenance: Enhanced GitHub and GitLab GraphQL endpoint check 2021-10-05 06:42:26 +00:00
Martin Gruner
5ddec48643 Maintenance: Improved updating of user records. 2021-10-05 06:42:26 +00:00
Mantas
4c72d5b9d9 Fixes #3769 - Usage of inactive object attributes in SLAs will crash admin SLA interface 2021-10-04 19:09:10 +00:00
Mantas Masalskis
90eca0f1eb Fixes #3773 - Inconstant alignment in the listing of attachments/submit button in new article area
Fixes #3774 - Broken dialog whiling uploading oversized attachment
2021-10-04 21:05:32 +02:00
Rolf Schmidt
ffa8814d02 Fixes #3779 - Core Workflow: Add organization condition attributes for object User. 2021-10-04 15:47:30 +02:00
Mantas Masalskis
32a23f9e8b Fixes #3783 - Improve contrasts in answer search for articles 2021-10-04 15:42:35 +02:00
Rolf Schmidt
798d45b299 Maintenance: Add another reload to setup new js for core workflow. 2021-10-04 13:24:50 +00:00
Martin Gruner
ca6e510ed4 Maintenance: Specify a certain PostgreSQL version for the build process that still works with older platforms. 2021-10-04 11:57:32 +02:00
Rolf Schmidt
dd66c30d59 Follow up 5f2181d8a3 - Fixes #3757 - escaped 'Set fixed' workflows don't refresh set values on active ticket sessions. 2021-10-04 10:50:14 +02:00
Martin Gruner
03bcf66126 Maintenance: Updated argon2, async-pool, jwt and rubocop gems. 2021-10-04 07:02:01 +02:00
f
1bf468a262 Use gems compiled for Alpine Linux 2021-10-03 19:41:28 -03:00
Rolf Schmidt
5bd714878a Fixes #3781 - ObjectManager Attribute without screen attribute causes CoreWorkflows migration to fail 2021-10-01 12:25:06 +02:00
Rolf Schmidt
79bacb14aa Follow up 4e4ba091d4 - Fixes #3776 - Force users to reload after system migration. 2021-10-01 09:56:43 +00:00
Mantas Masalskis
9c5a11f36e Maintenance: Rubocop uses custom inflections 2021-10-01 11:56:09 +02:00
benrubson
489177cca1 Fixes #2674, closes #3775 - Zammad preflight check warning output causes Syntax-Error in postinstall.sh and failing installation. 2021-09-30 11:09:15 +02:00
Martin Gruner
dbb93bf02c Maintenance: Improve MR template. 2021-09-30 10:15:34 +02:00
Romit Choudhary
4f3e7f4003 Fixes #2780 - Shared Organisation issue create your first ticket 2021-09-30 09:25:13 +02:00
Martin Gruner
51933e3b76 Maintenance: Bump rubocop from 1.21.0 to 1.22.0 2021-09-30 09:18:16 +02:00
Rolf Schmidt
4e4ba091d4 Fixes #3776 - Force users to reload after system migration. 2021-09-30 06:31:13 +00:00
Dominik Klein
c335147d62 Maintenance: Port customer ticket create fields test to capybara. 2021-09-29 17:17:21 +02:00
Martin Gruner
36aa35f765 Maintenance: Port admin_calendar_sla_test.rb to Capybara. 2021-09-29 12:43:58 +00:00
Thorsten Eckel
6d8f5b7d95 Fixes #3777 - misspelled KnowledgeBase constant breaks update. 2021-09-29 12:16:16 +02:00
Romit Choudhary
bf6da241d8 Fixes #2351 - Unable to cancel attachment upload 2021-09-29 11:24:50 +02:00
Mantas
1404f7b2fc Fixes #2619 - KB header and footer link-color not changeable 2021-09-29 08:29:54 +00:00
Mantas
68adb3974e Fixes #3028 - Syntax errors break scheduler job for good 2021-09-29 08:19:39 +00:00
Martin Edenhofer
0cc5764ab3 Fixes #3365 - No script content (e. g. JavaScript) in emails 2021-09-29 10:13:40 +02:00
Mantas Masalskis
8d37feceb6 Fixes #3772 - Existing tickets: New article modal with padding-left: 0; padding-right: 0; 2021-09-29 10:09:08 +02:00
Rolf Schmidt
5f2181d8a3 Fixes #3757 - escaped 'Set fixed' workflows don't refresh set values on active ticket sessions. 2021-09-29 10:03:04 +02:00
Thorsten Eckel
b85e402807 Maintenance: Pluralize admin navigation entry name for Core Workflows. 2021-09-28 15:29:44 +02:00
Martin Gruner
b17f1be9a0 Maintenance: Updated Browser requirements. 2021-09-28 11:21:57 +02:00
Martin Gruner
8d77ac4579 Maintenance: Update various gem dependencies. 2021-09-28 08:58:38 +02:00
Martin Gruner
98065e1df8 Maintenance: Bump nokogiri to v1.12.5. 2021-09-28 08:02:08 +02:00
Dominik Klein
63335652cb Maintenance: Port agent ticket update tests to capybara. 2021-09-27 12:49:55 +02:00
Martin Gruner
1b3530f2ae Maintenance: Stabilize System > Objects test (another try). 2021-09-27 09:57:56 +00:00
Bartosz Pijet
b82e8544f0 Fixes #3760 - Fix polish translations 2021-09-27 08:59:06 +00:00
Martin Gruner
24830cf814 Maintenance: Stabilize System > Objects test. 2021-09-25 06:28:00 +02:00
Martin Gruner
4f2e7b9e52 Maintenance: Port System > Translations test to capybara. 2021-09-24 15:59:07 +02:00
Martin Gruner
59f1824c3a Fixes: #3765 - Possible race condition causing OTRS import to fail 2021-09-24 07:00:41 +00:00
Martin Gruner
e88fec5bb3 Maintenance: Bump doorkeeper from 5.5.2 to 5.5.3
Bumps [doorkeeper](https://github.com/doorkeeper-gem/doorkeeper) from 5.5.2 to 5.5.3.
- [Release notes](https://github.com/doorkeeper-gem/doorkeeper/releases)
- [Changelog](https://github.com/doorkeeper-gem/doorkeeper/blob/main/CHANGELOG.md)
- [Commits](https://github.com/doorkeeper-gem/doorkeeper/compare/v5.5.2...v5.5.3)
2021-09-24 03:09:06 +02:00
Mantas
39179c83f8 Fixes #3746 - Incorrect alignment in the listing of attachments when creating a ticket 2021-09-23 14:31:03 +00:00
Rolf Schmidt
c099698c71 Fixes #3758 - Saved conditions break on selections without reloading. 2021-09-23 13:50:21 +00:00
Romit Choudhary
1fe7611bab Fixes #3075 - Misleading view of user icons which are on vacation and disabled 2021-09-23 13:44:57 +00:00
Martin Gruner
0b659776e9 Maintenance: Work around timeouts caused by the sanitizer in slow CI environments. 2021-09-23 15:14:15 +02:00
285 changed files with 3950 additions and 7497 deletions

View file

@ -1,20 +0,0 @@
module.exports = class PreventUnderscoreBackport
rule:
name: 'prevent_underscore_backport'
level: 'error'
message: 'The method __(...) is not available in current stable'
description: '''
'''
constructor: ->
@callTokens = []
tokens: ['CALL_START']
lintToken: (token, tokenApi) ->
[type, tokenValue] = token
p = tokenApi.peek(-1)
if p[1] == '__'
return { }

3
.gitignore vendored
View file

@ -84,9 +84,6 @@
# Eclipse # Eclipse
/.project /.project
# VSCode
/.vscode
# Byebug # Byebug
/.byebug_history /.byebug_history

View file

@ -1,5 +1,5 @@
default: default:
image: $CI_REGISTRY/docker/zammad-ci:2.7.4 image: registry.znuny.com/docker/zammad-ci:2.7.4
include: include:
- local: '/.gitlab/ci/base.yml' - local: '/.gitlab/ci/base.yml'
@ -55,7 +55,7 @@ cache:
# Initialize application env # Initialize application env
before_script: before_script:
- source /etc/profile.d/rvm.sh - source /etc/profile.d/rvm.sh
- source /opt/rh/rh-nodejs*/enable - source /opt/rh/rh-nodejs12/enable
- bundle install -j $(nproc) --path vendor - bundle install -j $(nproc) --path vendor
- bundle exec ruby .gitlab/configure_environment.rb - bundle exec ruby .gitlab/configure_environment.rb
- source .gitlab/environment.env - source .gitlab/environment.env

View file

@ -74,35 +74,35 @@
# DB Docker # DB Docker
.docker_mysql: &docker_mysql .docker_mysql: &docker_mysql
name: $CI_REGISTRY/docker/zammad-mysql:stable name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
.docker_postgresql: &docker_postgresql .docker_postgresql: &docker_postgresql
name: $CI_REGISTRY/docker/zammad-postgresql:stable name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
.docker_elasticsearch: &docker_elasticsearch .docker_elasticsearch: &docker_elasticsearch
name: $CI_REGISTRY/docker/zammad-elasticsearch:$ELASTICSEARCH_TAG name: registry.znuny.com/docker/zammad-elasticsearch:$ELASTICSEARCH_TAG
alias: elasticsearch alias: elasticsearch
.docker_selenium_chrome: &docker_selenium_chrome .docker_selenium_chrome: &docker_selenium_chrome
name: $CI_REGISTRY/docker/zammad-selenium-chrome:stable name: registry.znuny.com/docker/zammad-selenium-chrome:stable
alias: selenium-chrome alias: selenium-chrome
.docker_selenium_firefox: &docker_selenium_firefox .docker_selenium_firefox: &docker_selenium_firefox
name: $CI_REGISTRY/docker/zammad-selenium-firefox:stable name: registry.znuny.com/docker/zammad-selenium-firefox:stable
alias: selenium-firefox alias: selenium-firefox
.docker_imap: &docker_imap .docker_imap: &docker_imap
name: $CI_REGISTRY/docker/zammad-imap:stable name: registry.znuny.com/docker/zammad-imap:stable
alias: mail alias: mail
.docker_redis: &docker_redis .docker_redis: &docker_redis
name: $CI_REGISTRY/docker/zammad-redis:stable name: registry.znuny.com/docker/zammad-redis:stable
alias: redis alias: redis
.docker_memcached: &docker_memcached .docker_memcached: &docker_memcached
name: $CI_REGISTRY/docker/zammad-memcached:stable name: registry.znuny.com/docker/zammad-memcached:stable
alias: memcached alias: memcached
command: ["memcached", "-m", "256M"] command: ["memcached", "-m", "256M"]

View file

@ -8,7 +8,7 @@ api_client_php:
script: script:
- RAILS_ENV=test bundle exec rake db:create - RAILS_ENV=test bundle exec rake db:create
- RAILS_ENV=test bundle exec rake zammad:ci:test:start zammad:setup:auto_wizard - RAILS_ENV=test bundle exec rake zammad:ci:test:start zammad:setup:auto_wizard
- git clone https://github.com/zammad/zammad-api-client-php.git -b zammad-ci-5.0 # Use state with tests compatible to 5.0 - git clone https://github.com/zammad/zammad-api-client-php.git
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php --install-dir=/usr/local/bin - php composer-setup.php --install-dir=/usr/local/bin
- ln -s /usr/local/bin/composer.phar /usr/local/bin/composer - ln -s /usr/local/bin/composer.phar /usr/local/bin/composer

View file

@ -7,11 +7,11 @@ otrs_chrome:
IMPORT_OTRS_ENDPOINT: "http://zammad-ci-otrsimport-app/otrs/public.pl?Action=ZammadMigrator" IMPORT_OTRS_ENDPOINT: "http://zammad-ci-otrsimport-app/otrs/public.pl?Action=ZammadMigrator"
TZ: "Europe/Berlin" # Required for the zammad-ci-otrsimport-app containers TZ: "Europe/Berlin" # Required for the zammad-ci-otrsimport-app containers
services: services:
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-selenium-chrome:stable - name: registry.znuny.com/docker/zammad-selenium-chrome:stable
alias: selenium-chrome alias: selenium-chrome
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs6 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs6
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs6 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs6
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app

View file

@ -11,6 +11,7 @@
- bundle exec rails test test/integration/elasticsearch_active_test.rb - bundle exec rails test test/integration/elasticsearch_active_test.rb
- bundle exec rails test test/integration/elasticsearch_test.rb - bundle exec rails test test/integration/elasticsearch_test.rb
- bundle exec rspec --tag searchindex --tag ~type:system --profile 10 - bundle exec rspec --tag searchindex --tag ~type:system --profile 10
- bundle exec rails test test/integration/report_test.rb
es:7: es:7:
<<: *template_integration_es <<: *template_integration_es

View file

@ -12,71 +12,71 @@
otrs:6: otrs:6:
<<: *template_integration_otrs <<: *template_integration_otrs
services: services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable - name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs6 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs6
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs6 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs6
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app
otrs:5: otrs:5:
<<: *template_integration_otrs <<: *template_integration_otrs
services: services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable - name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs5 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs5
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs5 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs5
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app
otrs:4: otrs:4:
<<: *template_integration_otrs <<: *template_integration_otrs
services: services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable - name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs4 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs4
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs4 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs4
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app
otrs:33: otrs:33:
<<: *template_integration_otrs <<: *template_integration_otrs
services: services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable - name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs33 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs33
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs33 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs33
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app
otrs:32: otrs:32:
<<: *template_integration_otrs <<: *template_integration_otrs
services: services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable - name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs32 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs32
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs32 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs32
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app
otrs:31: otrs:31:
<<: *template_integration_otrs <<: *template_integration_otrs
services: services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable - name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable - name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql alias: postgresql
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-db:otrs31 - name: registry.znuny.com/docker/zammad-ci-otrsimport-db:otrs31
alias: zammad-ci-otrsimport-db alias: zammad-ci-otrsimport-db
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs31 - name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs31
alias: zammad-ci-otrsimport-app alias: zammad-ci-otrsimport-app

View file

@ -6,7 +6,7 @@
- .rules_singletest - .rules_singletest
before_script: before_script:
- source /etc/profile.d/rvm.sh # ensure RVM is loaded - source /etc/profile.d/rvm.sh # ensure RVM is loaded
- source /opt/rh/rh-nodejs*/enable # ensure Node.js is available - source /opt/rh/rh-nodejs12/enable # ensure Node.js is available
rubocop: rubocop:
<<: *template_pre <<: *template_pre
@ -39,7 +39,7 @@ brakeman:
artifacts: artifacts:
expire_in: 1 week expire_in: 1 week
paths: paths:
- tmp/brakeman-report.html - tmp/brakeman-report.html
when: on_failure when: on_failure
script: script:
- bundle install -j $(nproc) --path vendor - bundle install -j $(nproc) --path vendor
@ -48,7 +48,7 @@ brakeman:
coffeelint: coffeelint:
<<: *template_pre <<: *template_pre
script: script:
- coffeelint --rules ./.coffeelint/rules/* app/ - coffeelint app/
bundle-audit: bundle-audit:
<<: *template_pre <<: *template_pre
@ -62,9 +62,8 @@ github:
tags: tags:
- deploy - deploy
before_script: before_script:
- '' # no RVM present in deploy ENV - "" # no RVM present in deploy ENV
script: script:
- git fetch --unshallow
- script/build/sync_repo.sh git@github.com:zammad/zammad.git - script/build/sync_repo.sh git@github.com:zammad/zammad.git
global_refresh_envs: global_refresh_envs:
@ -78,7 +77,7 @@ global_refresh_envs:
artifacts: artifacts:
expire_in: 1 day expire_in: 1 day
paths: paths:
- fresh.env - fresh.env
rules: rules:
- if: $CI_MERGE_REQUEST_ID - if: $CI_MERGE_REQUEST_ID
when: never when: never

View file

@ -1,8 +1,9 @@
## What does this MR do? ## What does this MR do?
<!-- Is there a lot to say? Consider creating an issue. --> <!--Insert the link to a GitHub issue in (), or describe the changes if there is no issue -->
[Issue Link]()
## Screenshots <!-- Optional --> ## Screenshots <!-- Optional, very helpful for the reviewer colleagues from other teams -->
### Before ### Before
@ -12,7 +13,7 @@
![alt text](https://example.com/after.png) ![alt text](https://example.com/after.png)
## Notes ## Code Changes
* This MR * This MR
**does** <!-- KEEP ONLY ONE --> **does** <!-- KEEP ONLY ONE -->
@ -58,9 +59,36 @@ How do your performance changes scale on a system of this size?
they are really big customers, and we want to keep their business!) they are really big customers, and we want to keep their business!)
--> -->
### Follow-up Required <!-- Optional --> ### Documentation Follow-up Required?
<!-- Keep one of the two sections -->
<!-- <!--
Does your MR require coordination with the documentation/support teams? If this MR does change:
If so, apply the label and explain here. - How the user experiences or uses the application
- Visual appearance
- Screen flow
- Texts
- How the application is deployed an maintained
- Deployment process
- System requirements
- Command line interfaces
-->
This MR may require follow-up by the documentation team.
/label ~Documentation
<!--
Otherwise
--> -->
This MR does not require any follow-up.
## QA Checklist (to be filled by the reviewer)
- [ ] Implementation satisfies specification
- [ ] Changes confirmed by manual testing
- [ ] [Code style](https://git.znuny.com/zammad/zammad/-/wikis/Coding-style-guide) is appropriate
- [ ] Performance will not degrade
- [ ] Code is properly covered with tests
- If follow-up by the documentation team is needed:
- [ ] Add a comment with this text
> @<!-- don't treat this as a mention until copied -->MrGeneration please check if this MR requires changes to the documentation. Thanks!

View file

@ -56,18 +56,6 @@ targets:
- libimlib2 - libimlib2
- libimlib2-dev - libimlib2-dev
- shared-mime-info - shared-mime-info
debian-11:
dependencies:
- curl
- elasticsearch|elasticsearch-oss
- nginx|apache2
- postgresql|mariadb-server
- libimlib2
- shared-mime-info
build_dependencies:
- libimlib2
- libimlib2-dev
- shared-mime-info
ubuntu-16.04: ubuntu-16.04:
dependencies: dependencies:
- curl - curl

View file

@ -17,7 +17,7 @@ module RuboCop
PATTERN PATTERN
def_node_matcher :has_reset?, <<-PATTERN def_node_matcher :has_reset?, <<-PATTERN
$(send _ {:describe :context :it :shared_examples} (_ ...) (hash <(pair (sym :db_strategy) (sym {:reset :reset_all})) ...> )) $(send _ {:describe :context :it} (_ ...) (hash ... (pair (sym :db_strategy) (sym {:reset :reset_all}))))
PATTERN PATTERN
MSG = 'Add a `db_strategy: :reset` to your context/decribe when you are creating object manager attributes!'.freeze MSG = 'Add a `db_strategy: :reset` to your context/decribe when you are creating object manager attributes!'.freeze

View file

@ -1,17 +0,0 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop
module Zammad
class PreventUnderscroreBackport < Base
MSG = <<~ERROR_MESSAGE.freeze
The method __(...) is not available in current stable.
ERROR_MESSAGE
def on_send(node)
add_offense(node) if node.method_name.eql? :__
end
end
end
end
end

View file

@ -13,8 +13,7 @@ module RuboCop
def on_new_investigation def on_new_investigation
if processed_source.raw_source.include? '# Copyright (C) 2012-' if processed_source.raw_source.include? '# Copyright (C) 2012-'
# Disabled for stable branches. update_copyright
# update_copyright
else else
insert_copyright insert_copyright
end end

View file

@ -6,6 +6,8 @@ require:
- rubocop-performance - rubocop-performance
- rubocop-rails - rubocop-rails
- rubocop-rspec - rubocop-rspec
- rubocop-inflector
- ../config/initializers/inflections.rb
- ./rubocop_zammad.rb - ./rubocop_zammad.rb
inherit_from: inherit_from:

View file

@ -10,4 +10,3 @@ require_relative 'cop/zammad/no_to_sym_on_string'
require_relative 'cop/zammad/prefer_negated_if_over_unless' require_relative 'cop/zammad/prefer_negated_if_over_unless'
require_relative 'cop/zammad/update_copyright' require_relative 'cop/zammad/update_copyright'
require_relative 'cop/zammad/forbid_rand' require_relative 'cop/zammad/forbid_rand'
require_relative 'cop/zammad/prevent_underscore_backport'

View file

@ -887,10 +887,6 @@ Metrics/PerceivedComplexity:
- 'test/browser_test_helper.rb' - 'test/browser_test_helper.rb'
- 'test/integration/slack_test.rb' - 'test/integration/slack_test.rb'
Rails/AssertNot:
Exclude:
- 'test/browser/admin_permissions_granular_vs_full_test.rb'
Rails/CreateTableWithTimestamps: Rails/CreateTableWithTimestamps:
Exclude: Exclude:
- 'db/migrate/20120101000001_create_base.rb' - 'db/migrate/20120101000001_create_base.rb'

View file

@ -1,264 +1,15 @@
# Change Log # Change Log
## [5.0.3](https://github.com/zammad/zammad/tree/5.0.3) (2021-12-07) ## [5.1.0](https://github.com/zammad/zammad/tree/5.1.0) (2021-xx-xx)
[Full Changelog](https://github.com/zammad/zammad/compare/5.0.0...5.1.0)
[Full Changelog](https://github.com/zammad/zammad/compare/5.0.2...5.0.3)
**Implemented enhancements:** **Implemented enhancements:**
- Possibility to specify the order of objects [294](https://github.com/zammad/zammad/issues/294) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)]
- Display callback urls for third-party applications [3622](https://github.com/zammad/zammad/issues/3622) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Add clear selection action or has changed condition [3821](https://github.com/zammad/zammad/issues/3821) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[specification required](https://github.com/zammad/zammad/labels/specification required)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
**Fixed bugs:** **Fixed bugs:**
- Missing ticket updates on high load in MariaDB/MySQL environments [3877](https://github.com/zammad/zammad/issues/3877) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Wrong SLA is used (alphabetical order is ignored) [3871](https://github.com/zammad/zammad/issues/3871) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Agent with CREATE only permission acts "on behalf" ticket customer on shared organizations [3872](https://github.com/zammad/zammad/issues/3872) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Provide meaningful modal if report profile tries to use dates out side the filtered date range [3616](https://github.com/zammad/zammad/issues/3616) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[reporting](https://github.com/zammad/zammad/labels/reporting)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Allow `position` to determine an attributes position entirely [3594](https://github.com/zammad/zammad/issues/3594) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)] [[specification required](https://github.com/zammad/zammad/labels/specification required)]
- Till label not assigned to corresponding input fields in calendar edit view [3793](https://github.com/zammad/zammad/issues/3793) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Simple quote characters (`'`) not properly displayed [3846](https://github.com/zammad/zammad/issues/3846) [[bug](https://github.com/zammad/zammad/labels/bug)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Remove api user and password for sipgate integration [3848](https://github.com/zammad/zammad/issues/3848) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- No signature on new ticket if email is default message type [3844](https://github.com/zammad/zammad/issues/3844) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Forwarding no longer possible for email and web articles [3855](https://github.com/zammad/zammad/issues/3855) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Default values of new group dialog is different in german vs. english [3851](https://github.com/zammad/zammad/issues/3851) [[bug](https://github.com/zammad/zammad/labels/bug)]
- If no date is set the UI show it's shown as NaN.NaN.NaN. [3850](https://github.com/zammad/zammad/issues/3850) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Number of to show caller log entries is inconsistent setting wise [3852](https://github.com/zammad/zammad/issues/3852) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[admin area](https://github.com/zammad/zammad/labels/admin area)] [[integration](https://github.com/zammad/zammad/labels/integration)]
- Reply all: Duplicate email on changing recipient and cc in a certain way [3825](https://github.com/zammad/zammad/issues/3825) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Removing calendars via UI and API does not check for references [3845](https://github.com/zammad/zammad/issues/3845) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[escalation logic](https://github.com/zammad/zammad/labels/escalation logic)]
- Email address not shown inside forwarded email [3824](https://github.com/zammad/zammad/issues/3824) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Wrong escalation update time in admin interface is shown [3837](https://github.com/zammad/zammad/issues/3837) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Zammad returns stack error when one tries to remove groups via API [3841](https://github.com/zammad/zammad/issues/3841) [[bug](https://github.com/zammad/zammad/labels/bug)] [[API](https://github.com/zammad/zammad/labels/API)]
- Zammad ignores relative GitLab URLs [3830](https://github.com/zammad/zammad/issues/3830) [[bug](https://github.com/zammad/zammad/labels/bug)] [[integration](https://github.com/zammad/zammad/labels/integration)]
- If selected value is not part of the restriction of set_fixed_to it should recalculate it with the new value [3822](https://github.com/zammad/zammad/issues/3822) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Invalid group and owner list for tickets created via customer profile [3835](https://github.com/zammad/zammad/issues/3835) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Ticket zoom will loose attachments on rerender [3831](https://github.com/zammad/zammad/issues/3831) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Package installation creates database.yml as `root` and thus breaks the installation until next update [3834](https://github.com/zammad/zammad/issues/3834) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Ticket create screen will loose attachments by time [3827](https://github.com/zammad/zammad/issues/3827) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Simple quote characters (`'`) not properly displayed [3733](https://github.com/zammad/zammad/issues/3733) [[bug](https://github.com/zammad/zammad/labels/bug)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- When quoting, no breakout from div container possible [3094](https://github.com/zammad/zammad/issues/3094) [[bug](https://github.com/zammad/zammad/labels/bug)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- Quoting not working cleanly, if content gets too much [2334](https://github.com/zammad/zammad/issues/2334) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Zammad database credentials are world-readable [3828](https://github.com/zammad/zammad/issues/3828) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Update time SLAs escalates tickets with agent response [3140](https://github.com/zammad/zammad/issues/3140) [[bug](https://github.com/zammad/zammad/labels/bug)] [[escalation logic](https://github.com/zammad/zammad/labels/escalation logic)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
## [5.0.2](https://github.com/zammad/zammad/tree/5.0.2) (2021-10-28)
[Full Changelog](https://github.com/zammad/zammad/compare/5.0.1...5.0.2)
**Fixed bugs:**
- When looking for customers, it is no longer possible to change into organizations [3815](https://github.com/zammad/zammad/issues/3815) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Owner should get cleared if not listed in changed group [3818](https://github.com/zammad/zammad/issues/3818) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Custom date and datetime attributes are filled with dates on creation of tickets/users after update from 4.1 to 5.x [3810](https://github.com/zammad/zammad/issues/3810) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- ActionController::UnknownHttpMethod FRAGE [3807](https://github.com/zammad/zammad/issues/3807) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[macros](https://github.com/zammad/zammad/labels/macros)]
- Remote change of the group id does show it falsly as user change and not render the new value to the ticket [3801](https://github.com/zammad/zammad/issues/3801) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Adding private keys allows adding certificates [3727](https://github.com/zammad/zammad/issues/3727) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Able to create custom fields for existing relation (e. g. ticket.state) - will lead to non bootable Zammad [3811](https://github.com/zammad/zammad/issues/3811) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Sort order group_by broken (alphabetical) [3800](https://github.com/zammad/zammad/issues/3800) [[bug](https://github.com/zammad/zammad/labels/bug)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Ticket owner selection is not updated if owner selection should be empty [3809](https://github.com/zammad/zammad/issues/3809) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Chat can't be closed after timeout [2471](https://github.com/zammad/zammad/issues/2471) [[bug](https://github.com/zammad/zammad/labels/bug)] [[chat](https://github.com/zammad/zammad/labels/chat)]
- Support workflow mechanism to do pending reminder state hide pending time use case [3790](https://github.com/zammad/zammad/issues/3790) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Cache.clear in postinstall.sh throws ugly errors on fresh installations [3808](https://github.com/zammad/zammad/issues/3808) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Example payload in webhook view leads to 500 error [3794](https://github.com/zammad/zammad/issues/3794) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- OS package upgrade fails (activity_stream_object_id) [3797](https://github.com/zammad/zammad/issues/3797) [[bug](https://github.com/zammad/zammad/labels/bug)]
## [5.0.1](https://github.com/zammad/zammad/tree/5.0.1) (2021-10-08)
[Full Changelog](https://github.com/zammad/zammad/compare/5.0.0...5.0.1)
**Fixed bugs:**
- Bug Report 4.1.x Overview Sort - Grouped by user [3737](https://github.com/zammad/zammad/issues/3737) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Article box opening on tickets with no changes [3789](https://github.com/zammad/zammad/issues/3789) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- UploadCacheCleanupJob does not execute [3787](https://github.com/zammad/zammad/issues/3787) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- lib/fill_db.rb fails to work in production environments [3788](https://github.com/zammad/zammad/issues/3788) [[bug](https://github.com/zammad/zammad/labels/bug)]
## [5.0.0](https://github.com/zammad/zammad/tree/5.0.0) (2021-10-05)
[Full Changelog](https://github.com/zammad/zammad/compare/4.1.0...5.0.0)
**Implemented enhancements:**
- Core Workflow: Add organization condition attributes for object User [3779](https://github.com/zammad/zammad/issues/3779) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- No script content (e. g. javascript) in emails [3365](https://github.com/zammad/zammad/issues/3365) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail processing)]
- Read-only custom objects [2102](https://github.com/zammad/zammad/issues/2102) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Granular admin permission for google channel is missing [3194](https://github.com/zammad/zammad/issues/3194) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Use country codes (e.g. `DE` or `ES`) for knowledgebase answer selection [3574](https://github.com/zammad/zammad/issues/3574) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- New email account expert view cannot be opened without filling in all fields [3137](https://github.com/zammad/zammad/issues/3137) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Don't provide option to create API-Token if authentication via API token is disabled [3168](https://github.com/zammad/zammad/issues/3168) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Define default "stay on tab" / "close tab" behavior [257](https://github.com/zammad/zammad/issues/257) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Space after ticket hook in ticket/zoom [3265](https://github.com/zammad/zammad/issues/3265) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- Enhance LDAP login to not affect "failed logins" [2389](https://github.com/zammad/zammad/issues/2389) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[LDAP](https://github.com/zammad/zammad/labels/LDAP)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Detect Jira follow-ups [3695](https://github.com/zammad/zammad/issues/3695) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail processing)]
- csv import example file download (organizations) is empty [3514](https://github.com/zammad/zammad/issues/3514) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Add bulk option to extended search [445](https://github.com/zammad/zammad/issues/445) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- MessageBird integration [3672](https://github.com/zammad/zammad/issues/3672) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[channel](https://github.com/zammad/zammad/labels/channel)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Add attachment via Trigger and scheduler if wanted by admin [2485](https://github.com/zammad/zammad/issues/2485) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[admin area](https://github.com/zammad/zammad/labels/admin area)] [[trigger](https://github.com/zammad/zammad/labels/trigger)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Tag KB Answers [2612](https://github.com/zammad/zammad/issues/2612) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- Backtrace lines pollute log [3556](https://github.com/zammad/zammad/issues/3556) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[authentication](https://github.com/zammad/zammad/labels/authentication)]
- Visualise locked users in UI and make them unlock-able for admin [2565](https://github.com/zammad/zammad/issues/2565) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Representation of inactive customers and orgnizations [3302](https://github.com/zammad/zammad/issues/3302) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- No possibility to enforce auto response if one of the blocking auto response mail header exists [3667](https://github.com/zammad/zammad/issues/3667) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail processing)]
- REST doc of Online Notification controler is outdated/wrong and expand param is missing. [3635](https://github.com/zammad/zammad/issues/3635) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Scroll background instead of foreground [978](https://github.com/zammad/zammad/issues/978) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Log if a active user (in UI) has been logged out due to SessionTimeout [3614](https://github.com/zammad/zammad/issues/3614) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- The rake task `zammad:package:migrate` does not execute migrations for linked packages. [3606](https://github.com/zammad/zammad/issues/3606) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[developer experience](https://github.com/zammad/zammad/labels/developer experience)]
- Accept 2xx as response for requests in UserAgent [3573](https://github.com/zammad/zammad/pull/3573) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Don't fail job is `deletable_id` is no longer available [3536](https://github.com/zammad/zammad/issues/3536) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[data privacy](https://github.com/zammad/zammad/labels/data privacy)]
- Add console output for searchindex rebuild status [3562](https://github.com/zammad/zammad/issues/3562) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Display minutes for session timeouts instead of seconds [3575](https://github.com/zammad/zammad/issues/3575) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[admin area](https://github.com/zammad/zammad/labels/admin area)]
**Fixed bugs:**
- Inconstant alignment in the listing of attachments/submit button in new article area [3773](https://github.com/zammad/zammad/issues/3773) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Improve contrasts in answer search for articles [3783](https://github.com/zammad/zammad/issues/3783) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- escaped 'Set fixed' workflows don't refresh set values on active ticket sessions [3757](https://github.com/zammad/zammad/issues/3757) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- ObjectManager Attribute without screen attribute causes CoreWorkflows migration to fail [3781](https://github.com/zammad/zammad/issues/3781) [[bug](https://github.com/zammad/zammad/labels/bug)] [[migration / update](https://github.com/zammad/zammad/labels/migration / update)]
- Zammad preflight check warning output causes Syntax-Error in postinstall.sh and failing installation [2674](https://github.com/zammad/zammad/issues/2674) [[bug](https://github.com/zammad/zammad/labels/bug)] [[migration / update](https://github.com/zammad/zammad/labels/migration / update)]
- Shared organization issue (Create your first ticket) [2780](https://github.com/zammad/zammad/issues/2780) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- Force users to reload after system migration [3776](https://github.com/zammad/zammad/issues/3776) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Unable to cancel attachment upload [2351](https://github.com/zammad/zammad/issues/2351) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- [BUG] miss spell in db/migrate/20210923172256_issue_2619_kb_header_link_color.rb [3777](https://github.com/zammad/zammad/issues/3777) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[migration / update](https://github.com/zammad/zammad/labels/migration / update)]
- KB header and footer link-color not changeable [2619](https://github.com/zammad/zammad/issues/2619) [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)] [[specification required](https://github.com/zammad/zammad/labels/specification required)] [[theming / skinning](https://github.com/zammad/zammad/labels/theming / skinning)]
- Syntax errors break scheduler job for good [3028](https://github.com/zammad/zammad/issues/3028) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Existing tickets: New article modal with padding-left: 0; padding-right: 0; [3772](https://github.com/zammad/zammad/issues/3772) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Possible race condition causing OTRS import to fail [3765](https://github.com/zammad/zammad/issues/3765) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Incorrect alignment in the listing of attachments when creating a ticket [3746](https://github.com/zammad/zammad/issues/3746) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Saved conditions break on selections without reloading [3758](https://github.com/zammad/zammad/issues/3758) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Misleading view of user icons which are on vacation and disabled [3075](https://github.com/zammad/zammad/issues/3075) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- User with user_id 1 is show in admin interface (which should not) [3755](https://github.com/zammad/zammad/issues/3755) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)]
- Unable to close tickets in certran cases if core workflow is used [3710](https://github.com/zammad/zammad/issues/3710) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Login failed after upgrade to zammad 5.0 [3759](https://github.com/zammad/zammad/issues/3759) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[migration / update](https://github.com/zammad/zammad/labels/migration / update)]
- Unable to create a ticket in web app if default for additional boolean value is FALSE [3762](https://github.com/zammad/zammad/issues/3762) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- User search / selection does not always work if you want to correct your search [3696](https://github.com/zammad/zammad/issues/3696) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Unable to create new organization [3751](https://github.com/zammad/zammad/issues/3751) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Core Workflow "is not" operator is working unexpected [3752](https://github.com/zammad/zammad/issues/3752) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- scrollPageHeader disappears when answering via email [3736](https://github.com/zammad/zammad/issues/3736) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Scheduler ignores "disable notifications == no" [3684](https://github.com/zammad/zammad/issues/3684) [[bug](https://github.com/zammad/zammad/labels/bug)] [[notification](https://github.com/zammad/zammad/labels/notification)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Notes on existing ticks are discarded by editing profile settings [3088](https://github.com/zammad/zammad/issues/3088) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Owner selection empty or pending reminder data picker not shown if customer field has content but no customer is selected (in ticket create screen) [3743](https://github.com/zammad/zammad/issues/3743) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Removal of Microsoft365-Channel not possible via UI when having no email address relation [3741](https://github.com/zammad/zammad/issues/3741) [[bug](https://github.com/zammad/zammad/labels/bug)] [[channel](https://github.com/zammad/zammad/labels/channel)]
- Removal of Google-Channel not possible via UI when having a normal email channel of same account [3203](https://github.com/zammad/zammad/issues/3203) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[channel](https://github.com/zammad/zammad/labels/channel)]
- Core-Workflow: Option manipulation of boolean attributes not possible [3740](https://github.com/zammad/zammad/issues/3740) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Core Workflow: Show hidden attributes on group selection (ticket edit) [3739](https://github.com/zammad/zammad/issues/3739) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- OTRS migration doesn't import article creation time [3235](https://github.com/zammad/zammad/issues/3235) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Spaces stay URL-encoded when going back to search results on KB for agents [3378](https://github.com/zammad/zammad/issues/3378) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- Not working unpack of mail body if decrypted body is in signed-data attachment [3705](https://github.com/zammad/zammad/issues/3705) [[bug](https://github.com/zammad/zammad/labels/bug)] [[mail processing](https://github.com/zammad/zammad/labels/mail processing)]
- It should be possible to show attributes which are configured `shown` false [3726](https://github.com/zammad/zammad/issues/3726) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- admin.core_workflow permission is missing [3732](https://github.com/zammad/zammad/issues/3732) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- AttributeManager doesn't display boolean default values within the UI [3271](https://github.com/zammad/zammad/issues/3271) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)]
- Spaces in front of mentions can cause partly content removal [3717](https://github.com/zammad/zammad/issues/3717) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Drop files here not disappearing after dropping a file [3725](https://github.com/zammad/zammad/issues/3725) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- ⚙ -> Manage -> Calendars -> Edit: "Subscribe to public holidays in" sorted wrong [2528](https://github.com/zammad/zammad/issues/2528) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Pending reminder notifications are not sent if ticket is opened in tab [2931](https://github.com/zammad/zammad/issues/2931) [[bug](https://github.com/zammad/zammad/labels/bug)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Fields are falsey displayed as mandatory if they contain historic screen values [3721](https://github.com/zammad/zammad/issues/3721) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- `ticket.customer_id` is `current_user` breaks email fetching [3503](https://github.com/zammad/zammad/issues/3503) [[bug](https://github.com/zammad/zammad/labels/bug)] [[channel](https://github.com/zammad/zammad/labels/channel)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- Scheduler jobs don't ensure current ticket information if they're running a long time [3329](https://github.com/zammad/zammad/issues/3329) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- groups selection for customer panel is not working anymore (with core workflows) [3713](https://github.com/zammad/zammad/issues/3713) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Scheduler Time offset [457](https://github.com/zammad/zammad/issues/457) [[bug](https://github.com/zammad/zammad/labels/bug)] [[trigger](https://github.com/zammad/zammad/labels/trigger)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- "Warten auf Erinnerung" - Inconsistent timestamps [2366](https://github.com/zammad/zammad/issues/2366) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Ical escaltion update the calendar entry to 2:00 am [2157](https://github.com/zammad/zammad/issues/2157) [[bug](https://github.com/zammad/zammad/labels/bug)] [[notification](https://github.com/zammad/zammad/labels/notification)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Inheritance of out of office settings [3694](https://github.com/zammad/zammad/issues/3694) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Core worflow perform action "select" should not make multiple values selectable [3712](https://github.com/zammad/zammad/issues/3712) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Setting for CheckMK not saved in zammad [3707](https://github.com/zammad/zammad/issues/3707) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Any user can be set as a replacement for out of office [2293](https://github.com/zammad/zammad/issues/2293) [[bug](https://github.com/zammad/zammad/labels/bug)] [[personal settings/menu](https://github.com/zammad/zammad/labels/personal settings/menu)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Core Workflow Implementation [3709](https://github.com/zammad/zammad/issues/3709) [[feature backlog](https://github.com/zammad/zammad/labels/feature backlog)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[core](https://github.com/zammad/zammad/labels/core)] [[core workflows](https://github.com/zammad/zammad/labels/core workflows)]
- Can't remove auto assignment timeout [2544](https://github.com/zammad/zammad/issues/2544) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Assign Follow ups has no affect [2455](https://github.com/zammad/zammad/issues/2455) [[bug](https://github.com/zammad/zammad/labels/bug)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- The calendar shows Chilean holidays one day in advance [3706](https://github.com/zammad/zammad/issues/3706) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Organization removal does not clear organization_id from Tickets [3703](https://github.com/zammad/zammad/issues/3703) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Merge not possible with not set, required attributes [2634](https://github.com/zammad/zammad/issues/2634) [[bug](https://github.com/zammad/zammad/labels/bug)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)]
- Merging tickets doesnt trigger notification for target ticket [3105](https://github.com/zammad/zammad/issues/3105) [[bug](https://github.com/zammad/zammad/labels/bug)] [[notification](https://github.com/zammad/zammad/labels/notification)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- One of DB migrations timestamp breaks migrations queue [3702](https://github.com/zammad/zammad/issues/3702) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Tags in ticket create screen displayed wrong [3701](https://github.com/zammad/zammad/issues/3701) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[regression](https://github.com/zammad/zammad/labels/regression)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- Custom date attributes provide inconsistent sorting within grouping [3663](https://github.com/zammad/zammad/issues/3663) [[bug](https://github.com/zammad/zammad/labels/bug)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Mix of binary encoded ISO-8859-1 data in header fields (e.g. to) fails mail processing [3697](https://github.com/zammad/zammad/issues/3697) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail processing)]
- Zammad sends mails even though there is no email address visible in TO or CC fields (any more) [3554](https://github.com/zammad/zammad/issues/3554) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- Error 500 / zammad {"error":" 123456 is out of range for ActiveModel::Type::Integer with limit 4 bytes"} [3647](https://github.com/zammad/zammad/issues/3647) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Default value not set for attributes of type input, select, tree_select, richtext, textarea, checkbox [1653](https://github.com/zammad/zammad/issues/1653) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[object manager attribute](https://github.com/zammad/zammad/labels/object manager attribute)]
- When replying, quote article content only [3539](https://github.com/zammad/zammad/issues/3539) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Trigger ignores changes on some Ticket attributes [3428](https://github.com/zammad/zammad/issues/3428) [[bug](https://github.com/zammad/zammad/labels/bug)] [[trigger](https://github.com/zammad/zammad/labels/trigger)]
- KB search does not allow pagination on endpoint [3068](https://github.com/zammad/zammad/issues/3068) [[bug](https://github.com/zammad/zammad/labels/bug)] [[API](https://github.com/zammad/zammad/labels/API)] [[search](https://github.com/zammad/zammad/labels/search)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- “You have not created a ticket yet” shown but I already have closed tickets [3053](https://github.com/zammad/zammad/issues/3053) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[🚧 refactoring 2.0 🚧](https://github.com/zammad/zammad/labels/🚧 refactoring 2.0 🚧)]
- Support HTML5 'required' attribute in forms [1890](https://github.com/zammad/zammad/pull/1890)
- Freshdesk import works not with more then 30_000 tickets [3681](https://github.com/zammad/zammad/issues/3681) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Pagination for knowledge base answer sorting breaks sorting [3660](https://github.com/zammad/zammad/issues/3660) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[admin area](https://github.com/zammad/zammad/labels/admin area)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- Zendesk-Import `Connection reset by peer` cancels import [3583](https://github.com/zammad/zammad/issues/3583) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[waiting for feedback](https://github.com/zammad/zammad/labels/waiting for feedback)]
- Prefer HTTP standard header "From" over custom "X-On-Behalf-Of" for impersonation [3113](https://github.com/zammad/zammad/issues/3113) [[API](https://github.com/zammad/zammad/labels/API)] [[help appreciated](https://github.com/zammad/zammad/labels/help appreciated)] [[authentication](https://github.com/zammad/zammad/labels/authentication)] [[hacktoberfest](https://github.com/zammad/zammad/labels/hacktoberfest)] [[:construction: refactoring :construction:](https://github.com/zammad/zammad/labels/:construction: refactoring :construction:)] [[specification required](https://github.com/zammad/zammad/labels/specification required)] [[good first issue](https://github.com/zammad/zammad/labels/good first issue)] [[deprecation](https://github.com/zammad/zammad/labels/deprecation)]
- Do not send `domain` and migrate `domain` out of Google and Microsoft 365 channels [3669](https://github.com/zammad/zammad/issues/3669) [[bug](https://github.com/zammad/zammad/labels/bug)] [[channel](https://github.com/zammad/zammad/labels/channel)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- high organization user count relates to bad performance [3648](https://github.com/zammad/zammad/issues/3648) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[performance](https://github.com/zammad/zammad/labels/performance)]
- Removing organizations removes user and ticket as well [3688](https://github.com/zammad/zammad/issues/3688) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Wrong user is used when "X-On-Behalf-Of” header value is an email that starts with digits [2851](https://github.com/zammad/zammad/issues/2851) [[bug](https://github.com/zammad/zammad/labels/bug)] [[API](https://github.com/zammad/zammad/labels/API)]
- Allow out of office for one day without setting two days [3590](https://github.com/zammad/zammad/issues/3590) [[bug](https://github.com/zammad/zammad/labels/bug)] [[personal settings/menu](https://github.com/zammad/zammad/labels/personal settings/menu)]
- FreshDesk Import doesn't pull in auto-assign domain(s) for organizations [3687](https://github.com/zammad/zammad/issues/3687) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- FreshDesk Import brings in all users as inactive [3689](https://github.com/zammad/zammad/issues/3689) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- KB Public UI icons are misspaced [3680](https://github.com/zammad/zammad/issues/3680) [[bug](https://github.com/zammad/zammad/labels/bug)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- FreshDesk Import Error - undefined method `body' for 10:Integer [3661](https://github.com/zammad/zammad/issues/3661) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Cannot select multiple tickets in ticket overview with shift+click in Firefox [3449](https://github.com/zammad/zammad/issues/3449) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[overviews](https://github.com/zammad/zammad/labels/overviews)]
- "Drop files here" drag area not always hiding [3460](https://github.com/zammad/zammad/issues/3460) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[help appreciated](https://github.com/zammad/zammad/labels/help appreciated)]
- CTI Callerlog signaling hides "+" for new ticket if more than one user is found [2930](https://github.com/zammad/zammad/issues/2930) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Zendesk URL check fails with Net::HTTPForbidden 403 error [3679](https://github.com/zammad/zammad/issues/3679) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Mac Mail inline PDF destroys E-Mail-Body [2407](https://github.com/zammad/zammad/issues/2407) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail processing)]
- Outdated urls on security page (third-party logins) [3627](https://github.com/zammad/zammad/issues/3627) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Duplicated article after bulk action was executed for newly created tickets without a browser refresh in between [3568](https://github.com/zammad/zammad/issues/3568) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Text Editor deletes text unrecoverably if quicktext was canceled with Ctrl+Backspace [2886](https://github.com/zammad/zammad/issues/2886) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- The defined ignored attributes in the popover context are not working [3668](https://github.com/zammad/zammad/issues/3668) [[bug](https://github.com/zammad/zammad/labels/bug)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Ensure Upload Cache files are removed after grace period [3579](https://github.com/zammad/zammad/issues/3579) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Package installation fails because of too long file names [3666](https://github.com/zammad/zammad/issues/3666) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Package migrations fail on package installation or update due to codebase self-modification [3580](https://github.com/zammad/zammad/issues/3580) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core](https://github.com/zammad/zammad/labels/core)]
- saving Boolean field with empty values [2973](https://github.com/zammad/zammad/issues/2973) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- CTI-API should handle doubled requests better [3247](https://github.com/zammad/zammad/issues/3247) [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[CTI](https://github.com/zammad/zammad/labels/CTI)] [[specification required](https://github.com/zammad/zammad/labels/specification required)]
- In some situations the chat button is visible without a active websocket connection [2258](https://github.com/zammad/zammad/issues/2258) [[bug](https://github.com/zammad/zammad/labels/bug)] [[chat](https://github.com/zammad/zammad/labels/chat)]
- Fixes mistypes in article_view.coffee [3658](https://github.com/zammad/zammad/pull/3658)
- Creating and editing users via office 365 failes with Image source is invalid [3617](https://github.com/zammad/zammad/issues/3617) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- FreshDesk Import fails with timeout error [3653](https://github.com/zammad/zammad/issues/3653) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Chat widget cannot load CSS on (sub)domains that contain "ws" characters [3654](https://github.com/zammad/zammad/issues/3654) [[bug](https://github.com/zammad/zammad/labels/bug)] [[chat](https://github.com/zammad/zammad/labels/chat)]
- timezone issue with elasticsearch [2085](https://github.com/zammad/zammad/issues/2085) [[duplicate](https://github.com/zammad/zammad/labels/duplicate)]
- Invalid html signature detection for exchange warning boxes [3571](https://github.com/zammad/zammad/issues/3571) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Searching for integer fields does not work as expected [3599](https://github.com/zammad/zammad/issues/3599) [[bug](https://github.com/zammad/zammad/labels/bug)] [[search](https://github.com/zammad/zammad/labels/search)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- FreshDesk import fails on certain custom field types [3628](https://github.com/zammad/zammad/issues/3628) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Freshdesk import subdomain selection fails [3631](https://github.com/zammad/zammad/issues/3631) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Search results missing for users with two names within lastname [3598](https://github.com/zammad/zammad/issues/3598) [[bug](https://github.com/zammad/zammad/labels/bug)] [[search](https://github.com/zammad/zammad/labels/search)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- New location notification with X-On-Behalf [3611](https://github.com/zammad/zammad/issues/3611) [[bug](https://github.com/zammad/zammad/labels/bug)] [[API](https://github.com/zammad/zammad/labels/API)] [[notification](https://github.com/zammad/zammad/labels/notification)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- State list of tickets ignore locale for their sorting [3335](https://github.com/zammad/zammad/issues/3335) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Newly created users are only shown in the admin interface after reload [3050](https://github.com/zammad/zammad/issues/3050) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend / JS app)]
- Migration 3.6.1 to 4.1 : No configured business hours found! [3641](https://github.com/zammad/zammad/issues/3641) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Verification tokens questionable behavior in developer mode [3116](https://github.com/zammad/zammad/issues/3116) [[developer experience](https://github.com/zammad/zammad/labels/developer experience)]
- Replacing a mention with a new leads to mentioning both agents [3636](https://github.com/zammad/zammad/issues/3636) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Attachment order is wrong [3584](https://github.com/zammad/zammad/issues/3584) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)]
- When disconnecting a Chat, customer can still continue posting messages [2559](https://github.com/zammad/zammad/issues/2559) [[bug](https://github.com/zammad/zammad/labels/bug)] [[chat](https://github.com/zammad/zammad/labels/chat)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- some macros are hidden in the drag & drop- overview with a small screen size [3359](https://github.com/zammad/zammad/issues/3359) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Add redis as an (optional) session store backend [3450](https://github.com/zammad/zammad/pull/3450)
- Text Module widget is broken/hidden after pressing backspace (once) [3637](https://github.com/zammad/zammad/issues/3637) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Mention widget show same users several times (if rest requests will return in different order) [3639](https://github.com/zammad/zammad/issues/3639) [[bug](https://github.com/zammad/zammad/labels/bug)]
- The rebuild of the index is failing [3633](https://github.com/zammad/zammad/issues/3633) [[bug](https://github.com/zammad/zammad/labels/bug)] [[chat](https://github.com/zammad/zammad/labels/chat)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Monitoring endpoint complains about `Failed to run SessionTimeoutJob.perform_now after 10 tries #<NoMethodError: undefined method `id' for nil:NilClass` [3632](https://github.com/zammad/zammad/issues/3632) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Updating package-based installations can break the front end. [3629](https://github.com/zammad/zammad/issues/3629) [[bug](https://github.com/zammad/zammad/labels/bug)]
- backup: stop using su for pg_dump [3352](https://github.com/zammad/zammad/pull/3352) [[waiting for feedback](https://github.com/zammad/zammad/labels/waiting for feedback)]
- Reply-to header ignored if from contains a system address [2551](https://github.com/zammad/zammad/issues/2551) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Maintenance: Fix handling of test that require secrets not to run for GitHub PRs. [3626](https://github.com/zammad/zammad/pull/3626)
- replacing find -mtime with find -mmin [3570](https://github.com/zammad/zammad/pull/3570)
- Ensure to migrate old calendar URLs for google calendar sources [3618](https://github.com/zammad/zammad/issues/3618) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Mentions/Subscribe with read permissions [3615](https://github.com/zammad/zammad/issues/3615) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Chat-Message references not cleared with data privacy task [3610](https://github.com/zammad/zammad/issues/3610) [[bug](https://github.com/zammad/zammad/labels/bug)] [[data privacy](https://github.com/zammad/zammad/labels/data privacy)]
- Overview names are hidden in mobile view for RTL languages [3500](https://github.com/zammad/zammad/issues/3500) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[mobile](https://github.com/zammad/zammad/labels/mobile)]
- SMTP-Attachments missing when using the API under high load [2991](https://github.com/zammad/zammad/issues/2991) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Inline image conversion from jpeg to png causes huge overhead [3538](https://github.com/zammad/zammad/issues/3538) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- session timeout does regulary logout active users before timeout because of dead old sessions [3605](https://github.com/zammad/zammad/issues/3605) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Zendesk import creates new ticket numbers rather than using the Zendesk ticket IDs also as ticket numbers in Zammad [3593](https://github.com/zammad/zammad/issues/3593) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- wrong behaviour for the disabled option in session timeout [3600](https://github.com/zammad/zammad/issues/3600) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Header links are not responsive [3133](https://github.com/zammad/zammad/issues/3133) [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- Update description of the session timeout setting [3597](https://github.com/zammad/zammad/issues/3597) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin area)]
- Escalation calculation breaks data privacy ticket deletion [3588](https://github.com/zammad/zammad/issues/3588) [[bug](https://github.com/zammad/zammad/labels/bug)] [[data privacy](https://github.com/zammad/zammad/labels/data privacy)]
- `SessionTimeoutJob.perform_now` fails if user no longer exists [3586](https://github.com/zammad/zammad/issues/3586) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Robots.txt should allow indexing Knowledge Base on custom URLs [3164](https://github.com/zammad/zammad/issues/3164) [[bug](https://github.com/zammad/zammad/labels/bug)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- DataPrivacy may fail to clear user relations [3585](https://github.com/zammad/zammad/issues/3585) [[bug](https://github.com/zammad/zammad/labels/bug)] [[data privacy](https://github.com/zammad/zammad/labels/data privacy)]
- SessionTimeoutJob.perform_now scheduler job fails on update if scheduler process wasn't restarted [3581](https://github.com/zammad/zammad/issues/3581) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Freshdesk import attribute ID mapping lookup constants fail application boot in systems with changed default names [3582](https://github.com/zammad/zammad/issues/3582) [[bug](https://github.com/zammad/zammad/labels/bug)]
- mentioned KB entries with the same title in different categories can not distinguished [3559](https://github.com/zammad/zammad/issues/3559) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge base)]
- Invalid auto assignment conditions may break ticket view for unassigned tickets [3567](https://github.com/zammad/zammad/issues/3567) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX/UI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised by payment)]
- Add Greek translation for chat [3569](https://github.com/zammad/zammad/pull/3569) [[chat](https://github.com/zammad/zammad/labels/chat)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- Freshdesk [865](https://github.com/zammad/zammad/issues/865) [[feature backlog](https://github.com/zammad/zammad/labels/feature backlog)] [[import](https://github.com/zammad/zammad/labels/import)]
- Old JQuery version delivered [3431](https://github.com/zammad/zammad/issues/3431) [[bug](https://github.com/zammad/zammad/labels/bug)] [[chat](https://github.com/zammad/zammad/labels/chat)]

View file

@ -3,8 +3,8 @@
source 'https://gems.sutty.nl' source 'https://gems.sutty.nl'
# core - base # core - base
ruby '2.7.5' ruby '2.7.3'
gem 'rails', '~> 6.0' gem 'rails', '~> 6.0.0'
# core - rails additions # core - rails additions
gem 'activerecord-import' gem 'activerecord-import'
@ -198,6 +198,7 @@ group :development, :test do
gem 'overcommit' gem 'overcommit'
gem 'rubocop' gem 'rubocop'
gem 'rubocop-faker' gem 'rubocop-faker'
gem 'rubocop-inflector'
gem 'rubocop-performance' gem 'rubocop-performance'
gem 'rubocop-rails' gem 'rubocop-rails'
gem 'rubocop-rspec' gem 'rubocop-rspec'

View file

@ -21,50 +21,50 @@ GEM
specs: specs:
aasm (5.2.0) aasm (5.2.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
actioncable (6.0.4.7) actioncable (6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailbox (6.0.4.7) actionmailbox (6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
activejob (= 6.0.4.7) activejob (= 6.0.4.1)
activerecord (= 6.0.4.7) activerecord (= 6.0.4.1)
activestorage (= 6.0.4.7) activestorage (= 6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
mail (>= 2.7.1) mail (>= 2.7.1)
actionmailer (6.0.4.7) actionmailer (6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
actionview (= 6.0.4.7) actionview (= 6.0.4.1)
activejob (= 6.0.4.7) activejob (= 6.0.4.1)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (6.0.4.7) actionpack (6.0.4.1)
actionview (= 6.0.4.7) actionview (= 6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
rack (~> 2.0, >= 2.0.8) rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.4.7) actiontext (6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
activerecord (= 6.0.4.7) activerecord (= 6.0.4.1)
activestorage (= 6.0.4.7) activestorage (= 6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (6.0.4.7) actionview (6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.4.7) activejob (6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (6.0.4.7) activemodel (6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
activerecord (6.0.4.7) activerecord (6.0.4.1)
activemodel (= 6.0.4.7) activemodel (= 6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
activerecord-import (1.2.0) activerecord-import (1.2.0)
activerecord (>= 3.2) activerecord (>= 3.2)
activerecord-nulldb-adapter (0.7.0) activerecord-nulldb-adapter (0.7.0)
@ -75,12 +75,12 @@ GEM
multi_json (~> 1.11, >= 1.11.2) multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 3) rack (>= 2.0.8, < 3)
railties (>= 5.2.4.1) railties (>= 5.2.4.1)
activestorage (6.0.4.7) activestorage (6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
activejob (= 6.0.4.7) activejob (= 6.0.4.1)
activerecord (= 6.0.4.7) activerecord (= 6.0.4.1)
marcel (~> 1.0.0) marcel (~> 1.0.0)
activesupport (6.0.4.7) activesupport (6.0.4.1)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
@ -90,31 +90,31 @@ GEM
activerecord (>= 4.2) activerecord (>= 4.2)
addressable (2.8.0) addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
argon2 (2.0.3) argon2 (2.1.1)
ffi (~> 1.14) ffi (~> 1.14)
ffi-compiler (~> 1.0) ffi-compiler (~> 1.0)
argon2 (2.0.3-x86_64-linux-musl) argon2 (2.0.3-x86_64-linux-musl)
ffi (~> 1.14) ffi (~> 1.14)
ffi-compiler (~> 1.0) ffi-compiler (~> 1.0)
ast (2.4.2) ast (2.4.2)
async (1.29.1) async (1.30.1)
console (~> 1.10) console (~> 1.10)
nio4r (~> 2.3) nio4r (~> 2.3)
timers (~> 4.1) timers (~> 4.1)
async-http (0.56.3) async-http (0.56.5)
async (~> 1.25) async (>= 1.25)
async-io (~> 1.28) async-io (>= 1.28)
async-pool (~> 0.2) async-pool (>= 0.2)
protocol-http (~> 0.22.0) protocol-http (~> 0.22.0)
protocol-http1 (~> 0.14.0) protocol-http1 (~> 0.14.0)
protocol-http2 (~> 0.14.0) protocol-http2 (~> 0.14.0)
async-http-faraday (0.11.0) async-http-faraday (0.11.0)
async-http (~> 0.42) async-http (~> 0.42)
faraday faraday
async-io (1.32.1) async-io (1.32.2)
async (~> 1.14) async
async-pool (0.3.7) async-pool (0.3.9)
async (~> 1.25) async (>= 1.25)
autoprefixer-rails (10.3.3.0) autoprefixer-rails (10.3.3.0)
execjs (~> 2) execjs (~> 2)
binding_of_caller (1.0.0) binding_of_caller (1.0.0)
@ -188,7 +188,7 @@ GEM
docile (1.4.0) docile (1.4.0)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.5.2) doorkeeper (5.5.4)
railties (>= 5) railties (>= 5)
dotenv (2.7.6) dotenv (2.7.6)
eco (1.0.0) eco (1.0.0)
@ -232,9 +232,9 @@ GEM
faraday-net_http_persistent (1.2.0) faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0) faraday-patron (1.0.0)
faraday-rack (1.0.0) faraday-rack (1.0.0)
faraday_middleware (1.0.0) faraday_middleware (1.1.0)
faraday (~> 1.0) faraday (~> 1.0)
ffi (1.15.3-x86_64-linux-musl) ffi (1.15.4-x86_64-linux-musl)
ffi-compiler (1.0.1) ffi-compiler (1.0.1)
ffi (>= 1.0.0) ffi (>= 1.0.0)
rake rake
@ -250,7 +250,7 @@ GEM
rainbow (>= 2.2.1) rainbow (>= 2.2.1)
rake (>= 10.0) rake (>= 10.0)
gli (2.20.1) gli (2.20.1)
globalid (1.0.0) globalid (0.5.2)
activesupport (>= 5.0) activesupport (>= 5.0)
gmail_xoauth (0.4.2) gmail_xoauth (0.4.2)
oauth (>= 0.3.6) oauth (>= 0.3.6)
@ -291,7 +291,7 @@ GEM
http_parser.rb (0.6.0) http_parser.rb (0.6.0)
http_parser.rb (0.6.0-x86_64-linux-musl) http_parser.rb (0.6.0-x86_64-linux-musl)
httpclient (2.8.3) httpclient (2.8.3)
i18n (1.10.0) i18n (1.8.10)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
icalendar (2.7.1) icalendar (2.7.1)
ice_cube (~> 0.16) ice_cube (~> 0.16)
@ -302,24 +302,24 @@ GEM
inflection (1.0.0) inflection (1.0.0)
iniparse (1.5.0) iniparse (1.5.0)
interception (0.5) interception (0.5)
json (2.5.1)
json (2.5.1-x86_64-linux-musl) json (2.5.1-x86_64-linux-musl)
jwt (2.2.3) jwt (2.3.0)
kgio (2.11.4) kgio (2.11.4)
kgio (2.11.4-x86_64-linux-musl) kgio (2.11.4-x86_64-linux-musl)
koala (3.0.0) koala (3.0.0)
addressable addressable
faraday faraday
json (>= 1.8) json (>= 1.8)
libv8 (8.4.255.0)
libv8 (8.4.255.0-x86_64-linux) libv8 (8.4.255.0-x86_64-linux)
listen (3.5.1) listen (3.7.0)
rb-fsevent (~> 0.10, >= 0.10.3) rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10) rb-inotify (~> 0.9, >= 0.9.10)
little-plugger (1.1.4) little-plugger (1.1.4)
logging (2.3.0) logging (2.3.0)
little-plugger (~> 1.1) little-plugger (~> 1.1)
multi_json (~> 1.14) multi_json (~> 1.14)
loofah (2.14.0) loofah (2.12.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
lumberjack (1.2.8) lumberjack (1.2.8)
@ -330,12 +330,12 @@ GEM
method_source (1.0.0) method_source (1.0.0)
mime-types (3.3.1) mime-types (3.3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2021.0225) mime-types-data (3.2021.0901)
mini_mime (1.1.2) mini_mime (1.1.1)
mini_portile2 (2.8.0) mini_portile2 (2.6.1)
mini_racer (0.2.9) mini_racer (0.2.9)
libv8 (>= 6.9.411) libv8 (>= 6.9.411)
minitest (5.15.0) minitest (5.14.4)
msgpack (1.4.2) msgpack (1.4.2)
msgpack (1.4.2-x86_64-linux-musl) msgpack (1.4.2-x86_64-linux-musl)
multi_json (1.15.0) multi_json (1.15.0)
@ -350,11 +350,11 @@ GEM
netrc (0.11.0) netrc (0.11.0)
nio4r (2.5.8) nio4r (2.5.8)
nio4r (2.5.8-x86_64-linux-musl) nio4r (2.5.8-x86_64-linux-musl)
nokogiri (1.13.3) nokogiri (1.12.5)
mini_portile2 (~> 2.8.0) mini_portile2 (~> 2.6.1)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.13.3-x86_64-linux-musl) nokogiri (1.12.5-x86_64-linux-musl)
mini_portile2 (~> 2.8.0) mini_portile2 (~> 2.6.1)
racc (~> 1.4) racc (~> 1.4)
nori (2.6.0) nori (2.6.0)
notiffany (0.1.3) notiffany (0.1.3)
@ -422,8 +422,8 @@ GEM
pg (0.21.0-x86_64-linux-musl) pg (0.21.0-x86_64-linux-musl)
power_assert (2.0.1) power_assert (2.0.1)
protocol-hpack (1.4.2) protocol-hpack (1.4.2)
protocol-http (0.22.4) protocol-http (0.22.5)
protocol-http1 (0.14.1) protocol-http1 (0.14.2)
protocol-http (~> 0.22) protocol-http (~> 0.22)
protocol-http2 (0.14.2) protocol-http2 (0.14.2)
protocol-hpack (~> 1.4) protocol-hpack (~> 1.4)
@ -443,7 +443,7 @@ GEM
binding_of_caller (~> 1.0) binding_of_caller (~> 1.0)
pry (~> 0.13) pry (~> 0.13)
public_suffix (4.0.6) public_suffix (4.0.6)
puma (4.3.11) puma (4.3.10)
nio4r (~> 2.0) nio4r (~> 2.0)
puma (4.3.8-x86_64-linux-musl) puma (4.3.8-x86_64-linux-musl)
nio4r (~> 2.0) nio4r (~> 2.0)
@ -451,27 +451,27 @@ GEM
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
pundit-matchers (1.7.0) pundit-matchers (1.7.0)
rspec-rails (>= 3.0.0) rspec-rails (>= 3.0.0)
racc (1.6.0) racc (1.5.2)
racc (1.6.0-x86_64-linux-musl) racc (1.5.2-x86_64-linux-musl)
rack (2.2.3) rack (2.2.3)
rack-livereload (0.3.17) rack-livereload (0.3.17)
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rails (6.0.4.7) rails (6.0.4.1)
actioncable (= 6.0.4.7) actioncable (= 6.0.4.1)
actionmailbox (= 6.0.4.7) actionmailbox (= 6.0.4.1)
actionmailer (= 6.0.4.7) actionmailer (= 6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
actiontext (= 6.0.4.7) actiontext (= 6.0.4.1)
actionview (= 6.0.4.7) actionview (= 6.0.4.1)
activejob (= 6.0.4.7) activejob (= 6.0.4.1)
activemodel (= 6.0.4.7) activemodel (= 6.0.4.1)
activerecord (= 6.0.4.7) activerecord (= 6.0.4.1)
activestorage (= 6.0.4.7) activestorage (= 6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 6.0.4.7) railties (= 6.0.4.1)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
@ -482,9 +482,9 @@ GEM
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.4.2) rails-html-sanitizer (1.4.2)
loofah (~> 2.3) loofah (~> 2.3)
railties (6.0.4.7) railties (6.0.4.1)
actionpack (= 6.0.4.7) actionpack (= 6.0.4.1)
activesupport (= 6.0.4.7) activesupport (= 6.0.4.1)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0) thor (>= 0.20.3, < 2.0)
@ -521,38 +521,41 @@ GEM
rspec-mocks (~> 3.10) rspec-mocks (~> 3.10)
rspec-support (~> 3.10) rspec-support (~> 3.10)
rspec-support (3.10.2) rspec-support (3.10.2)
rszr (0.5.2)
rszr (0.5.2-x86_64-linux-musl) rszr (0.5.2-x86_64-linux-musl)
rubocop (1.21.0) rubocop (1.22.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.0.0.0) parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0) regexp_parser (>= 1.8, < 3.0)
rexml rexml
rubocop-ast (>= 1.9.1, < 2.0) rubocop-ast (>= 1.12.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0) unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.11.0) rubocop-ast (1.12.0)
parser (>= 3.0.1.1) parser (>= 3.0.1.1)
rubocop-faker (1.1.0) rubocop-faker (1.1.0)
faker (>= 2.12.0) faker (>= 2.12.0)
rubocop (>= 0.82.0) rubocop (>= 0.82.0)
rubocop-inflector (0.1.1)
activesupport
rubocop
rubocop-rspec
rubocop-performance (1.11.5) rubocop-performance (1.11.5)
rubocop (>= 1.7.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0) rubocop-ast (>= 0.4.0)
rubocop-rails (2.12.2) rubocop-rails (2.12.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.7.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
rubocop-rspec (2.5.0) rubocop-rspec (2.5.0)
rubocop (~> 1.19) rubocop (~> 1.19)
ruby-progressbar (1.11.0) ruby-progressbar (1.11.0)
ruby-saml (1.12.2) ruby-saml (1.13.0)
nokogiri (>= 1.10.5) nokogiri (>= 1.10.5)
rexml rexml
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
rubyntlm (0.6.3) rubyntlm (0.6.3)
rubyzip (2.3.0) rubyzip (2.3.2)
sassc (2.4.0) sassc (2.4.0)
ffi (~> 1.9) ffi (~> 1.9)
sassc (2.4.0-x86_64-linux-musl) sassc (2.4.0-x86_64-linux-musl)
@ -597,9 +600,9 @@ GEM
sprockets (3.7.2) sprockets (3.7.2)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (3.4.2) sprockets-rails (3.2.2)
actionpack (>= 5.2) actionpack (>= 4.0)
activesupport (>= 5.2) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sync (0.5.0) sync (0.5.0)
tcr (0.2.2) tcr (0.2.2)
@ -610,13 +613,13 @@ GEM
tins (~> 1.0) tins (~> 1.0)
test-unit (3.4.7) test-unit (3.4.7)
power_assert power_assert
thor (1.2.1) thor (1.1.0)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.10) tilt (2.0.10)
timers (4.3.3) timers (4.3.3)
tins (1.29.1) tins (1.29.1)
sync sync
twilio-ruby (5.58.3) twilio-ruby (5.59.0)
faraday (>= 0.9, < 2.0) faraday (>= 0.9, < 2.0)
jwt (>= 1.5, <= 2.5) jwt (>= 1.5, <= 2.5)
nokogiri (>= 1.6, < 2.0) nokogiri (>= 1.6, < 2.0)
@ -637,7 +640,8 @@ GEM
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.7-x86_64-linux-musl) unf_ext (0.0.8)
unf_ext (0.0.8-x86_64-linux-musl)
unicode-display_width (2.1.0) unicode-display_width (2.1.0)
unicorn (6.0.0) unicorn (6.0.0)
kgio (~> 2.6) kgio (~> 2.6)
@ -666,7 +670,7 @@ GEM
writeexcel (1.0.5) writeexcel (1.0.5)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.5.4) zeitwerk (2.4.2)
zendesk_api (1.33.0) zendesk_api (1.33.0)
faraday (>= 0.9.0, < 2.0.0) faraday (>= 0.9.0, < 2.0.0)
hashie (>= 3.5.2, < 5.0.0) hashie (>= 3.5.2, < 5.0.0)
@ -753,7 +757,7 @@ DEPENDENCIES
pundit pundit
pundit-matchers pundit-matchers
rack-livereload rack-livereload
rails (~> 6.0) rails (~> 6.0.0)
rails-controller-testing rails-controller-testing
rb-fsevent rb-fsevent
rchardet (>= 1.8.0) rchardet (>= 1.8.0)
@ -762,6 +766,7 @@ DEPENDENCIES
rszr (= 0.5.2) rszr (= 0.5.2)
rubocop rubocop
rubocop-faker rubocop-faker
rubocop-inflector
rubocop-performance rubocop-performance
rubocop-rails rubocop-rails
rubocop-rspec rubocop-rspec
@ -792,7 +797,7 @@ DEPENDENCIES
zendesk_api zendesk_api
RUBY VERSION RUBY VERSION
ruby 2.7.5p203 ruby 2.7.3p183
BUNDLED WITH BUNDLED WITH
2.2.20 2.2.27

View file

@ -1 +1 @@
5.0.x 5.1.x

View file

@ -300,10 +300,9 @@ class App.Controller extends Spine.Controller
frontendTimeUpdateItem: (item, currentVal) => frontendTimeUpdateItem: (item, currentVal) =>
timestamp = item.attr('datetime') timestamp = item.attr('datetime')
return if timestamp is 'null' time = @humanTime(timestamp, item.hasClass('escalation'))
# only do dom updates on changes # only do dom updates on changes
time = @humanTime(timestamp, item.hasClass('escalation'))
return if time is currentVal return if time is currentVal
newTitle = App.i18n.translateTimestamp(timestamp) newTitle = App.i18n.translateTimestamp(timestamp)

View file

@ -418,11 +418,11 @@ class App.ControllerForm extends App.Controller
if !@constructor.fieldIsMandatory(field_by_name) if !@constructor.fieldIsMandatory(field_by_name)
field_by_name.attr('required', true) field_by_name.attr('required', true)
field_by_name.closest('.form-group').find('label span').html('*') field_by_name.parents('.form-group').find('label span').html('*')
field_by_name.closest('.form-group').addClass('is-required') field_by_name.closest('.form-group').addClass('is-required')
if !@constructor.fieldIsMandatory(field_by_data) if !@constructor.fieldIsMandatory(field_by_data)
field_by_data.attr('required', true) field_by_data.attr('required', true)
field_by_data.closest('.form-group').find('label span').html('*') field_by_data.parents('.form-group').find('label span').html('*')
field_by_data.closest('.form-group').addClass('is-required') field_by_data.closest('.form-group').addClass('is-required')
optional: (name, el = @form) -> optional: (name, el = @form) ->
@ -434,11 +434,11 @@ class App.ControllerForm extends App.Controller
if @constructor.fieldIsMandatory(field_by_name) if @constructor.fieldIsMandatory(field_by_name)
field_by_name.attr('required', false) field_by_name.attr('required', false)
field_by_name.closest('.form-group').find('label span').html('') field_by_name.parents('.form-group').find('label span').html('')
field_by_name.closest('.form-group').removeClass('is-required') field_by_name.closest('.form-group').removeClass('is-required')
if @constructor.fieldIsMandatory(field_by_data) if @constructor.fieldIsMandatory(field_by_data)
field_by_data.attr('required', false) field_by_data.attr('required', false)
field_by_data.closest('.form-group').find('label span').html('') field_by_data.parents('.form-group').find('label span').html('')
field_by_data.closest('.form-group').removeClass('is-required') field_by_data.closest('.form-group').removeClass('is-required')
readonly: (name, el = @form) -> readonly: (name, el = @form) ->

View file

@ -2,7 +2,6 @@ class App.ControllerObserver extends App.Controller
model: 'Ticket' model: 'Ticket'
template: 'tba' template: 'tba'
globalRerender: true globalRerender: true
lastAttributes: undefined
### ###
observe: observe:
@ -26,7 +25,7 @@ class App.ControllerObserver extends App.Controller
# rerender, e. g. on language change # rerender, e. g. on language change
if @globalRerender if @globalRerender
@controllerBind('ui:rerender', => @controllerBind('ui:rerender', =>
@lastAttributes = undefined @lastAttributres = undefined
@maybeRender(App[@model].fullLocal(@object_id)) @maybeRender(App[@model].fullLocal(@object_id))
) )
@ -44,40 +43,32 @@ class App.ControllerObserver extends App.Controller
if !@subscribeId if !@subscribeId
@subscribeId = object.subscribe(@subscribe) @subscribeId = object.subscribe(@subscribe)
return if !@hasChanged(object) # remember current attributes
@render(object)
hasChanged: (object) =>
currentAttributes = {} currentAttributes = {}
objectCloned = $.extend(true, {}, object)
if @observe if @observe
for key, active of @observe for key, active of @observe
if active && !_.isFunction(value) if active
currentAttributes[key] = objectCloned[key] currentAttributes[key] = object[key]
if @observeNot if @observeNot
for key, value of objectCloned for key, value of object
if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value) if key isnt 'cid' && !@observeNot[key] && !_.isFunction(value) && !_.isObject(value)
currentAttributes[key] = value currentAttributes[key] = value
if !@lastAttributes if !@lastAttributres
@lastAttributes = currentAttributes @lastAttributres = {}
return true else
diff = difference(currentAttributes, @lastAttributres)
diff = difference(currentAttributes, @lastAttributes) if _.isEmpty(diff)
if _.isEmpty(diff) @log 'debug', 'maybeRender no diff, no rerender'
@log 'debug', 'maybeRender no diff, no rerender' return
return false
@log 'debug', 'maybeRender.diff', diff, @observe, @model @log 'debug', 'maybeRender.diff', diff, @observe, @model
@lastAttributes = currentAttributes @lastAttributres = currentAttributes
true @render(object, diff)
render: (object) => render: (object, diff) =>
@log 'debug', 'render', @template, object @log 'debug', 'render', @template, object, diff
@html App.view(@template)( @html App.view(@template)(
object: object object: object
) )

View file

@ -493,6 +493,16 @@ class App.ControllerTable extends App.Controller
sortable: @dndCallback sortable: @dndCallback
)) ))
getGroupByKeyName: (object, groupBy) ->
reference_key = groupBy + '_id'
if reference_key of object
attribute = _.findWhere(object.constructor.configure_attributes, { name: reference_key })
return App[attribute.relation]?.find(object[reference_key])?.displayName() || reference_key
groupBy
sortObjectKeys: (objects, direction) -> sortObjectKeys: (objects, direction) ->
sorted = Object.keys(objects).sort() sorted = Object.keys(objects).sort()
@ -515,7 +525,7 @@ class App.ControllerTable extends App.Controller
objectsToShow = @objectsOfPage(@pagerShownPage) objectsToShow = @objectsOfPage(@pagerShownPage)
if @groupBy if @groupBy
# group by raw (and not printable) value so dates work also # group by raw (and not printable) value so dates work also
objectsGrouped = _.groupBy(objectsToShow, (object) => @groupObjectName(object, @groupBy, excludeTags: ['date', 'datetime'])) objectsGrouped = _.groupBy(objectsToShow, (object) => object[@getGroupByKeyName(object, @groupBy)])
else else
objectsGrouped = { '': objectsToShow } objectsGrouped = { '': objectsToShow }
@ -855,15 +865,11 @@ class App.ControllerTable extends App.Controller
@objects = localObjects @objects = localObjects
@lastSortedobjects = localObjects @lastSortedobjects = localObjects
groupObjectName: (object, key = undefined, options = {}) -> groupObjectName: (object, key = undefined) ->
group = object group = object
if key if key
if key not of object if key not of object
key += '_id' key += '_id'
# return internal value if needed
return object[key] if options.excludeTags && _.find(@attributesList, (attr) -> attr.name == key && _.contains(options.excludeTags, attr.tag))
group = App.viewPrint(object, key, @attributesList) group = App.viewPrint(object, key, @attributesList)
if _.isEmpty(group) if _.isEmpty(group)
group = '' group = ''

View file

@ -1,9 +0,0 @@
class App.ControllerTechnicalErrorModal extends App.ControllerModal
head: "StatusCode: #{status}"
contentCode: ''
buttonClose: false
buttonSubmit: 'Ok'
onSubmit: (e) -> @close(e)
content: ->
"<pre><code>#{@contentCode}</code></pre>"

View file

@ -428,7 +428,20 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
ui.hide('options::folder') ui.hide('options::folder')
ui.hide('options::keep_on_server') ui.hide('options::keep_on_server')
form = new App.ControllerForm( handlePort = (params, attribute, attributes, classname, form, ui) ->
return if !params
return if !params.options
currentPort = @$('[name="options::port"]').val()
if params.options.ssl is true
if !currentPort || currentPort is '143'
@$('[name="options::port"]').val('993')
return
if params.options.ssl is false
if !currentPort || currentPort is '993'
@$('[name="options::port"]').val('143')
return
new App.ControllerForm(
el: @$('.base-inbound-settings'), el: @$('.base-inbound-settings'),
model: model:
configure_attributes: configureAttributesInbound configure_attributes: configureAttributesInbound
@ -436,16 +449,10 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
params: @account.inbound params: @account.inbound
handlers: [ handlers: [
showHideFolder, showHideFolder,
handlePort,
] ]
) )
form.el.find("select[name='options::ssl']").off('change').on('change', (e) ->
if $(e.target).val() is 'true'
form.el.find("[name='options::port']").val('993')
else
form.el.find("[name='options::port']").val('143')
)
toggleOutboundAdapter: => toggleOutboundAdapter: =>
# fill user / password based on intro info # fill user / password based on intro info

View file

@ -60,30 +60,6 @@ class Form extends App.Controller
placetel_token: App.Setting.get('placetel_token') placetel_token: App.Setting.get('placetel_token')
) )
configure_attributes = [
{
name: 'view_limit',
display: '',
tag: 'select',
null: false,
options: [
{ name: 60, value: 60 }
{ name: 120, value: 120 }
{ name: 180, value: 180 }
{ name: 240, value: 240 }
{ name: 300, value: 300 }
]
},
]
new App.ControllerForm(
el: @$('.js-viewLimit')
model:
configure_attributes: configure_attributes,
params:
view_limit: @config['view_limit']
autofocus: false
)
updateCurrentConfig: => updateCurrentConfig: =>
config = @config config = @config
cleanupInput = @cleanupInput cleanupInput = @cleanupInput
@ -94,10 +70,6 @@ class Form extends App.Controller
default_caller_id = @$('input[name=default_caller_id]').val() default_caller_id = @$('input[name=default_caller_id]').val()
config.outbound.default_caller_id = cleanupInput(default_caller_id) config.outbound.default_caller_id = cleanupInput(default_caller_id)
# default view limit
view_limit = @$('select[name=view_limit]').val()
config.view_limit = parseInt(view_limit)
# routing table # routing table
config.outbound.routing_table = [] config.outbound.routing_table = []
@$('.js-outboundRouting .js-row').each(-> @$('.js-outboundRouting .js-row').each(->

View file

@ -59,42 +59,17 @@ class Form extends App.Controller
config: @config config: @config
) )
configure_attributes = [
{
name: 'view_limit',
display: '',
tag: 'select',
null: false,
options: [
{ name: 60, value: 60 }
{ name: 120, value: 120 }
{ name: 180, value: 180 }
{ name: 240, value: 240 }
{ name: 300, value: 300 }
]
},
]
new App.ControllerForm(
el: @$('.js-viewLimit')
model:
configure_attributes: configure_attributes,
params:
view_limit: @config['view_limit']
autofocus: false
)
updateCurrentConfig: => updateCurrentConfig: =>
config = @config config = @config
cleanupInput = @cleanupInput cleanupInput = @cleanupInput
config.api_user = cleanupInput(@$('input[name=api_user]').val())
config.api_password = cleanupInput(@$('input[name=api_password]').val())
# default caller_id # default caller_id
default_caller_id = @$('input[name=default_caller_id]').val() default_caller_id = @$('input[name=default_caller_id]').val()
config.outbound.default_caller_id = cleanupInput(default_caller_id) config.outbound.default_caller_id = cleanupInput(default_caller_id)
# default view limit
view_limit = @$('select[name=view_limit]').val()
config.view_limit = parseInt(view_limit)
# routing table # routing table
config.outbound.routing_table = [] config.outbound.routing_table = []
@$('.js-outboundRouting .js-row').each(-> @$('.js-outboundRouting .js-row').each(->

View file

@ -96,8 +96,6 @@ class App.UiElement.ApplicationSelector
# ignore passwords and relations # ignore passwords and relations
if row.type isnt 'password' && row.name.substr(row.name.length-4,4) isnt '_ids' && row.searchable isnt false if row.type isnt 'password' && row.name.substr(row.name.length-4,4) isnt '_ids' && row.searchable isnt false
config = _.clone(row) config = _.clone(row)
if config.tag is 'textarea'
config.expanding = false
if config.type is 'email' || config.type is 'tel' if config.type is 'email' || config.type is 'tel'
config.type = 'text' config.type = 'text'
for operatorRegEx, operator of operators_type for operatorRegEx, operator of operators_type

View file

@ -1,9 +0,0 @@
# coffeelint: disable=camel_case_classes
class App.UiElement.auth_provider
@render: (attribute) ->
for key, value of App.Config.get('auth_provider_all')
continue if value.config isnt attribute.provider
attribute.value = "#{App.Config.get('http_type')}://#{App.Config.get('fqdn')}#{value.url}/callback"
break
$( App.view('generic/auth_provider')( attribute: attribute ) )

View file

@ -155,4 +155,4 @@ class App.UiElement.basedate
clear: 'clear' clear: 'clear'
} }
App.i18n.translateDeepPlain(data) App.i18n.translateDeep(data)

View file

@ -50,15 +50,15 @@ class App.UiElement.core_workflow_condition extends App.UiElement.ApplicationSel
operatorsType = operatorsType =
'active$': ['is'] 'active$': ['is']
'boolean$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to'] 'boolean$': ['is', 'is not', 'is set', 'not set']
'integer$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to'] 'integer$': ['is', 'is not', 'is set', 'not set']
'^select$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to'] '^select$': ['is', 'is not', 'is set', 'not set']
'^tree_select$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to'] '^tree_select$': ['is', 'is not', 'is set', 'not set']
'^(input|textarea|richtext)$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to', 'regex match', 'regex mismatch'] '^(input|textarea|richtext)$': ['is', 'is not', 'is set', 'not set', 'regex match', 'regex mismatch']
operatorsName = operatorsName =
'_id$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to'] '_id$': ['is', 'is not', 'is set', 'not set']
'_ids$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to'] '_ids$': ['is', 'is not', 'is set', 'not set']
# merge config # merge config
elements = {} elements = {}
@ -153,8 +153,6 @@ class App.UiElement.core_workflow_condition extends App.UiElement.ApplicationSel
# ignore passwords and relations # ignore passwords and relations
if row.type isnt 'password' && row.name.substr(row.name.length-4,4) isnt '_ids' && row.searchable isnt false if row.type isnt 'password' && row.name.substr(row.name.length-4,4) isnt '_ids' && row.searchable isnt false
config = _.clone(row) config = _.clone(row)
if config.tag is 'textarea'
config.expanding = false
if config.tag is 'select' if config.tag is 'select'
config.multiple = true config.multiple = true
config.default = undefined config.default = undefined
@ -177,7 +175,7 @@ class App.UiElement.core_workflow_condition extends App.UiElement.ApplicationSel
currentOperator = elementRow.find('.js-operator option:selected').attr('value') currentOperator = elementRow.find('.js-operator option:selected').attr('value')
name = @buildValueName(elementFull, elementRow, groupAndAttribute, elements, meta, attribute) name = @buildValueName(elementFull, elementRow, groupAndAttribute, elements, meta, attribute)
if _.contains(['is set', 'not set', 'has changed'], currentOperator) if _.contains(['is set', 'not set'], currentOperator)
elementRow.find('.js-value').addClass('hide').html('<input type="hidden" name="' + name + '" value="true" />') elementRow.find('.js-value').addClass('hide').html('<input type="hidden" name="' + name + '" value="true" />')
return return

View file

@ -128,7 +128,7 @@ class App.UiElement.core_workflow_perform extends App.UiElement.ApplicationSelec
super(elementFull, elementRow, groupAndAttribute, elements, meta, attribute) super(elementFull, elementRow, groupAndAttribute, elements, meta, attribute)
@buildValueConfigMultiple: (config, meta) -> @buildValueConfigMultiple: (config, meta) ->
if _.contains(['add_option', 'remove_option', 'set_fixed_to', 'select'], meta.operator) if _.contains(['add_option', 'remove_option', 'set_fixed_to'], meta.operator)
config.multiple = true config.multiple = true
config.nulloption = true config.nulloption = true
else else

View file

@ -244,7 +244,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
params: params params: params
) )
configureAttributes = [ configureAttributes = [
{ name: 'data_option::diff', display: 'Default time Diff (minutes)', tag: 'integer', null: true }, { name: 'data_option::diff', display: 'Default time Diff (minutes)', tag: 'integer', null: false, default: 24 },
] ]
datetimeDiff = new App.ControllerForm( datetimeDiff = new App.ControllerForm(
model: model:
@ -258,7 +258,7 @@ class App.UiElement.object_manager_attribute extends App.UiElement.ApplicationUi
@date: (item, localParams, params) -> @date: (item, localParams, params) ->
configureAttributes = [ configureAttributes = [
{ name: 'data_option::diff', display: 'Default time Diff (hours)', tag: 'integer', null: true }, { name: 'data_option::diff', display: 'Default time Diff (hours)', tag: 'integer', null: false, default: 24 },
] ]
dateDiff = new App.ControllerForm( dateDiff = new App.ControllerForm(
model: model:

View file

@ -27,8 +27,6 @@ class App.UiElement.richtext
renderFile = (file) -> renderFile = (file) ->
item.find('.attachments').append(App.view('generic/attachment_item')(file)) item.find('.attachments').append(App.view('generic/attachment_item')(file))
attachments.push file attachments.push file
if form.richTextUploadRenderCallback
form.richTextUploadRenderCallback(attribute, attachments)
if params && params.attachments if params && params.attachments
for file in params.attachments for file in params.attachments
@ -56,8 +54,6 @@ class App.UiElement.richtext
return if item.id.toString() is id.toString() return if item.id.toString() is id.toString()
item item
) )
if form.richTextUploadDeleteCallback
form.richTextUploadDeleteCallback(attribute, attachments)
form_id = item.closest('form').find('[name=form_id]').val() form_id = item.closest('form').find('[name=form_id]').val()

View file

@ -8,11 +8,9 @@ class App.UiElement.sla_times
item = $( App.view('generic/sla_times')( item = $( App.view('generic/sla_times')(
attribute: attribute attribute: attribute
first_response_time: params.first_response_time first_response_time: params.first_response_time
response_time: params.response_time
update_time: params.update_time update_time: params.update_time
solution_time: params.solution_time solution_time: params.solution_time
first_response_time_in_text: @toText(params.first_response_time) first_response_time_in_text: @toText(params.first_response_time)
response_time_in_text: @toText(params.response_time)
update_time_in_text: @toText(params.update_time) update_time_in_text: @toText(params.update_time)
solution_time_in_text: @toText(params.solution_time) solution_time_in_text: @toText(params.solution_time)
) ) ) )
@ -28,16 +26,12 @@ class App.UiElement.sla_times
row = element.closest('tr') row = element.closest('tr')
if element.prop('checked') if element.prop('checked')
row.addClass('is-active') row.addClass('is-active')
if row.has('.js-updateTypeSelector').length > 0 && row.has('.js-updateTypeSelector:checked').length == 0
row.find('.js-updateTypeSelector:first').prop('checked', true)
else else
row.removeClass('is-active') row.removeClass('is-active')
# reset data item # reset data item
row.find('.js-timeConvertFrom').val('') row.find('.js-timeConvertFrom').val('')
row.find('.js-timeConvertTo').val('') row.find('.js-timeConvertTo').val('')
row.find('.js-updateTypeSelector').attr('checked', false)
row.find('.help-inline').empty() row.find('.help-inline').empty()
row.removeClass('has-error') row.removeClass('has-error')
) )
@ -48,16 +42,12 @@ class App.UiElement.sla_times
inText = element.val() inText = element.val()
row = element.closest('tr') row = element.closest('tr')
row.find('.js-activateRow').prop('checked', true)
row
.find('.js-activateRow')
.prop('checked', true)
.trigger('change')
row.addClass('is-active') row.addClass('is-active')
row element
.find("[name='#{element.data('name')}']") .closest('td')
.find('.js-timeConvertTo')
.val(@toMinutes(inText) || '') .val(@toMinutes(inText) || '')
) )
@ -66,19 +56,9 @@ class App.UiElement.sla_times
$(e.currentTarget).closest('tr').find('.checkbox-replacement').click() $(e.currentTarget).closest('tr').find('.checkbox-replacement').click()
) )
# toggle update type on clicking around the element
item.find('.js-forward-radio').bind('click', (e) ->
elem = $(e.currentTarget).closest('p').find('.js-updateTypeSelector')
elem.prop('checked', true)
elem.trigger('change')
)
# focus time input on clicking surrounding cell # focus time input on clicking surrounding cell
item.find('.js-focus-input').bind('click', (e) -> item.find('.js-focus-input').bind('click', (e) ->
$(e.currentTarget) $(e.currentTarget).find('.form-control').focus()
.find('.form-control:visible')
.focus()
) )
# show placeholder instead of 00:00 # show placeholder instead of 00:00
@ -87,36 +67,15 @@ class App.UiElement.sla_times
$(e.currentTarget).val('') $(e.currentTarget).val('')
) )
# switch update/response times when type is selected accordingly
item.find('.js-updateTypeSelector').bind('change', (e) ->
element = $(e.target)
row = element.closest('tr')
row.find('.js-activateRow').prop('checked', true)
row.addClass('is-active')
row
.find('.js-timeConvertFrom')
.addClass('hidden')
.val('')
row
.find('.js-timeConvertTo')
.val('')
row
.find("[data-name='#{element.val()}_time']")
.removeClass('hidden')
)
# set initial active/inactive rows # set initial active/inactive rows
item.find('.js-timeConvertFrom').each(-> item.find('.js-timeConvertFrom').each(->
row = $(@).closest('tr') row = $(@).closest('tr')
checkbox = row.find('.js-activateRow') checkbox = row.find('.js-activateRow')
if $(@).val()
return if !$(@).val() checkbox.prop('checked', true)
row.addClass('is-active')
checkbox.prop('checked', true) else
row.addClass('is-active') checkbox.prop('checked', false)
) )
item item

View file

@ -4,17 +4,16 @@ class App.UiElement.textarea
fileUploaderId = 'file-uploader-' + new Date().getTime() + '-' + Math.floor( Math.random() * 99999 ) fileUploaderId = 'file-uploader-' + new Date().getTime() + '-' + Math.floor( Math.random() * 99999 )
item = $( App.view('generic/textarea')( attribute: attribute ) + '<div class="file-uploader ' + attribute.class + '" id="' + fileUploaderId + '"></div>' ) item = $( App.view('generic/textarea')( attribute: attribute ) + '<div class="file-uploader ' + attribute.class + '" id="' + fileUploaderId + '"></div>' )
if attribute.expanding isnt false a = ->
a = -> visible = $( item[0] ).is(':visible')
if visible && !$( item[0] ).expanding('active')
$( item[0] ).expanding()
$( item[0] ).on('focus', ->
visible = $( item[0] ).is(':visible') visible = $( item[0] ).is(':visible')
if visible && !$( item[0] ).expanding('active') if visible && !$( item[0] ).expanding('active')
$( item[0] ).expanding() $( item[0] ).expanding().focus()
$( item[0] ).on('focus', -> )
visible = $( item[0] ).is(':visible') App.Delay.set(a, 80)
if visible && !$( item[0] ).expanding('active')
$( item[0] ).expanding().focus()
)
App.Delay.set(a, 80)
if attribute.upload if attribute.upload

View file

@ -48,15 +48,12 @@ class App.TicketCreate extends App.Controller
if @ticket_id && @article_id if @ticket_id && @article_id
@split = "/#{@ticket_id}/#{@article_id}" @split = "/#{@ticket_id}/#{@article_id}"
@ajax( load = (data) =>
type: 'GET' App.Collection.loadAssets(data.assets)
url: "#{@apiPath}/ticket_create" @formMeta = data.form_meta
processData: true @buildScreen(params)
success: (data, status, xhr) => @bindId = App.TicketCreateCollection.bind(load, false)
App.Collection.loadAssets(data.assets) App.TicketCreateCollection.fetch()
@formMeta = data.form_meta
@buildScreen(params)
)
# rerender view, e. g. on langauge change # rerender view, e. g. on langauge change
@controllerBind('ui:rerender', => @controllerBind('ui:rerender', =>
@ -72,6 +69,9 @@ class App.TicketCreate extends App.Controller
@sidebarWidget.render(@params()) @sidebarWidget.render(@params())
) )
release: =>
App.TicketCreateCollection.unbindById(@bindId)
currentChannel: => currentChannel: =>
if !type if !type
type = @$('.type-tabs .tab.active').data('type') type = @$('.type-tabs .tab.active').data('type')
@ -282,15 +282,8 @@ class App.TicketCreate extends App.Controller
return if !@formMeta return if !@formMeta
App.QueueManager.run(@queueKey) App.QueueManager.run(@queueKey)
updateTaskManagerAttachments: (attribute, attachments) =>
taskData = App.TaskManager.get(@taskKey)
return if _.isEmpty(taskData)
taskData.attachments = attachments
App.TaskManager.update(@taskKey, taskData)
render: (template = {}) -> render: (template = {}) ->
return if !@formMeta
# get params # get params
params = @prefilledParams || {} params = @prefilledParams || {}
if template && !_.isEmpty(template.options) if template && !_.isEmpty(template.options)
@ -332,16 +325,17 @@ class App.TicketCreate extends App.Controller
handlers = @Config.get('TicketCreateFormHandler') handlers = @Config.get('TicketCreateFormHandler')
@controllerFormCreateMiddle = new App.ControllerForm( @controllerFormCreateMiddle = new App.ControllerForm(
el: @$('.ticket-form-middle') el: @$('.ticket-form-middle')
form_id: @formId form_id: @formId
model: App.Ticket model: App.Ticket
screen: 'create_middle' screen: 'create_middle'
handlersConfig: handlers handlersConfig: handlers
formMeta: @formMeta filter: @formMeta.filter
params: params formMeta: @formMeta
noFieldset: true params: params
taskKey: @taskKey noFieldset: true
rejectNonExistentValues: true taskKey: @taskKey
rejectNonExistentValues: true
) )
# tunnel events to make sure core workflow does know # tunnel events to make sure core workflow does know
@ -365,6 +359,8 @@ class App.TicketCreate extends App.Controller
events: events:
'change [name=customer_id]': @localUserInfo 'change [name=customer_id]': @localUserInfo
handlersConfig: handlersTunnel handlersConfig: handlersTunnel
filter: @formMeta.filter
formMeta: @formMeta
autofocus: true autofocus: true
params: params params: params
taskKey: @taskKey taskKey: @taskKey
@ -380,8 +376,6 @@ class App.TicketCreate extends App.Controller
handlersConfig: handlersTunnel handlersConfig: handlersTunnel
params: params params: params
taskKey: @taskKey taskKey: @taskKey
richTextUploadRenderCallback: @updateTaskManagerAttachments
richTextUploadDeleteCallback: @updateTaskManagerAttachments
) )
@controllerFormCreateBottom = new App.ControllerForm( @controllerFormCreateBottom = new App.ControllerForm(
el: @$('.ticket-form-bottom') el: @$('.ticket-form-bottom')
@ -389,6 +383,8 @@ class App.TicketCreate extends App.Controller
model: App.Ticket model: App.Ticket
screen: 'create_bottom' screen: 'create_bottom'
handlersConfig: handlersTunnel handlersConfig: handlersTunnel
filter: @formMeta.filter
formMeta: @formMeta
params: params params: params
taskKey: @taskKey taskKey: @taskKey
) )

View file

@ -1,4 +1,4 @@
class TicketCreateFormHandlerSignature class TicketCreateFormHanderSignature
@run: (params, attribute, attributes, classname, form, ui) -> @run: (params, attribute, attributes, classname, form, ui) ->
return if !attribute return if !attribute
@ -19,7 +19,10 @@ class TicketCreateFormHandlerSignature
if App.Utils.signatureCheck(currentBody.html() || '', signatureFinished) if App.Utils.signatureCheck(currentBody.html() || '', signatureFinished)
# if signature has changed, in case remove old signature # if signature has changed, in case remove old signature
ui.el.closest('.content').find('[data-signature="true"]').remove() signature_id = ui.el.closest('.content').find('[data-signature=true]').data('signature-id')
if signature_id && signature_id.toString() isnt signature.id.toString()
ui.el.closest('.content').find('[data-signature="true"]').remove()
if !App.Utils.htmlLastLineEmpty(currentBody) if !App.Utils.htmlLastLineEmpty(currentBody)
currentBody.append('<br><br>') currentBody.append('<br><br>')
@ -32,4 +35,4 @@ class TicketCreateFormHandlerSignature
else else
ui.el.closest('.content').find('[data-name="body"]').find('[data-signature=true]').remove() ui.el.closest('.content').find('[data-name="body"]').find('[data-signature=true]').remove()
App.Config.set('200-ticketFormSignature', TicketCreateFormHandlerSignature, 'TicketCreateFormHandler') App.Config.set('200-ticketFormSignature', TicketCreateFormHanderSignature, 'TicketCreateFormHandler')

View file

@ -13,7 +13,13 @@ class CustomerTicketCreate extends App.ControllerAppContent
@form_id = App.ControllerForm.formId() @form_id = App.ControllerForm.formId()
@navupdate '#customer_ticket_new' @navupdate '#customer_ticket_new'
@render()
load = (data) =>
App.Collection.loadAssets(data.assets)
@formMeta = data.form_meta
@render()
@bindId = App.TicketCreateCollection.bind(load, false)
App.TicketCreateCollection.fetch()
render: (template = {}) -> render: (template = {}) ->
if !@Config.get('customer_ticket_create') if !@Config.get('customer_ticket_create')
@ -37,6 +43,8 @@ class CustomerTicketCreate extends App.ControllerAppContent
form_id: @form_id form_id: @form_id
model: App.Ticket model: App.Ticket
screen: 'create_middle' screen: 'create_middle'
filter: @formMeta.filter
formMeta: @formMeta
params: defaults params: defaults
noFieldset: true noFieldset: true
handlersConfig: handlers handlersConfig: handlers
@ -62,6 +70,8 @@ class CustomerTicketCreate extends App.ControllerAppContent
model: App.Ticket model: App.Ticket
screen: 'create_top' screen: 'create_top'
handlersConfig: handlersTunnel handlersConfig: handlersTunnel
filter: @formMeta.filter
formMeta: @formMeta
autofocus: true autofocus: true
params: defaults params: defaults
) )
@ -73,6 +83,8 @@ class CustomerTicketCreate extends App.ControllerAppContent
events: events:
'fileUploadStart .richtext': => @submitDisable() 'fileUploadStart .richtext': => @submitDisable()
'fileUploadStop .richtext': => @submitEnable() 'fileUploadStop .richtext': => @submitEnable()
filter: @formMeta.filter
formMeta: @formMeta
params: defaults params: defaults
handlersConfig: handlersTunnel handlersConfig: handlersTunnel
) )
@ -83,6 +95,8 @@ class CustomerTicketCreate extends App.ControllerAppContent
model: App.Ticket model: App.Ticket
screen: 'create_bottom' screen: 'create_bottom'
handlersConfig: handlersTunnel handlersConfig: handlersTunnel
filter: @formMeta.filter
formMeta: @formMeta
params: defaults params: defaults
) )

View file

@ -91,7 +91,20 @@ class GettingStartedChannelEmail extends App.ControllerWizardFullScreen
ui.hide('options::folder') ui.hide('options::folder')
ui.hide('options::keep_on_server') ui.hide('options::keep_on_server')
form = new App.ControllerForm( handlePort = (params, attribute, attributes, classname, form, ui) ->
return if !params
return if !params.options
currentPort = @$('.base-inbound-settings [name="options::port"]').val()
if params.options.ssl is true
if !currentPort
@$('.base-inbound-settings [name="options::port"]').val('993')
return
if params.options.ssl is false
if !currentPort || currentPort is '993'
@$('.base-inbound-settings [name="options::port"]').val('143')
return
new App.ControllerForm(
el: @$('.base-inbound-settings') el: @$('.base-inbound-settings')
model: model:
configure_attributes: configureAttributesInbound configure_attributes: configureAttributesInbound
@ -99,16 +112,10 @@ class GettingStartedChannelEmail extends App.ControllerWizardFullScreen
params: @account.inbound params: @account.inbound
handlers: [ handlers: [
showHideFolder, showHideFolder,
handlePort,
] ]
) )
form.el.find("select[name='options::ssl']").off('change').on('change', (e) ->
if $(e.target).val() is 'true'
form.el.find("[name='options::port']").val('993')
else
form.el.find("[name='options::port']").val('143')
)
toggleOutboundAdapter: => toggleOutboundAdapter: =>
# fill user / password based on intro info # fill user / password based on intro info

View file

@ -165,7 +165,7 @@ class ImportFreshdesk extends App.ControllerWizardFullScreen
@$('.js-error').addClass('hide') @$('.js-error').addClass('hide')
if !_.isEmpty(data.finished_at) && _.isEmpty(data.result['error']) if !_.isEmpty(data.finished_at) && _.isEmpty(data.result['error'])
@redirectToLogin() window.location.reload()
return return
if !_.isEmpty(data.result) if !_.isEmpty(data.result)

View file

@ -163,7 +163,7 @@ class ImportZendesk extends App.ControllerWizardFullScreen
@$('.js-error').addClass('hide') @$('.js-error').addClass('hide')
if !_.isEmpty(data.finished_at) && _.isEmpty(data.result['error']) if !_.isEmpty(data.finished_at) && _.isEmpty(data.result['error'])
@redirectToLogin() window.location.reload()
return return
if !_.isEmpty(data.result) if !_.isEmpty(data.result)

View file

@ -247,6 +247,8 @@ class Edit extends App.ControllerGenericEdit
#if attribute.name is 'data_type' #if attribute.name is 'data_type'
# attribute.disabled = true # attribute.disabled = true
console.log('configure_attributes', configure_attributes)
@controller = new App.ControllerForm( @controller = new App.ControllerForm(
model: model:
configure_attributes: configure_attributes configure_attributes: configure_attributes

View file

@ -153,7 +153,7 @@ class Object extends App.ControllerObserver
elLocal.find('.js-userList').html(members) elLocal.find('.js-userList').html(members)
) )
if @organization.member_ids.length <= @memberLimit if @organization.member_ids.length < @memberLimit
@el.find('.js-showMoreMembers').parent().addClass('hidden') @el.find('.js-showMoreMembers').parent().addClass('hidden')
else else
@el.find('.js-showMoreMembers').parent().removeClass('hidden') @el.find('.js-showMoreMembers').parent().removeClass('hidden')
@ -202,7 +202,7 @@ class Object extends App.ControllerObserver
value = $(e.target).html() value = $(e.target).html()
org = App.Organization.find(@object_id) org = App.Organization.find(@object_id)
if org[name] isnt value if org[name] isnt value
@lastAttributes[name] = value @lastAttributres[name] = value
data = {} data = {}
data[name] = value data[name] = value
org.updateAttributes(data) org.updateAttributes(data)

View file

@ -171,13 +171,6 @@ class Graph extends App.Controller
backends: @params.backendSelected backends: @params.backendSelected
) )
processData: true processData: true
error: (xhr) =>
return if !_.include([401, 403, 404, 422, 502], xhr.status)
@bodyModal = new App.ControllerTechnicalErrorModal(
head: 'Cannot generate report'
contentCode: xhr.responseJSON.error
)
success: (data) => success: (data) =>
@update(data) @update(data)
@delay(@render, interval, 'report-update', 'page') @delay(@render, interval, 'report-update', 'page')

View file

@ -56,9 +56,13 @@ class App.Search extends App.Controller
@navupdate(url: '#search', type: 'menu') @navupdate(url: '#search', type: 'menu')
return if _.isEmpty(params.query) return if _.isEmpty(params.query)
@$('.js-search').val(params.query).trigger('keyup') @$('.js-search').val(params.query).trigger('change')
return if @shown
@search(1000, true)
hide: -> hide: ->
@shown = false
if @table if @table
@table.hide() @table.hide()
@ -104,7 +108,6 @@ class App.Search extends App.Controller
return return
# on other keys, show result # on other keys, show result
@navigate "#search/#{encodeURIComponent(@searchInput.val())}"
@search(0) @search(0)
empty: => empty: =>

View file

@ -26,6 +26,12 @@ class Sla extends App.ControllerSubContent
sortBy: 'name' sortBy: 'name'
) )
for sla in slas for sla in slas
if sla.first_response_time
sla.first_response_time_in_text = @toText(sla.first_response_time)
if sla.update_time
sla.update_time_in_text = @toText(sla.update_time)
if sla.solution_time
sla.solution_time_in_text = @toText(sla.solution_time)
sla.rules = App.UiElement.ticket_selector.humanText(sla.condition) sla.rules = App.UiElement.ticket_selector.humanText(sla.condition)
sla.calendar = App.Calendar.find(sla.calendar_id) sla.calendar = App.Calendar.find(sla.calendar_id)
@ -89,8 +95,21 @@ class Sla extends App.ControllerSubContent
description: (e) => description: (e) =>
new App.ControllerGenericDescription( new App.ControllerGenericDescription(
description: App.Sla.description description: App.Calendar.description
container: @el.closest('.content') container: @el.closest('.content')
) )
toText: (m) ->
m = parseInt(m)
return if !m
minutes = m % 60
hours = Math.floor(m / 60)
if minutes < 10
minutes = "0#{minutes}"
if hours < 10
hours = "0#{hours}"
"#{hours}:#{minutes}"
App.Config.set('Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Sla, permission: ['admin.sla'] }, 'NavBarAdmin') App.Config.set('Sla', { prio: 2900, name: 'SLAs', parent: '#manage', target: '#manage/slas', controller: Sla, permission: ['admin.sla'] }, 'NavBarAdmin')

View file

@ -206,13 +206,22 @@ class App.TicketOverview extends App.Controller
article: article article: article
) )
ticket.article = article ticket.article = article
ticket.save( ticket.ajax().update(
ticket.attributes()
# this option will prevent callbacks and invalid data states in case of an error
failResponseNoTrigger: true
done: (r) => done: (r) =>
@batchCountIndex++ @batchCountIndex++
# refresh view after all tickets are proceeded # refresh view after all tickets are proceeded
if @batchCountIndex == @batchCount if @batchCountIndex == @batchCount
App.Event.trigger('overview:fetch') App.Event.trigger('overview:fetch')
fail: (record, settings, details) ->
console.log('record, settings, details', record, settings, details)
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('Bulk action stopped %s!', error)
})
) )
return return
@ -225,13 +234,21 @@ class App.TicketOverview extends App.Controller
ticket.owner_id = id ticket.owner_id = id
if !_.isEmpty(groupId) if !_.isEmpty(groupId)
ticket.group_id = groupId ticket.group_id = groupId
ticket.save( ticket.ajax().update(
ticket.attributes()
# this option will prevent callbacks and invalid data states in case of an error
failResponseNoTrigger: true
done: (r) => done: (r) =>
@batchCountIndex++ @batchCountIndex++
# refresh view after all tickets are proceeded # refresh view after all tickets are proceeded
if @batchCountIndex == @batchCount if @batchCountIndex == @batchCount
App.Event.trigger('overview:fetch') App.Event.trigger('overview:fetch')
fail: (record, settings, details) ->
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('Bulk action stopped %s!', settings.error)
})
) )
return return
@ -242,13 +259,21 @@ class App.TicketOverview extends App.Controller
#console.log "perform action #{action} with id #{id} on ", $(item).val() #console.log "perform action #{action} with id #{id} on ", $(item).val()
ticket = App.Ticket.find($(item).val()) ticket = App.Ticket.find($(item).val())
ticket.group_id = id ticket.group_id = id
ticket.save( ticket.ajax().update(
ticket.attributes()
# this option will prevent callbacks and invalid data states in case of an error
failResponseNoTrigger: true
done: (r) => done: (r) =>
@batchCountIndex++ @batchCountIndex++
# refresh view after all tickets are proceeded # refresh view after all tickets are proceeded
if @batchCountIndex == @batchCount if @batchCountIndex == @batchCount
App.Event.trigger('overview:fetch') App.Event.trigger('overview:fetch')
fail: (record, settings, details) ->
App.Event.trigger('notify', {
type: 'error'
msg: App.i18n.translateContent('Bulk action stopped %s!', error)
})
) )
return return

View file

@ -493,22 +493,16 @@ class App.TicketZoom extends App.Controller
@form_id = @taskGet('article').form_id || App.ControllerForm.formId() @form_id = @taskGet('article').form_id || App.ControllerForm.formId()
@articleNew = new App.TicketZoomArticleNew( @articleNew = new App.TicketZoomArticleNew(
ticket: @ticket ticket: @ticket
ticket_id: @ticket_id ticket_id: @ticket_id
el: elLocal.find('.article-new') el: elLocal.find('.article-new')
formMeta: @formMeta formMeta: @formMeta
form_id: @form_id form_id: @form_id
defaults: @taskGet('article') defaults: @taskGet('article')
taskKey: @taskKey taskKey: @taskKey
ui: @ ui: @
richTextUploadStartCallback: @submitDisable callbackFileUploadStart: @submitDisable
richTextUploadRenderCallback: (attachments) => callbackFileUploadStop: @submitEnable
@submitEnable()
@taskUpdateAttachments('article', attachments)
@delay(@markForm, 250, 'ticket-zoom-form-update')
richTextUploadDeleteCallback: (attachments) =>
@taskUpdateAttachments('article', attachments)
@delay(@markForm, 250, 'ticket-zoom-form-update')
) )
@highligher = new App.TicketZoomHighlighter( @highligher = new App.TicketZoomHighlighter(
@ -647,7 +641,6 @@ class App.TicketZoom extends App.Controller
# update changes in ui # update changes in ui
currentStore = @currentStore() currentStore = @currentStore()
modelDiff = @formDiff(currentParams, currentStore) modelDiff = @formDiff(currentParams, currentStore)
return if _.isEmpty(modelDiff)
# set followup state if needed # set followup state if needed
@setDefaultFollowUpState(modelDiff, currentStore) @setDefaultFollowUpState(modelDiff, currentStore)
@ -727,7 +720,7 @@ class App.TicketZoom extends App.Controller
# add attachments if exist # add attachments if exist
attachmentCount = @$('.article-add .textBubble .attachments .attachment').length attachmentCount = @$('.article-add .textBubble .attachments .attachment').length
if attachmentCount > 0 if attachmentCount > 0
currentParams.article.attachments = attachmentCount currentParams.article.attachments = true
else else
delete currentParams.article.attachments delete currentParams.article.attachments
@ -742,14 +735,6 @@ class App.TicketZoom extends App.Controller
# do not compare null or undefined value # do not compare null or undefined value
if currentStore.ticket if currentStore.ticket
# make sure that the compared state is same in local storage and
# rendered html. Else we could have race conditions of data
# which is not rendered yet
renderedUpdatedAt = @el.find('.edit').attr('data-ticket-updated-at')
return if !renderedUpdatedAt
return if currentStore.ticket.updated_at.toString() isnt renderedUpdatedAt
for key, value of currentStore.ticket for key, value of currentStore.ticket
if value is null || value is undefined if value is null || value is undefined
currentStore.ticket[key] = '' currentStore.ticket[key] = ''
@ -984,14 +969,15 @@ class App.TicketZoom extends App.Controller
processData: true processData: true
success: (data) => success: (data) =>
#App.SessionStorage.set(@key, data)
@load(data, true, true)
# reset article - should not be resubmitted on next ticket update # reset article - should not be resubmitted on next ticket update
ticket.article = undefined ticket.article = undefined
# reset form after save # reset form after save
@reset() @reset()
@load(data, false, true)
if @sidebarWidget if @sidebarWidget
@sidebarWidget.commit() @sidebarWidget.commit()
@ -1084,13 +1070,6 @@ class App.TicketZoom extends App.Controller
App.TaskManager.update(@taskKey, taskData) App.TaskManager.update(@taskKey, taskData)
taskUpdateAttachments: (area, attachments) =>
taskData = App.TaskManager.get(@taskKey)
return if !taskData
taskData.attachments = attachments
App.TaskManager.update(@taskKey, taskData)
taskUpdateAll: (data) => taskUpdateAll: (data) =>
@localTaskData = data @localTaskData = data
@localTaskData.article['form_id'] = @form_id @localTaskData.article['form_id'] = @form_id
@ -1113,7 +1092,7 @@ class App.TicketZoom extends App.Controller
@localTaskData = @localTaskData =
ticket: {} ticket: {}
article: {} article: {}
App.TaskManager.update(@taskKey, { 'state': @localTaskData, attachments: [] }) App.TaskManager.update(@taskKey, { 'state': @localTaskData })
renderOverviewNavigator: (parentEl) -> renderOverviewNavigator: (parentEl) ->
new App.TicketZoomOverviewNavigator( new App.TicketZoomOverviewNavigator(

View file

@ -257,7 +257,7 @@ class EmailReply extends App.Controller
quote_header = App.FullQuoteHeader.fullQuoteHeaderForward(article) quote_header = App.FullQuoteHeader.fullQuoteHeaderForward(article)
body = "<br/><div>---#{App.i18n.translateInline('Begin forwarded message')}:---<br/><br/></div><div><blockquote type=\"cite\">#{quote_header}#{body}</blockquote></div><div><br></div>" body = "<br/><div>---Begin forwarded message:---<br/><br/></div><div><blockquote type=\"cite\">#{quote_header}#{body}</blockquote></div><div><br></div>"
articleNew = {} articleNew = {}
articleNew.body = body articleNew.body = body

View file

@ -24,7 +24,7 @@ class Internal
internal = true internal = true
if article.internal == true if article.internal == true
internal = false internal = false
ui.lastAttributes.internal = internal ui.lastAttributres.internal = internal
article.updateAttributes(internal: internal) article.updateAttributes(internal: internal)
# runtime update # runtime update

View file

@ -198,17 +198,17 @@ class App.TicketZoomArticleNew extends App.Controller
inputField: @$('.article-attachment input') inputField: @$('.article-attachment input')
onFileStartCallback: => onFileStartCallback: =>
@richTextUploadStartCallback?() @callbackFileUploadStart?()
onFileCompletedCallback: (response) => onFileCompletedCallback: (response) =>
@attachments.push response.data @attachments.push response.data
@renderAttachment(response.data) @renderAttachment(response.data)
@$('.article-attachment input').val('') @$('.article-attachment input').val('')
@richTextUploadRenderCallback?(@attachments) @callbackFileUploadStop?()
onFileAbortedCallback: => onFileAbortedCallback: =>
@richTextUploadRenderCallback?(@attachments) @callbackFileUploadStop?()
attachmentPlaceholder: @attachmentPlaceholder attachmentPlaceholder: @attachmentPlaceholder
attachmentUpload: @attachmentUpload attachmentUpload: @attachmentUpload
@ -287,6 +287,7 @@ class App.TicketZoomArticleNew extends App.Controller
params.preferences ||= {} params.preferences ||= {}
params.preferences.security = @paramsSecurity() params.preferences.security = @paramsSecurity()
params.attachments = @attachments
params params
validate: => validate: =>
@ -623,8 +624,6 @@ class App.TicketZoomArticleNew extends App.Controller
$(e.currentTarget).closest('.attachment').remove() $(e.currentTarget).closest('.attachment').remove()
if element.find('.attachment').length == 0 if element.find('.attachment').length == 0
element.empty() element.empty()
@richTextUploadDeleteCallback?(@attachments)
) )
actions: -> actions: ->

View file

@ -218,11 +218,11 @@ class ArticleViewItem extends App.ControllerObserver
) )
@articleActions = new App.TicketZoomArticleActions( @articleActions = new App.TicketZoomArticleActions(
el: @$('.js-article-actions') el: @$('.js-article-actions')
ticket: @ticket ticket: @ticket
article: article article: article
lastAttributes: @lastAttributes lastAttributres: @lastAttributres
form_id: @form_id form_id: @form_id
) )
# set see more # set see more
@ -305,38 +305,34 @@ class ArticleViewItem extends App.ControllerObserver
e.stopPropagation() e.stopPropagation()
article_id = $(e.target).closest('.ticket-article-item').data('id') article_id = $(e.target).closest('.ticket-article-item').data('id')
article = App.TicketArticle.find(article_id)
@ajax( @ajax(
id: 'retrySecurityProcess' id: 'retrySecurityProcess'
type: 'POST' type: 'POST'
url: "#{@apiPath}/ticket_articles/#{article_id}/retry_security_process" url: "#{@apiPath}/ticket_articles/#{article_id}/retry_security_process"
processData: true processData: true
success: (encryption_data, status, xhr) => success: (data, status, xhr) =>
for data in encryption_data if data.sign.success
continue if article.preferences.security.type isnt data.type @notify
type: 'success'
msg: App.i18n.translateContent('Verify sign success!')
else if data.sign.comment
comment = App.i18n.translateContent('Verify sign failed!') + ' ' + App.i18n.translateContent(data.sign.comment || '')
@notify
type: 'error'
msg: comment
timeout: 2000
if data.sign.success if data.encryption.success
@notify @notify
type: 'success' type: 'success'
msg: App.i18n.translateContent('Verify sign success!') msg: App.i18n.translateContent('Decryption success!')
else if data.sign.comment else if data.encryption.comment
comment = App.i18n.translateContent('Verify sign failed!') + ' ' + App.i18n.translateContent(data.sign.comment || '') comment = App.i18n.translateContent('Decryption failed!') + ' ' + App.i18n.translateContent(data.encryption.comment || '')
@notify @notify
type: 'error' type: 'error'
msg: comment msg: comment
timeout: 2000 timeout: 2000
if data.encryption.success
@notify
type: 'success'
msg: App.i18n.translateContent('Decryption success!')
else if data.encryption.comment
comment = App.i18n.translateContent('Decryption failed!') + ' ' + App.i18n.translateContent(data.encryption.comment || '')
@notify
type: 'error'
msg: comment
timeout: 2000
error: (xhr) => error: (xhr) =>
@notify @notify

View file

@ -79,12 +79,6 @@ class App.FormHandlerCoreWorkflow
return if !App.WebSocket.channel() return if !App.WebSocket.channel()
return !App.Config.get('core_workflow_ajax_mode') return !App.Config.get('core_workflow_ajax_mode')
@restrictValuesAttributeCache: (attribute, values) ->
result = { values: values }
return result if !attribute.relation
result.lastUpdatedAt = App[attribute.relation].lastUpdatedAt()
return result
# restricts the dropdown and tree select values of a form # restricts the dropdown and tree select values of a form
@restrictValues: (classname, form, ui, attributes, params, data) -> @restrictValues: (classname, form, ui, attributes, params, data) ->
return if _.isEmpty(data.restrict_values) return if _.isEmpty(data.restrict_values)
@ -117,17 +111,17 @@ class App.FormHandlerCoreWorkflow
# cache state for performance and only run # cache state for performance and only run
# if values or param differ # if values or param differ
if coreWorkflowRestrictions?[classname]?[item.name] if coreWorkflowRestrictions?[classname]?[item.name]
compare = App.FormHandlerCoreWorkflow.restrictValuesAttributeCache(attribute, values) compare = values
continue if _.isEqual(coreWorkflowRestrictions[classname][item.name], compare) continue if _.isEqual(coreWorkflowRestrictions[classname][item.name], compare)
coreWorkflowRestrictions[classname] ||= {} coreWorkflowRestrictions[classname] ||= {}
coreWorkflowRestrictions[classname][item.name] = App.FormHandlerCoreWorkflow.restrictValuesAttributeCache(attribute, values) coreWorkflowRestrictions[classname][item.name] = values
valueFound = false valueFound = false
for value in values for value in values
# false values are valid values e.g. for boolean fields (be careful) # false values are valid values e.g. for boolean fields (be careful)
if value isnt undefined && paramValue isnt undefined && value isnt null && paramValue isnt null if value isnt undefined && paramValue isnt undefined
if value.toString() == paramValue.toString() if value.toString() == paramValue.toString()
valueFound = true valueFound = true
break break
@ -139,11 +133,6 @@ class App.FormHandlerCoreWorkflow
if valueFound if valueFound
item.default = paramValue item.default = paramValue
item.newValue = paramValue item.newValue = paramValue
else if params.id
obj = App[ui.model.className].find(params.id)
if obj && obj[item.name]
item.default = obj[item.name]
item.newValue = obj[item.name]
else else
item.default = '' item.default = ''
item.newValue = '' item.newValue = ''
@ -310,11 +299,6 @@ class App.FormHandlerCoreWorkflow
screen: ui.screen screen: ui.screen
} }
# send last changed attribute only once for has changed condition
if ui.lastChangedAttribute
requestData.last_changed_attribute = ui.lastChangedAttribute
ui.lastChangedAttribute = '-'
if App.FormHandlerCoreWorkflow.useWebSockets() if App.FormHandlerCoreWorkflow.useWebSockets()
App.WebSocket.send(requestData) App.WebSocket.send(requestData)
else else
@ -340,12 +324,8 @@ class App.FormHandlerCoreWorkflow
# get params and add id from ui if needed # get params and add id from ui if needed
params = App.FormHandlerCoreWorkflow.cleanParams(params_ref) params = App.FormHandlerCoreWorkflow.cleanParams(params_ref)
if ui?.params?.id
# add object id for edit screens
if ui?.params?.id && ui.screen.match(/edit/)
params.id = ui.params.id params.id = ui.params.id
else
delete params.id
# skip double checks # skip double checks
return if _.isEqual(coreWorkflowParams[classname], params) return if _.isEqual(coreWorkflowParams[classname], params)

View file

@ -29,33 +29,41 @@ class Edit extends App.Controller
# for the new ticket + eventually changed task state # for the new ticket + eventually changed task state
@formMeta.core_workflow = undefined @formMeta.core_workflow = undefined
editable = @ticket.editable() if followUpPossible == 'new_ticket' && ticketState != 'closed' ||
if followUpPossible == 'new_ticket' && ticketState != 'closed' || followUpPossible != 'new_ticket' || @permissionCheck('admin') || @ticket.currentView() is 'agent' followUpPossible != 'new_ticket' ||
editable = !editable @permissionCheck('admin') || @ticket.currentView() is 'agent'
@controllerFormSidebarTicket = new App.ControllerForm(
elReplace: @el
model: { className: 'Ticket', configure_attributes: @formMeta.configure_attributes || App.Ticket.configure_attributes }
screen: 'edit'
handlersConfig: handlers
filter: @formMeta.filter
formMeta: @formMeta
params: defaults
isDisabled: !@ticket.editable()
taskKey: @taskKey
core_workflow: {
callbacks: [@markForm]
}
#bookmarkable: true
)
else
@controllerFormSidebarTicket = new App.ControllerForm(
elReplace: @el
model: { className: 'Ticket', configure_attributes: @formMeta.configure_attributes || App.Ticket.configure_attributes }
screen: 'edit'
handlersConfig: handlers
filter: @formMeta.filter
formMeta: @formMeta
params: defaults
isDisabled: @ticket.editable()
taskKey: @taskKey
core_workflow: {
callbacks: [@markForm]
}
#bookmarkable: true
)
# reset updated_at for the sidbar because we render a new state
# it is used to compare the ticket with the rendered data later
# and needed to prevent race conditions
@el.removeAttr('data-ticket-updated-at')
@controllerFormSidebarTicket = new App.ControllerForm(
elReplace: @el
model: { className: 'Ticket', configure_attributes: @formMeta.configure_attributes || App.Ticket.configure_attributes }
screen: 'edit'
handlersConfig: handlers
filter: @formMeta.filter
formMeta: @formMeta
params: defaults
isDisabled: editable
taskKey: @taskKey
core_workflow: {
callbacks: [@markForm]
}
#bookmarkable: true
)
# set updated_at for the sidbar because we render a new state
@el.attr('data-ticket-updated-at', defaults.updated_at)
@markForm(true) @markForm(true)
return if @resetBind return if @resetBind

View file

@ -19,7 +19,7 @@ class App.TicketZoomTitle extends App.ControllerObserver
title = $(e.target).ceg() || '' title = $(e.target).ceg() || ''
# update title # update title
return if title is @lastAttributes.title return if title is @lastAttributres.title
ticket = App.Ticket.find(@object_id) ticket = App.Ticket.find(@object_id)
ticket.title = title ticket.title = title

View file

@ -220,7 +220,7 @@ class Object extends App.ControllerObserver
value = $(e.target).html() value = $(e.target).html()
user = App.User.find(@object_id) user = App.User.find(@object_id)
if user[name] isnt value if user[name] isnt value
@lastAttributes[name] = value @lastAttributres[name] = value
data = {} data = {}
data[name] = value data[name] = value
user.updateAttributes(data) user.updateAttributes(data)

View file

@ -33,7 +33,7 @@ class App.WidgetOrganization extends App.Controller
elLocal.find('.js-userList').html(members) elLocal.find('.js-userList').html(members)
) )
if @organization.member_ids.length <= @memberLimit if @organization.member_ids.length < @memberLimit
@el.find('.js-showMoreMembers').parent().addClass('hidden') @el.find('.js-showMoreMembers').parent().addClass('hidden')
else else
@el.find('.js-showMoreMembers').parent().removeClass('hidden') @el.find('.js-showMoreMembers').parent().removeClass('hidden')

View file

@ -14,7 +14,6 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
'click': 'stopPropagation' 'click': 'stopPropagation'
'change .js-objectId': 'executeCallback' 'change .js-objectId': 'executeCallback'
'click .js-remove': 'removeThisToken' 'click .js-remove': 'removeThisToken'
'click .js-showMoreMembers': 'showMoreMembers'
elements: elements:
'.recipientList': 'recipientList' '.recipientList': 'recipientList'
@ -252,42 +251,14 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
objectCount: objectCount objectCount: objectCount
) )
showMoreMembers: (e) ->
@preventDefaultAndStopPropagation(e)
memberElement = $(e.target).closest('.js-showMoreMembers')
oldMemberLimit = memberElement.attr('organization-member-limit')
newMemberLimit = (parseInt(oldMemberLimit / 25) + 1) * 25
memberElement.attr('organization-member-limit', newMemberLimit)
@renderMembers(memberElement, oldMemberLimit, newMemberLimit)
renderMembers: (element, fromMemberLimit, toMemberLimit) ->
id = element.closest('.recipientList-organizationMembers').attr('organization-id')
organization = App.Organization.find(id)
# only first 10 members else we would need more ajax requests
organization.members(fromMemberLimit, toMemberLimit, (users) =>
for user in users
element.before(@buildObjectItem(user))
if element.closest('ul').hasClass('is-shown')
@showOrganizationMembers(undefined, element.closest('ul'))
)
if organization.member_ids.length <= toMemberLimit
element.addClass('hidden')
else
element.removeClass('hidden')
buildOrganizationMembers: (organization) => buildOrganizationMembers: (organization) =>
organizationMembers = $( App.view(@templateOrganizationItemMembers)( organizationMemebers = $( App.view(@templateOrganizationItemMembers)(
organization: organization organization: organization
) ) ) )
if organization[@referenceAttribute]
@renderMembers(organizationMembers.find('.js-showMoreMembers'), 0, 10) for objectId in organization[@referenceAttribute]
object = App[@objectSingle].fullLocal(objectId)
organizationMembers organizationMemebers.append(@buildObjectItem(object))
buildObjectItem: (object) => buildObjectItem: (object) =>
icon = @objectIcon icon = @objectIcon
@ -433,7 +404,8 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
e.stopPropagation() e.stopPropagation()
listEntry = $(e.currentTarget) listEntry = $(e.currentTarget)
organizationId = listEntry.data('organization-id') || listEntry.attr('organization-id') organizationId = listEntry.data('organization-id')
@organizationList = @$("[organization-id=#{ organizationId }]") @organizationList = @$("[organization-id=#{ organizationId }]")
return if !@organizationList.get(0) return if !@organizationList.get(0)

View file

@ -102,18 +102,12 @@ class _ajaxSingleton
# do not show any error message with code 502 # do not show any error message with code 502
return if status is 502 return if status is 502
try
json = JSON.parse(detail)
text = json.error_human || json.error
text = detail if !text
escaped = App.Utils.htmlEscape(text)
# show error message # show error message
new App.ControllerTechnicalErrorModal( new App.ControllerModal(
contentCode: escaped head: "StatusCode: #{status}"
head: "StatusCode: #{status}" contentInline: "<pre>#{App.Utils.htmlEscape(detail)}</pre>"
buttonClose: true
buttonSubmit: false
) )
) )

View file

@ -37,11 +37,11 @@ class App.Browser
# define min. required browser version # define min. required browser version
map = map =
Chrome: 37 Firefox: 78 # ESR
Firefox: 36 Chrome: 83 # parallel to FF ESR - Edge is also detected as Chrome
Explorer: 10 Opera: 69 # based on Chrome 83
Safari: 6 Explorer: 11 # 10 is EOL
Opera: 22 Safari: 11 # released 2018
# disable id older # disable id older
if data.browser if data.browser

View file

@ -28,7 +28,7 @@ class App.FullQuoteHeader
@fullQuoteHeaderForwardTo: (article) -> @fullQuoteHeaderForwardTo: (article) ->
if article.type.name is 'email' || article.type.name is 'web' if article.type.name is 'email' || article.type.name is 'web'
@fullQuoteHeaderEnsureMultiPrivacy(article.to) @fullQuoteHeaderEnsurePrivacy(article.to) || article.to
else if article.sender.name is 'Customer' && article.type.name is 'phone' else if article.sender.name is 'Customer' && article.type.name is 'phone'
if email_address_id = App.Group.findByAttribute('name', article.to)?.email_address_id if email_address_id = App.Group.findByAttribute('name', article.to)?.email_address_id
App.EmailAddress.find(email_address_id).displayName() App.EmailAddress.find(email_address_id).displayName()
@ -36,17 +36,15 @@ class App.FullQuoteHeader
article.to article.to
else if article.sender.name is 'Agent' && article.type.name is 'phone' else if article.sender.name is 'Agent' && article.type.name is 'phone'
ticket = App.Ticket.find article.ticket_id ticket = App.Ticket.find article.ticket_id
@fullQuoteHeaderEnsurePrivacy(ticket.customer_id) || @fullQuoteHeaderEnsureMultiPrivacy(article.to) @fullQuoteHeaderEnsurePrivacy(ticket.customer_id) || @fullQuoteHeaderEnsurePrivacy(article.to) || article.to
else else
article.to article.to
@fullQuoteHeaderForwardCC: (article) -> @fullQuoteHeaderForwardCC: (article) ->
@fullQuoteHeaderEnsureMultiPrivacy(article.cc) return if !article.cc
@fullQuoteHeaderEnsureMultiPrivacy: (input) -> article
return if !input .cc
input
.split(',') .split(',')
.map (elem) -> .map (elem) ->
elem.trim() elem.trim()

View file

@ -8,12 +8,7 @@ class App.i18n
@translateDeep: (input, args...) -> @translateDeep: (input, args...) ->
if _instance == undefined if _instance == undefined
_instance ?= new _i18nSingleton() _instance ?= new _i18nSingleton()
_instance.translateDeep(input, args, false) _instance.translateDeep(input, args)
@translateDeepPlain: (input, args...) ->
if _instance == undefined
_instance ?= new _i18nSingleton()
_instance.translateDeep(input, args, true)
@translateContent: (string, args...) -> @translateContent: (string, args...) ->
if _instance == undefined if _instance == undefined
@ -235,20 +230,17 @@ class _i18nSingleton extends Spine.Module
return string if !string return string if !string
@translate(string, args, true) @translate(string, args, true)
translateDeep: (input, args, plain) => translateDeep: (input, args) =>
if _.isArray(input) if _.isArray(input)
_.map input, (item) => _.map input, (item) =>
@translateDeep(item, args, plain) @translateDeep(item, args)
else if _.isObject(input) else if _.isObject(input)
_.reduce _.keys(input), (memo, item) => _.reduce _.keys(input), (memo, item) =>
memo[item] = @translateDeep(input[item], args, plain) memo[item] = @translateDeep(input[item])
memo memo
, {} , {}
else else
if plain @translateInline(input, args)
@translatePlain(input, args)
else
@translateInline(input, args)
translateContent: (string, args) => translateContent: (string, args) =>

View file

@ -0,0 +1,27 @@
class _Singleton extends App._CollectionSingletonBase
event: 'ticket_create_attributes'
restEndpoint: '/ticket_create'
class App.TicketCreateCollection
_instance = new _Singleton
@get: ->
_instance.get()
@one: (callback, init = true) ->
_instance.bind(callback, init, true)
@bind: (callback, init = true) ->
_instance.bind(callback, init, false)
@unbind: (callback) ->
_instance.unbind(callback)
@unbindById: (id) ->
_instance.unbindById(id)
@trigger: ->
_instance.trigger()
@fetch: ->
_instance.fetch()

View file

@ -1327,7 +1327,7 @@ class App.Utils
if type is 'email' && !e.attrs.value.match(/@/) || e.attrs.value.match(/\s/) if type is 'email' && !e.attrs.value.match(/@/) || e.attrs.value.match(/\s/)
e.preventDefault() e.preventDefault()
return false return false
e.attrs.label ||= e.attrs.value e.attrs.label = e.attrs.value
true true
) )
App.Delay.set(a, 500, undefined, 'tags') App.Delay.set(a, 500, undefined, 'tags')

View file

@ -654,11 +654,6 @@
var tokensBefore = this.getTokensList() var tokensBefore = this.getTokensList()
this.setTokens( this.$input.val(), true ) this.setTokens( this.$input.val(), true )
// remove token text was cleared while editing
if (this.$input.data( 'edit' ) && !this.$input.val()) {
this.$element.val( this.getTokensList() )
}
if (tokensBefore == this.getTokensList() && this.$input.val().length) if (tokensBefore == this.getTokensList() && this.$input.val().length)
return false // No tokens were added, do nothing (prevent form submit) return false // No tokens were added, do nothing (prevent form submit)

View file

@ -114,22 +114,11 @@
sel = window.getSelection() sel = window.getSelection()
if (sel) { if (sel) {
node = $(sel.anchorNode) node = $(sel.anchorNode)
if (node && node.parent() && node.parent().is('blockquote')) {
if (node.closest('blockquote').length > 0) { e.preventDefault()
document.execCommand('Insertparagraph')
// Special handling when the line is not wrapped inside of a html element. document.execCommand('Outdent')
if (!node.is('div') && node.parent().is('blockquote') && node.text()) { return
e.preventDefault()
document.execCommand('formatBlock', false, 'div')
document.execCommand('insertParagraph')
return
}
if (!e.shiftKey && node && (node.is('blockquote') || (node.parent() && node.parent().is('blockquote')) || !node.text())) {
e.preventDefault()
document.execCommand('insertParagraph')
document.execCommand('outdent')
return
}
} }
} }

View file

@ -41,33 +41,17 @@ App.ViewHelpers =
return '' if isNaN(parseInt(time)) return '' if isNaN(parseInt(time))
# Hours, minutes and seconds # Hours, minutes and seconds
hrs = ~~parseInt((time / 3600)) hrs = ~~parseInt((time / 3600))
mins = ~~parseInt(((time % 3600) / 60)) mins = ~~parseInt(((time % 3600) / 60))
secs = parseInt(time % 60) secs = parseInt(time % 60)
# Output like "1:01" or "4:03:59" or "123:03:59" # Output like "1:01" or "4:03:59" or "123:03:59"
mins = "0#{mins}" if mins < 10 mins = "0#{mins}" if mins < 10
secs = "0#{secs}" if secs < 10 secs = "0#{secs}" if secs < 10
if hrs > 0 if hrs > 0
return "#{hrs}:#{mins}:#{secs}" return "#{hrs}:#{mins}:#{secs}"
"#{mins}:#{secs}" "#{mins}:#{secs}"
# define time_duration / hh:mm
time_duration_hh_mm: (time_in_minutes) ->
return '' if !time_in_minutes
return '' if isNaN(parseInt(time_in_minutes))
# Hours, minutes and seconds
hrs = ~~parseInt((time_in_minutes / 60))
mins = ~~parseInt((time_in_minutes % 60))
hrs = "0#{hrs}" if hrs < 10
mins = "0#{mins}" if mins < 10
"#{hrs}:#{mins}"
# define mask helper # define mask helper
# mask an value like 'a***********yz' # mask an value like 'a***********yz'
M: (item, start = 1, end = 2) -> M: (item, start = 1, end = 2) ->

View file

@ -234,11 +234,12 @@ class Singleton extends Base
failResponse: (options) => failResponse: (options) =>
(xhr, statusText, error, settings) => (xhr, statusText, error, settings) =>
switch settings.type if options.failResponseNoTrigger isnt true
when 'POST' then @createFailed() switch settings.type
when 'DELETE' then @destroyFailed() when 'POST' then @createFailed()
# add errors to calllback when 'DELETE' then @destroyFailed()
@record.trigger('ajaxError', @record, xhr, statusText, error, settings) # add errors to calllback
@record.trigger('ajaxError', @record, xhr, statusText, error, settings)
#options.fail?.call(@record, settings) #options.fail?.call(@record, settings)
detailsRaw = xhr.responseText detailsRaw = xhr.responseText
@ -246,7 +247,8 @@ class Singleton extends Base
details = JSON.parse(detailsRaw) details = JSON.parse(detailsRaw)
options.fail?.call(@record, settings, details) options.fail?.call(@record, settings, details)
@record.trigger('destroy', @record) if options.failResponseNoTrigger isnt true
@record.trigger('destroy', @record)
# /add errors to calllback # /add errors to calllback
createFailed: -> createFailed: ->

View file

@ -916,25 +916,20 @@ set new attributes of model (remove already available attributes)
# use jquery instead of ._clone() because we need a deep copy of the obj # use jquery instead of ._clone() because we need a deep copy of the obj
@org_configure_attributes = $.extend(true, [], @configure_attributes) @org_configure_attributes = $.extend(true, [], @configure_attributes)
configure_attributes = $.extend(true, [], @configure_attributes)
allAttributes = []
for attribute in attributes for attribute in attributes
@attributes.push attribute.name @attributes.push attribute.name
found = false found = false
for attribute_model, index in configure_attributes for attribute_model, index in @configure_attributes
continue if attribute_model.name != attribute.name continue if attribute_model.name != attribute.name
allAttributes.push $.extend(true, attribute_model, attribute) @configure_attributes[index] = _.extend(attribute_model, attribute)
configure_attributes.splice(index, 1) # remove found attribute
found = true found = true
break break
if !found if !found
allAttributes.push $.extend(true, {}, attribute) @configure_attributes.push attribute
@configure_attributes = $.extend(true, [], allAttributes.concat(configure_attributes))
@resetAttributes: -> @resetAttributes: ->
return if _.isEmpty(@org_configure_attributes) return if _.isEmpty(@org_configure_attributes)

View file

@ -6,8 +6,8 @@ class App.ObjectManagerAttribute extends App.Model
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false }, { name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
{ name: 'display', display: 'Display', tag: 'input', type: 'text', limit: 100, null: false }, { name: 'display', display: 'Display', tag: 'input', type: 'text', limit: 100, null: false },
{ name: 'object', display: 'Object', tag: 'input', readonly: 1 }, { name: 'object', display: 'Object', tag: 'input', readonly: 1 },
{ name: 'position', display: 'Position', tag: 'input', readonly: 1 },
{ name: 'active', display: 'Active', tag: 'active', default: true }, { name: 'active', display: 'Active', tag: 'active', default: true },
{ name: 'data_type', display: 'Format', tag: 'object_manager_attribute', null: false }, { name: 'data_type', display: 'Format', tag: 'object_manager_attribute', null: false },
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }, { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
{ name: 'position', display: 'Position', tag: 'integer', type: 'number', limit: 100, null: true },
] ]

View file

@ -36,7 +36,7 @@ Using **Organisations** you can **group** customers. This has among others two i
userResult = -> userResult = ->
users = [] users = []
for user_id in member_ids for user_id in member_ids
user = App.User.fullLocal(user_id) user = App.User.find(user_id)
continue if !user continue if !user
users.push(user) users.push(user)
return users return users

View file

@ -1,5 +1,5 @@
class App.Sla extends App.Model class App.Sla extends App.Model
@configure 'Sla', 'name', 'first_response_time', 'response_time', 'update_time', 'solution_time', 'condition', 'calendar_id' @configure 'Sla', 'name', 'first_response_time', 'update_time', 'solution_time', 'condition', 'calendar_id'
@extend Spine.Model.Ajax @extend Spine.Model.Ajax
@url: @apiPath + '/slas' @url: @apiPath + '/slas'
@configure_attributes = [ @configure_attributes = [
@ -12,7 +12,6 @@ class App.Sla extends App.Model
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 }, { name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }, { name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
{ name: 'first_response_time',skipRendering: true }, { name: 'first_response_time',skipRendering: true },
{ name: 'response_time', skipRendering: true },
{ name: 'update_time', skipRendering: true }, { name: 'update_time', skipRendering: true },
{ name: 'solution_time', skipRendering: true }, { name: 'solution_time', skipRendering: true },
] ]

View file

@ -1 +0,0 @@
<input type="text" disabled="disabled" readonly="readonly" value="<%= @attribute.value %>" class="form-control" />

View file

@ -20,8 +20,8 @@
<td data-day="<%- id %>" data-slot="<%- slot %>" class="form-group day-time<%- ' is-active' if @hours[id].active %>"> <td data-day="<%- id %>" data-slot="<%- slot %>" class="form-group day-time<%- ' is-active' if @hours[id].active %>">
<label for="<%- id %>_start_time">from</label> <label for="<%- id %>_start_time">from</label>
<input type="text" id="<%- id %>_start_time" name="<%= @attribute.name %>::<%- id %>::start" value="<%- @hours[id].timeframes[slot][0] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="0" class="form-control form-control--small time js-time"> <input type="text" id="<%- id %>_start_time" name="<%= @attribute.name %>::<%- id %>::start" value="<%- @hours[id].timeframes[slot][0] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="0" class="form-control form-control--small time js-time">
<label for="<%- id %>_end_time">till</label> <label for="monday_end_time">till</label>
<input type="text" id="<%- id %>_end_time" name="<%= @attribute.name %>::<%- id %>::end" value="<%- @hours[id].timeframes[slot][1] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="1" class="form-control form-control--small time js-time"> <input type="text" id="monday_end_time" name="<%= @attribute.name %>::<%- id %>::end" value="<%- @hours[id].timeframes[slot][1] %>" data-day="<%- id %>" data-slot="<%- slot %>" data-i="1" class="form-control form-control--small time js-time">
<% else: %> <% else: %>
<td class="empty-cell"> <td class="empty-cell">
<% end %> <% end %>

View file

@ -3,7 +3,7 @@
<% if @attribute.multiple: %> <% if @attribute.multiple: %>
<%- @tokens %> <%- @tokens %>
<% end %> <% end %>
<input name="<%= @attribute.name %>_completion" class="user-select token-input js-objectSelect form-control" autocapitalize="off" placeholder="<%- @Ti(@attribute.placeholder) %>" autocomplete="off" <%= @attribute.autofocus %> role="textbox" aria-autocomplete="list" value="<%= @name %>" aria-haspopup="true"> <input name="<%- @attribute.name %>_completion" class="user-select token-input js-objectSelect" autocapitalize="off" placeholder="<%- @Ti(@attribute.placeholder) %>" autocomplete="off" <%= @attribute.autofocus %> role="textbox" aria-autocomplete="list" value="<%= @name %>" aria-haspopup="true">
<% if @attribute.disableCreateObject isnt true: %><%- @Icon('arrow-down', 'dropdown-arrow') %><% end %> <% if @attribute.disableCreateObject isnt true: %><%- @Icon('arrow-down', 'dropdown-arrow') %><% end %>
</div> </div>

View file

@ -4,9 +4,4 @@
<%- @Icon('arrow-left') %> <%- @Icon('arrow-left') %>
<span class="btn-label"><%- @T('Back') %></span> <span class="btn-label"><%- @T('Back') %></span>
</div> </div>
<li class="recipientList-controls js-showMoreMembers" organization-member-limit="10">
<div class="btn btn--action btn--onDark">
<span class="btn-label"><%- @T('show more') %></span>
</div>
</ul> </ul>

View file

@ -6,7 +6,7 @@
<th><%- @T('Time') %> <span class="text-muted"><%- @T('in hours') %></span> <th><%- @T('Time') %> <span class="text-muted"><%- @T('in hours') %></span>
</thead> </thead>
<tbody> <tbody>
<tr> <tr class="form-group">
<td class="u-positionOrigin"> <td class="u-positionOrigin">
<label class="checkbox-replacement checkbox-replacement--fullscreen dont-grey-out"> <label class="checkbox-replacement checkbox-replacement--fullscreen dont-grey-out">
<input type="checkbox" class="js-activateRow" id="first_response_time" name="first_response_time_enabled"> <input type="checkbox" class="js-activateRow" id="first_response_time" name="first_response_time_enabled">
@ -16,51 +16,25 @@
<td class="u-clickable js-forward-click"> <td class="u-clickable js-forward-click">
<div><%- @T('First Response Time') %></div> <div><%- @T('First Response Time') %></div>
<p class="subtle"><%- @T('Timeframe for the first response.') %></p> <p class="subtle"><%- @T('Timeframe for the first response.') %></p>
<td class="u-clickable js-focus-input form-group"> <td class="u-clickable js-focus-input">
<input type="hidden" name="first_response_time" value="<%= @first_response_time %>" class="js-timeConvertTo"> <input type="hidden" name="first_response_time" value="<%= @first_response_time %>" class="js-timeConvertTo">
<input type="text" value="<%= @first_response_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom" placeholder="hh:mm" name="first_response_time_in_text" data-name="first_response_time"> <input type="text" value="<%= @first_response_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom" placeholder="hh:mm" name="first_response_time_in_text" data-name="first_response_time">
<tr> <tr class="form-group">
<td class="u-positionOrigin"> <td class="u-positionOrigin">
<label class="checkbox-replacement checkbox-replacement--fullscreen dont-grey-out"> <label class="checkbox-replacement checkbox-replacement--fullscreen dont-grey-out">
<input type="checkbox" class="js-activateRow" id="update_time" name="update_time_enabled"> <input type="checkbox" class="js-activateRow" id="update_time" name="update_time_enabled">
<%- @Icon('checkbox', 'icon-unchecked') %> <%- @Icon('checkbox', 'icon-unchecked') %>
<%- @Icon('checkbox-checked', 'icon-checked') %> <%- @Icon('checkbox-checked', 'icon-checked') %>
</label> </label>
<td class="u-clickable js-forward-click">
<div><%- @T('Update Time') %></div>
<p class="subtle"><%- @T('Timeframe for every following response.') %></p>
<td> <td>
<div class="u-clickable js-forward-click"> <input type="hidden" name="update_time" value="<%= @update_time %>" class="js-timeConvertTo">
<div><%- @T('Update Time') %></div> <input type="text" value="<%= @update_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom" placeholder="hh:mm" name="update_time_in_text" data-name="update_time">
<p class="subtle"><%- @T('Timeframe between agent updates or for an agent to respond.') %></p>
</div>
<p class="sla_radio_container js-forward-radio"> <tr class="form-group">
<label class="inline-label radio-replacement">
<input class="js-updateTypeSelector" type="radio" name="update_type" value="update" <% if @update_time: %>checked<% end %>>
<%- @Icon('radio', 'icon-unchecked') %>
<%- @Icon('radio-checked', 'icon-checked') %>
<span class="label-text"><%- @T('between agent updates') %></span>
</label>
</p>
<p class="sla_radio_container js-forward-radio u-clickable">
<label class="inline-label radio-replacement">
<input class="js-updateTypeSelector" type="radio" name="update_type" value="response" <% if @response_time: %>checked<% end %>>
<%- @Icon('radio', 'icon-unchecked') %>
<%- @Icon('radio-checked', 'icon-checked') %>
<span class="label-text"><%- @T('for an agent to respond') %></span>
</label>
</p>
<td class="form-group u-clickable js-focus-input u-clickable">
<span class="form-group">
<input type="hidden" name="update_time" value="<%= @update_time %>" class="js-timeConvertTo">
<input type="text" value="<%= @update_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom <% if @response_time: %>hidden<% end %>" placeholder="hh:mm" name="update_time_in_text" data-name="update_time">
</span>
<span class="form-group">
<input type="hidden" name="response_time" value="<%= @response_time %>" class="js-timeConvertTo">
<input type="text" value="<%= @response_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom <% if !@response_time: %>hidden<% end %>" placeholder="hh:mm" name="response_time_in_text" data-name="response_time">
</span>
<tr>
<td class="u-positionOrigin"> <td class="u-positionOrigin">
<label class="checkbox-replacement checkbox-replacement--fullscreen dont-grey-out"> <label class="checkbox-replacement checkbox-replacement--fullscreen dont-grey-out">
<input type="checkbox" id="solution_time" class="js-activateRow" name="solution_time_enabled"> <input type="checkbox" id="solution_time" class="js-activateRow" name="solution_time_enabled">
@ -70,7 +44,7 @@
<td class="u-clickable js-forward-click"> <td class="u-clickable js-forward-click">
<div><%- @T('Solution Time') %></div> <div><%- @T('Solution Time') %></div>
<p class="subtle"><%- @T('Timeframe for solving the problem.') %></p> <p class="subtle"><%- @T('Timeframe for solving the problem.') %></p>
<td class="form-group u-clickable js-focus-input"> <td>
<input type="hidden" name="solution_time" value="<%= @solution_time %>" class="js-timeConvertTo"> <input type="hidden" name="solution_time" value="<%= @solution_time %>" class="js-timeConvertTo">
<input type="text" value="<%= @solution_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom" placeholder="hh:mm" name="solution_time_in_text" data-name="solution_time"> <input type="text" value="<%= @solution_time_in_text %>" class="form-control form-control--small timeframe js-timeConvertFrom" placeholder="hh:mm" name="solution_time_in_text" data-name="solution_time">

View file

@ -82,7 +82,7 @@
<table class="settings-list" style="width: 100%;"> <table class="settings-list" style="width: 100%;">
<thead> <thead>
<tr> <tr>
<th width="50%"><%- @T('Value') %> <th width="50%"><%- @T('Name') %>
<th width="50%"><%- @T('Description') %> <th width="50%"><%- @T('Description') %>
</thead> </thead>
<tbody> <tbody>

View file

@ -91,30 +91,24 @@
</tbody> </tbody>
</table> </table>
</div> </div>
-->
<p><%- @T('Settings') %> <p><%- @T('Default caller id.') %>
<div class="settings-entry"> <div class="settings-entry">
<table class="settings-list" style="width: 100%;"> <table class="settings-list" style="width: 100%;">
<thead> <thead>
<tr> <tr>
<th width="50%"><%- @T('Value') %> <th width="50%"><%- @T('Default caller id') %>
<th width="50%"><%- @T('Description') %> <th width="50%"><%- @T('Note') %>
</thead> </thead>
<tbody> <tbody>
<!--
<tr> <tr>
<td class="settings-list-control-cell"><input name="default_caller_id" value="<%= @config.outbound.default_caller_id %>" placeholder="4930609854189" class="form-control form-control--small js-summary"> <td class="settings-list-control-cell"><input name="default_caller_id" value="<%= @config.outbound.default_caller_id %>" placeholder="4930609854189" class="form-control form-control--small js-summary">
<td class="settings-list-row-control"><%- @T('Default caller id for outbound calls.') %> <td class="settings-list-row-control"><%- @T('Default caller id for outbound calls.') %>
-->
<tr>
<td class="settings-list-control-cell js-viewLimit">
<td class="settings-list-row-control"><%- @T('Shown records in caller log.') %>
</tbody> </tbody>
</table> </table>
</div> </div>
-->
<h2><%- @T('User assignment to telephones') %></h2> <h2><%- @T('User assignment to telephones') %></h2>
<p><%- @T('User assignment to telephones to be able to offer extended like open new ticket screen on answering a call.') %> <p><%- @T('User assignment to telephones to be able to offer extended like open new ticket screen on answering a call.') %>

View file

@ -79,22 +79,38 @@
</table> </table>
</div> </div>
<p><%- @T('Settings') %> <p><%- @T('Default caller id.') %>
<div class="settings-entry"> <div class="settings-entry">
<table class="settings-list" style="width: 100%;"> <table class="settings-list" style="width: 100%;">
<thead> <thead>
<tr> <tr>
<th width="50%"><%- @T('Value') %> <th width="50%"><%- @T('Default caller id') %>
<th width="50%"><%- @T('Description') %> <th width="50%"><%- @T('Note') %>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td class="settings-list-control-cell"><input name="default_caller_id" value="<%= @config.outbound.default_caller_id %>" placeholder="4930609854189" class="form-control form-control--small js-summary"> <td class="settings-list-control-cell"><input name="default_caller_id" value="<%= @config.outbound.default_caller_id %>" placeholder="4930609854189" class="form-control form-control--small js-summary">
<td class="settings-list-row-control"><%- @T('Default caller id for outbound calls.') %> <td class="settings-list-row-control"><%- @T('Default caller id for outbound calls.') %>
</tbody>
</table>
</div>
<p><%- @T('In order for Zammad to access %s, a %s API user and password must be stored here', 'Sipgate', 'Sipgate') %>:<p>
<div class="settings-entry">
<table class="settings-list" style="width: 100%;">
<thead>
<tr> <tr>
<td class="settings-list-control-cell js-viewLimit"> <th width="20%"><%- @T('Type') %>
<td class="settings-list-row-control"><%- @T('Shown records in caller log.') %> <th width="80%"><%- @T('Content') %>
</thead>
<tbody>
<tr>
<td class="settings-list-row-control"><%- @T('API User') %>
<td class="settings-list-control-cell"><input type="input" class="form-control form-control--small js-select" value="<%= @config.api_user %>" name="api_user" placeholder="someuser@example.com">
<tr>
<td class="settings-list-row-control"><%- @T('API Password') %>
<td class="settings-list-control-cell"><input type="password" class="form-control form-control--small js-select" value="<%= @config.api_password %>" name="api_password" placeholder="">
</tbody> </tbody>
</table> </table>
</div> </div>

View file

@ -1,7 +1,7 @@
<div class="login fullscreen"> <div class="login fullscreen">
<div class="fullscreen-center"> <div class="fullscreen-center">
<div class="fullscreen-body"> <div class="fullscreen-body">
<p><%- @T('Login with %s', @C('fqdn')) %></p> <p><%- @T('Log in to %s', @C('fqdn')) %></p>
<% if @C('maintenance_mode'): %> <% if @C('maintenance_mode'): %>
<div class="hero-unit alert alert--danger js-maintenanceMode"><%- @T('Zammad is currently in maintenance mode. Only administrators can login. Please wait until the maintenance window is over.') %></div> <div class="hero-unit alert alert--danger js-maintenanceMode"><%- @T('Zammad is currently in maintenance mode. Only administrators can login. Please wait until the maintenance window is over.') %></div>

View file

@ -55,7 +55,6 @@
<th class=""><%- @T('Display') %></th> <th class=""><%- @T('Display') %></th>
<th class=""><%- @T('Name') %></th> <th class=""><%- @T('Name') %></th>
<th class="" style="width: 200px;"><%- @T('Type') %></th> <th class="" style="width: 200px;"><%- @T('Type') %></th>
<th><%- @T('Position') %></th>
<th class="" style="width: 140px;"><%- @T('Action') %></th> <th class="" style="width: 140px;"><%- @T('Action') %></th>
</tr> </tr>
</thead> </thead>
@ -65,7 +64,6 @@
<td><%= item.display %></td> <td><%= item.display %></td>
<td><%= item.name %></td> <td><%= item.name %></td>
<td><%= item.data_type %></td> <td><%= item.data_type %></td>
<td><%= item.position %></td>
<td> <td>
<% if item.to_create is true: %> <% if item.to_create is true: %>
<%- @T('will be created') %> <%- @T('will be created') %>

View file

@ -3,7 +3,7 @@
<% if @object.member_ids: %> <% if @object.member_ids: %>
<hr> <hr>
<div class="popover-block"> <div class="popover-block">
<label><%- @T('Members') %> (<%= @object.member_ids.length %>)</label> <label><%- @T('Members') %></label>
<div class="userList js-userList"></div> <div class="userList js-userList"></div>
</div> </div>
<% end %> <% end %>

View file

@ -34,19 +34,15 @@
<div class="action-block action-block--flex"> <div class="action-block action-block--flex">
<div class="label"><%- @T('Escalation Times') %></div> <div class="label"><%- @T('Escalation Times') %></div>
<% if sla.first_response_time: %> <% if sla.first_response_time: %>
<%- @time_duration_hh_mm(sla.first_response_time) %> <%- @T('hours') %> - <%- @T('First Response Time') %> <%- sla.first_response_time_in_text %> <%- @T('hours') %> - <%- @T('First Response Time') %>
<% end %>
<% if sla.response_time: %>
<br>
<%- @time_duration_hh_mm(sla.response_time) %> <%- @T('hours') %> - <%- @T('Response Time') %>
<% end %> <% end %>
<% if sla.update_time: %> <% if sla.update_time: %>
<br> <br>
<%- @time_duration_hh_mm(sla.update_time) %> <%- @T('hours') %> - <%- @T('Update Time') %> <%- sla.update_time_in_text %> <%- @T('hours') %> - <%- @T('Update Time') %>
<% end %> <% end %>
<% if sla.solution_time: %> <% if sla.solution_time: %>
<br> <br>
<%- @time_duration_hh_mm(sla.solution_time) %> <%- @T('hours') %> - <%- @T('Solution Time') %> <%- sla.solution_time_in_text %> <%- @T('hours') %> - <%- @T('Solution Time') %>
<% end %> <% end %>
<br> <br>
</div> </div>

View file

@ -65,9 +65,9 @@ Date.prototype.getWeek = function() {
function difference(object1, object2) { function difference(object1, object2) {
var changes = {}; var changes = {};
_.uniq(Object.keys(object1).concat(Object.keys(object2))).forEach(function(name) { for (var name in object1) {
if (name in object1 && name in object2) { if (name in object2) {
if (_.isObject(object1[name]) && !_.isArray(object1[name]) && _.isObject(object2[name]) && !_.isArray(object2[name])) { if (_.isObject(object2[name]) && !_.isArray(object2[name])) {
var diff = difference(object1[name], object2[name]); var diff = difference(object1[name], object2[name]);
if (!_.isEmpty(diff)) { if (!_.isEmpty(diff)) {
changes[name] = diff; changes[name] = diff;
@ -75,10 +75,8 @@ function difference(object1, object2) {
} else if (!_.isEqual(object1[name], object2[name])) { } else if (!_.isEqual(object1[name], object2[name])) {
changes[name] = object2[name]; changes[name] = object2[name];
} }
} else {
changes[name] = object2[name]
} }
}) }
return changes; return changes;
} }

View file

@ -1,39 +1,39 @@
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
src: url('assets/fonts/FiraSans-Bold.eot'); src: url('fonts/FiraSans-Bold.eot');
src: url('assets/fonts/FiraSans-Bold.woff2') format('woff2'), src: url('fonts/FiraSans-Bold.woff2') format('woff2'),
url('assets/fonts/FiraSans-Bold.woff') format('woff'), url('fonts/FiraSans-Bold.woff') format('woff'),
url('assets/fonts/FiraSans-Bold.ttf') format('truetype'); url('fonts/FiraSans-Bold.ttf') format('truetype');
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
src: url('assets/fonts/FiraSans-Regular.eot'); src: url('fonts/FiraSans-Regular.eot');
src: url('assets/fonts/FiraSans-Regular.woff2') format('woff2'), src: url('fonts/FiraSans-Regular.woff2') format('woff2'),
url('assets/fonts/FiraSans-Regular.woff') format('woff'), url('fonts/FiraSans-Regular.woff') format('woff'),
url('assets/fonts/FiraSans-Regular.ttf') format('truetype'); url('fonts/FiraSans-Regular.ttf') format('truetype');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
src: url('assets/fonts/FiraSans-Medium.eot'); src: url('fonts/FiraSans-Medium.eot');
src: url('assets/fonts/FiraSans-Medium.woff2') format('woff2'), src: url('fonts/FiraSans-Medium.woff2') format('woff2'),
url('assets/fonts/FiraSans-Medium.woff') format('woff'), url('fonts/FiraSans-Medium.woff') format('woff'),
url('assets/fonts/FiraSans-Medium.ttf') format('truetype'); url('fonts/FiraSans-Medium.ttf') format('truetype');
font-weight: 500; font-weight: 500;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
src: url('assets/fonts/FiraSans-Light.eot'); src: url('fonts/FiraSans-Light.eot');
src: url('assets/fonts/FiraSans-Light.woff2') format('woff2'), src: url('fonts/FiraSans-Light.woff2') format('woff2'),
url('assets/fonts/FiraSans-Light.woff') format('woff'), url('fonts/FiraSans-Light.woff') format('woff'),
url('assets/fonts/FiraSans-Light.ttf') format('truetype'); url('fonts/FiraSans-Light.ttf') format('truetype');
font-weight: 300; font-weight: 300;
font-style: normal; font-style: normal;
} }

View file

@ -358,26 +358,6 @@ ol, ul {
z-index: 1; z-index: 1;
} }
code {
background: hsla(0, 0%, 0%, 0.2);
border-radius: 3px;
box-decoration-break: clone;
}
code,
.hljs {
padding: 2px 4px;
font-size: 0.88em;
}
.hljs {
background: none;
}
pre code.hljs {
font-size: 1em;
}
pre { pre {
display: block; display: block;
padding: 9.5px; padding: 9.5px;
@ -391,26 +371,30 @@ pre {
border: 1px solid hsl(0,0%,90%); border: 1px solid hsl(0,0%,90%);
border-radius: 3px; border-radius: 3px;
} }
.modal-content pre {
background: hsl(0, 0%, 97%);
border: 1px solid hsl(0, 0%, 87%);
}
pre code { pre code {
padding: 0; padding: 0;
font-size: inherit; font-size: inherit;
color: inherit; color: inherit;
white-space: pre-wrap; white-space: pre-wrap;
background: none; background-color: transparent;
border-radius: 0; border-radius: 0;
border: none; }
overflow-x: auto;
&.hljs { .hljs,
padding: 0; code {
background: none; background: none;
} padding: 2px 4px;
font-size: 0.88em;
}
code:not(.hljs) {
border: 1px solid rgba(0,0,0,.2);
border-radius: 3px;
white-space: nowrap;
}
pre code.hljs {
font-size: 1em;
} }
.textarea::placeholder, .textarea::placeholder,
@ -13173,10 +13157,3 @@ span.is-disabled {
.text-modules-box { .text-modules-box {
max-height: 40vh; max-height: 40vh;
} }
.sla_times {
.sla_radio_container {
padding-top: 0.5em;
padding-left: 0.5em;
}
}

View file

@ -43,10 +43,6 @@ module ApplicationController::Authenticates
end end
def authentication_check_only(auth_param = {}) def authentication_check_only(auth_param = {})
if Rails.env.test? && ENV['FAKE_SELENIUM_LOGIN_USER_ID'].present? && session[:user_id].blank?
session[:user_id] = ENV['FAKE_SELENIUM_LOGIN_USER_ID'].to_i
end
# logger.debug 'authentication_check' # logger.debug 'authentication_check'
# logger.debug params.inspect # logger.debug params.inspect
# logger.debug session.inspect # logger.debug session.inspect

View file

@ -38,7 +38,6 @@ class CalendarsController < ApplicationController
end end
def destroy def destroy
model_references_check(Calendar, params)
model_destroy_render(Calendar, params) model_destroy_render(Calendar, params)
end end

View file

@ -149,7 +149,6 @@ curl http://localhost/api/v1/groups/{id} -v -u #{login}:#{password} -H "Content-
=end =end
def destroy def destroy
model_references_check(Group, params)
model_destroy_render(Group, params) model_destroy_render(Group, params)
end end
end end

View file

@ -50,9 +50,9 @@ class ImportFreshdeskController < ApplicationController
Setting.set('import_freshdesk_endpoint_key', params[:token]) Setting.set('import_freshdesk_endpoint_key', params[:token])
connection_result = Sequencer.process('Import::Freshdesk::ConnectionTest') result = Sequencer.process('Import::Freshdesk::ConnectionTest')
if !connection_result[:connected] if !result[:connected]
Setting.set('import_freshdesk_endpoint_key', nil) Setting.set('import_freshdesk_endpoint_key', nil)
@ -63,19 +63,6 @@ class ImportFreshdeskController < ApplicationController
return return
end end
permission_result = Sequencer.process('Import::Freshdesk::PermissionCheck')
if !permission_result[:permission_present]
Setting.set('import_freshdesk_endpoint_key', nil)
render json: {
result: 'invalid',
message_human: 'Missing administrator permission!',
}
return
end
render json: { render json: {
result: 'ok', result: 'ok',
} }

View file

@ -42,7 +42,9 @@ class Integration::SMIMEController < ApplicationController
string = params[:file].read.force_encoding('utf-8') string = params[:file].read.force_encoding('utf-8')
end end
items = SMIMECertificate.create_certificates(string) items = string.scan(%r{.+?-+END(?: TRUSTED)? CERTIFICATE-+}mi).each_with_object([]) do |cert, result|
result << SMIMECertificate.create!(public_key: cert)
end
render json: { render json: {
result: 'ok', result: 'ok',
@ -71,8 +73,14 @@ class Integration::SMIMEController < ApplicationController
raise "Parameter 'data' or 'file' required." if string.blank? raise "Parameter 'data' or 'file' required." if string.blank?
SMIMECertificate.create_certificates(string) private_key = OpenSSL::PKey.read(string, params[:secret])
SMIMECertificate.create_private_keys(string, params[:secret]) modulus = private_key.public_key.n.to_s(16)
certificate = SMIMECertificate.find_by(modulus: modulus)
raise Exceptions::UnprocessableEntity, 'Unable for find certificate for this private key.' if !certificate
certificate.update!(private_key: string, private_key_secret: params[:secret])
render json: { render json: {
result: 'ok', result: 'ok',

View file

@ -29,7 +29,7 @@ class ObjectManagerAttributesController < ApplicationController
) )
raise Exceptions::UnprocessableEntity, 'already exists' if exists raise Exceptions::UnprocessableEntity, 'already exists' if exists
add_attribute_using_params(permitted_params, status: :created) add_attribute_using_params(permitted_params.merge(position: 1550), status: :created)
end end
# PUT /object_manager_attributes/1 # PUT /object_manager_attributes/1

View file

@ -22,34 +22,26 @@ class ReportsController < ApplicationController
get_params = params_all get_params = params_all
return if !get_params return if !get_params
begin result = {}
result = {} get_params[:metric][:backend].each do |backend|
get_params[:metric][:backend].each do |backend| condition = get_params[:profile].condition
condition = get_params[:profile].condition if backend[:condition]
if backend[:condition] backend[:condition].merge(condition)
backend[:condition].merge(condition) else
else backend[:condition] = condition
backend[:condition] = condition
end
next if !backend[:adapter]
result[backend[:name]] = backend[:adapter].aggs(
range_start: get_params[:start],
range_end: get_params[:stop],
interval: get_params[:range],
selector: backend[:condition],
params: backend[:params],
timezone: get_params[:timezone],
timezone_offset: get_params[:timezone_offset],
current_user: current_user
)
end
rescue => e
if e.message.include? 'Conflicting date range'
raise Exceptions::UnprocessableEntity, 'Conflicting date ranges. Please check your selected report profile.'
end end
next if !backend[:adapter]
raise e result[backend[:name]] = backend[:adapter].aggs(
range_start: get_params[:start],
range_end: get_params[:stop],
interval: get_params[:range],
selector: backend[:condition],
params: backend[:params],
timezone: get_params[:timezone],
timezone_offset: get_params[:timezone_offset],
current_user: current_user
)
end end
render json: { render json: {

View file

@ -0,0 +1,31 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class TicketCreateScreenJob < ApplicationJob
include HasActiveJobLock
def perform
Sessions.list.each do |client_id, data|
next if client_id.blank?
user_id = data&.dig(:user, 'id')
next if user_id.blank?
user = User.lookup(id: user_id)
next if !user&.permissions?('ticket.agent')
# get attributes to update
ticket_create_attributes = Ticket::ScreenOptions.attributes_to_change(
current_user: user,
)
# no data exists
next if ticket_create_attributes.blank?
Rails.logger.debug { "push ticket_create for user #{user.id}" }
Sessions.send(client_id, {
event: 'ticket_create_attributes',
data: ticket_create_attributes,
})
end
end
end

View file

@ -373,14 +373,18 @@ returns
end end
# check if sla's are refer to an existing calendar # check if sla's are refer to an existing calendar
if destroyed? default_calendar = Calendar.find_by(default: true)
default_calendar = Calendar.find_by(default: true) Sla.find_each do |sla|
Sla.where(calendar_id: id).find_each do |sla| if !sla.calendar_id
sla.calendar_id = default_calendar.id
sla.save!
next
end
if !Calendar.exists?(id: sla.calendar_id)
sla.calendar_id = default_calendar.id sla.calendar_id = default_calendar.id
sla.save! sla.save!
end end
end end
true true
end end

View file

@ -7,6 +7,8 @@ class Channel::Driver::Imap < Channel::EmailParser
FETCH_METADATA_TIMEOUT = 2.minutes FETCH_METADATA_TIMEOUT = 2.minutes
FETCH_MSG_TIMEOUT = 4.minutes FETCH_MSG_TIMEOUT = 4.minutes
EXPUNGE_TIMEOUT = 16.minutes EXPUNGE_TIMEOUT = 16.minutes
DEFAULT_TIMEOUT = 45.seconds
CHECK_ONLY_TIMEOUT = 6.seconds
def fetchable?(_channel) def fetchable?(_channel)
true true
@ -110,10 +112,7 @@ example
Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl},starttls=#{starttls},folder=#{folder},keep_on_server=#{keep_on_server},auth_type=#{options.fetch(:auth_type, 'LOGIN')})" Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl},starttls=#{starttls},folder=#{folder},keep_on_server=#{keep_on_server},auth_type=#{options.fetch(:auth_type, 'LOGIN')})"
# on check, reduce open_timeout to have faster probing # on check, reduce open_timeout to have faster probing
check_type_timeout = 45 check_type_timeout = check_type == 'check' ? CHECK_ONLY_TIMEOUT : DEFAULT_TIMEOUT
if check_type == 'check'
check_type_timeout = 6
end
timeout(check_type_timeout) do timeout(check_type_timeout) do
@imap = ::Net::IMAP.new(options[:host], port, ssl, nil, false) @imap = ::Net::IMAP.new(options[:host], port, ssl, nil, false)

Some files were not shown because too many files have changed in this diff Show more