Compare commits

..

4 commits

Author SHA1 Message Date
f
af9baadea7 Merge branch 'develop' into antifascista 2021-10-14 10:40:22 -03:00
f
6c1a6b48a4 Merge branch 'develop' into antifascista 2021-10-13 12:39:26 -03:00
f
ea2cf81ab4 makefile 2021-10-05 20:21:45 -03:00
f
1bf468a262 Use gems compiled for Alpine Linux 2021-10-03 19:41:28 -03:00
3784 changed files with 110317 additions and 660206 deletions

View file

@ -1,91 +0,0 @@
module.exports = class DetectTranslatableString
# coffeelint: disable=detect_translatable_string
rule:
name: 'detect_translatable_string'
level: 'ignore'
message: 'The following string looks like it should be marked as translatable via __(...)'
description: '''
'''
constructor: ->
@callTokens = []
tokens: ['STRING', 'CALL_START', 'CALL_END']
lintToken: (token, tokenApi) ->
[type, tokenValue] = token
if type in ['CALL_START', 'CALL_END']
@trackCall token, tokenApi
return
return false if @isInIgnoredMethod()
return @lintString(token, tokenApi)
lintString: (token, tokenApi) ->
[type, tokenValue] = token
# Remove quotes.
string = tokenValue[1..-2]
# Ignore strings with less than two words.
return false if string.split(' ').length < 2
# Ignore strings that are being used as exception; unlike Ruby exceptions, these should not reach the user.
return false if tokenApi.peek(-3)[1] == 'throw'
return false if tokenApi.peek(-2)[1] == 'throw'
return false if tokenApi.peek(-1)[1] == 'throw'
# Ignore strings that are being used for comparison
return false if tokenApi.peek(-1)[1] == '=='
# String interpolation is handled via concatenation, ignore such strings.
return false if tokenApi.peek(1)[1] == '+'
return false if tokenApi.peek(2)[1] == '+'
BLOCKLIST = [
# Only look at strings starting with upper case letters
/^[^A-Z]/,
# # Ignore strings starting with three upper case letters like SELECT, POST etc.
# /^[A-Z]{3}/,
]
return false if BLOCKLIST.some (entry) ->
#console.log([string, entry, string.match(entry), token, tokenApi.peek(-1), tokenApi.peek(1)])
string.match(entry)
# console.log(tokenApi.peek(-3))
# console.log(tokenApi.peek(-2))
# console.log(tokenApi.peek(-1))
# console.log(token)
return { context: "Found: #{token[1]}" }
ignoredMethods: {
'__': true,
'log': true,
'T': true,
'controllerBind': true,
'error': true, # App.Log.error
'set': true, # App.Config.set
'translateInline': true,
'translateContent': true,
'translatePlain': true,
}
isInIgnoredMethod: ->
#console.log(@callTokens)
for t in @callTokens
return true if t.isIgnoredMethod
return false
trackCall: (token, tokenApi) ->
if token[0] is 'CALL_START'
p = tokenApi.peek(-1)
token.isIgnoredMethod = p and @ignoredMethods[p[1]]
@callTokens.push(token)
else
@callTokens.pop()
return null

2
.csslintrc Normal file
View file

@ -0,0 +1,2 @@
--exclude-exts=.min.css
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes

1
.gitattributes vendored
View file

@ -1 +0,0 @@
public/assets/** filter=lfs diff=lfs merge=lfs -text

View file

@ -0,0 +1,10 @@
user=zammad
project=zammad
output=CHANGELOG.md
since-tag=1.0.0
bug-labels=bug,minor bug,security
enhancement-labels=enhancement,feature,feature backlog
issues-wo-labels=false
include-labels=security,trigger,UX/UI,admin area,API,browser,bug,channel,chat,email filter,enhancement,feature,feature backlog,import,minor bug,notification,email filter,ticket templates,
issue-line-labels=enhancement,feature,feature backlog,bug,minor bug,notification,reporting,security,ticket templates,translation,trigger,UX/UI
exclude-tags=9.0.1,0.9.1,v0.1.8,v0.1.7,unittests_passed

27
.gitignore vendored
View file

@ -37,15 +37,20 @@
/db/*.sqlite3
/db/schema.rb
# legacy translation cache files
/config/locales-*.yml
# translation cache files
/config/locales*.yml
/config/translations/*.yml
# NPM / Yarn
/node_modules
/yarn.lock
# logfiles and tempfiles
/log
/public/assets/*.*
/public/assets/addons
/public/assets/app
/public/assets/custom
/public/assets/chat/node_modules
/tmp/*
!/tmp/pids
@ -53,9 +58,17 @@
!/tmp/pids/.keep
/storage/fs
# doorkeeper (OAuth 2)
/public/assets/doorkeeper
# images
/public/assets/images/yarn.lock
/public/assets/images/node_modules
/public/assets/images/*
!/public/assets/images/icons/
!/public/assets/images/avatar-bg.png
!/public/assets/images/chat-demo-avatar.png
!/public/assets/images/eyedropper.gif
!/public/assets/images/icons.svg
!/public/assets/images/logo.svg
# Third-Party ------------------------------------------------------------------
@ -71,12 +84,12 @@
# Eclipse
/.project
# VSCode
/.vscode
# Byebug
/.byebug_history
# SimpleCov
/coverage
# RDoc / YARD
/doc

View file

@ -1,5 +1,5 @@
default:
image: $CI_REGISTRY/docker/zammad-ci:2.7.4
image: registry.znuny.com/docker/zammad-ci:2.7.4
include:
- local: '/.gitlab/ci/base.yml'
@ -55,9 +55,7 @@ cache:
# Initialize application env
before_script:
- source /etc/profile.d/rvm.sh
- source /opt/rh/rh-nodejs*/enable
- echo -e "\\e[0Ksection_start:`date +%s`:bundle_install[collapsed=true]\\r\\e[0Kbundle install"
- source /opt/rh/rh-nodejs12/enable
- bundle install -j $(nproc) --path vendor
- echo -e "\\e[0Ksection_end:`date +%s`:bundle_install\\r\\e[0K"
- bundle exec ruby .gitlab/configure_environment.rb
- source .gitlab/environment.env

View file

@ -1,7 +1,7 @@
# Artifacts are stored for failed jobs
# Artifacts are stored for failed jobs for 2 days
.artifacts_error: &artifacts_error
artifacts:
expire_in: 1 week
expire_in: 2 days
when: on_failure
paths:
- tmp/screenshot*
@ -12,7 +12,6 @@
variables:
ES_INDEX_RAND: "true"
ES_URL: "http://elasticsearch:9200"
ELASTICSEARCH_TAG: '7.16'
.variables_redis_memcached: &variables_redis_memcached
variables:
@ -23,19 +22,17 @@
variables:
REMOTE_URL: "http://selenium-firefox:4444/wd/hub"
BROWSER: "firefox"
BROWSER_HEADLESS: "true"
START_XVFB: "false" # not needed for headless mode
SE_NODE_MAX_SESSIONS: "5"
SE_NODE_OVERRIDE_MAX_SESSIONS: "true"
# Settings for Selenium 3:
NODE_MAX_INSTANCES: "5"
NODE_MAX_SESSION: "5"
.variables_selenium_chrome: &variables_selenium_chrome
variables:
REMOTE_URL: "http://selenium-chrome:4444/wd/hub"
BROWSER: chrome
BROWSER_HEADLESS: "true"
START_XVFB: "false" # not needed for headless mode
SE_NODE_MAX_SESSIONS: "5"
SE_NODE_OVERRIDE_MAX_SESSIONS: "true"
# Settings for Selenium 3:
NODE_MAX_INSTANCES: "5"
NODE_MAX_SESSION: "5"
.variables_app_restart_cmd: &variables_app_restart_cmd
variables:
@ -65,11 +62,6 @@
tags:
- docker
.tags_docker_low_concurrency: &tags_docker_low_concurrency
tags:
- docker
- low_concurrency
# Workaround for blocked port 25 access on cloud provider infrastructure
.tags_mail: &tags_mail
tags:
@ -82,35 +74,35 @@
# DB Docker
.docker_mysql: &docker_mysql
name: $CI_REGISTRY/docker/zammad-mysql:stable
name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
.docker_postgresql: &docker_postgresql
name: $CI_REGISTRY/docker/zammad-postgresql:stable
name: registry.znuny.com/docker/zammad-postgresql:stable
alias: postgresql
.docker_elasticsearch: &docker_elasticsearch
name: $CI_REGISTRY/docker/zammad-elasticsearch:$ELASTICSEARCH_TAG
name: registry.znuny.com/docker/zammad-elasticsearch:$ELASTICSEARCH_TAG
alias: elasticsearch
.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
.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
.docker_imap: &docker_imap
name: $CI_REGISTRY/docker/zammad-imap:stable
name: registry.znuny.com/docker/zammad-imap:stable
alias: mail
.docker_redis: &docker_redis
name: $CI_REGISTRY/docker/zammad-redis:stable
name: registry.znuny.com/docker/zammad-redis:stable
alias: redis
.docker_memcached: &docker_memcached
name: $CI_REGISTRY/docker/zammad-memcached:stable
name: registry.znuny.com/docker/zammad-memcached:stable
alias: memcached
command: ["memcached", "-m", "256M"]
@ -139,6 +131,11 @@
- <<: *docker_redis
- <<: *docker_memcached
.services_mysql_postgresql: &services_mysql_postgresql
services:
- <<: *docker_mysql
- <<: *docker_postgresql
.services_mysql_postgresql_redis_memcached: &services_mysql_postgresql_redis_memcached
extends:
- .variables_redis_memcached
@ -169,6 +166,8 @@
- <<: *docker_imap
.services_mysql_postgresql_elasticsearch: &services_mysql_postgresql_elasticsearch
variables:
ELASTICSEARCH_TAG: 'stable'
services:
- <<: *docker_mysql
- <<: *docker_postgresql
@ -177,6 +176,8 @@
.services_mysql_postgresql_elasticsearch_selenium_chrome_imap: &services_mysql_postgresql_elasticsearch_selenium_chrome_imap
extends:
- .variables_selenium_chrome
variables:
ELASTICSEARCH_TAG: 'stable'
services:
- <<: *docker_mysql
- <<: *docker_postgresql
@ -187,6 +188,8 @@
.services_mysql_postgresql_elasticsearch_selenium_firefox_imap: &services_mysql_postgresql_elasticsearch_selenium_firefox_imap
extends:
- .variables_selenium_firefox
variables:
ELASTICSEARCH_TAG: 'stable'
services:
- <<: *docker_mysql
- <<: *docker_postgresql
@ -198,6 +201,8 @@
extends:
- .variables_selenium_chrome
- .variables_redis_memcached
variables:
ELASTICSEARCH_TAG: 'stable'
services:
- <<: *docker_mysql
- <<: *docker_postgresql
@ -211,6 +216,8 @@
extends:
- .variables_selenium_firefox
- .variables_redis_memcached
variables:
ELASTICSEARCH_TAG: 'stable'
services:
- <<: *docker_mysql
- <<: *docker_postgresql

View file

@ -19,15 +19,12 @@ include:
- .env_base
- .variables_es
- .variables_app_restart_cmd
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "production"
script:
- script/build/test_slice_tests.sh $TEST_SLICE
- RAILS_ENV=test bundle exec rake db:create
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_start[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:start"
- bundle exec rake zammad:ci:test:start[with_elasticsearch]
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_start\\r\\e[0K"
- time bundle exec rails test --fail-fast test/browser
.template_browser-core_chrome: &template_browser-core_chrome
@ -47,7 +44,6 @@ include:
extends:
- .env_base
- .variables_app_restart_cmd
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "production"
AUTO_WIZARD_FILE: "contrib/auto_wizard_example.json"
@ -55,9 +51,7 @@ include:
script:
- RAILS_ENV=test bundle exec rake db:create
- cp $AUTO_WIZARD_FILE auto_wizard.json
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_start[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:start"
- bundle exec rake zammad:ci:test:start
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_start\\r\\e[0K"
- bundle exec rails test $TEST_FILE
.template_browser-core_autowizard_chrome: &template_browser-core_autowizard_chrome
@ -78,7 +72,6 @@ include:
- .env_base
- .variables_app_restart_cmd
- .services_mysql_postgresql_redis_memcached
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "production"
@ -90,13 +83,10 @@ include:
- .env_base
- .variables_es
- .variables_rspec_slicing
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "test"
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_prepare[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:prepare"
- bundle exec rake zammad:ci:test:prepare
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_prepare\\r\\e[0K"
- echo "RSpec filter:" "$RSPEC_EXAMPLE_MATCHES"
- bundle exec rspec --require ./spec/rspec_extensions.rb --example-matches "$RSPEC_EXAMPLE_MATCHES" --fail-fast -t ~integration --profile 10 spec/system

View file

@ -7,9 +7,7 @@ api_client_php:
ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_PASSWORD: "test"
script:
- RAILS_ENV=test bundle exec rake db:create
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_start[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:start"
- RAILS_ENV=test bundle exec rake zammad:ci:test:start zammad:setup:auto_wizard
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_start\\r\\e[0K"
- git clone https://github.com/zammad/zammad-api-client-php.git
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php --install-dir=/usr/local/bin

View file

@ -4,9 +4,7 @@ api_client_ruby:
script:
- RAILS_ENV=test bundle exec rake db:create
- cp contrib/auto_wizard_test.json auto_wizard.json
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_start[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:start"
- bundle exec rake zammad:ci:test:start
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_start\\r\\e[0K"
- git clone https://github.com/zammad/zammad-api-client-ruby.git
- cd zammad-api-client-ruby
- bundle update --bundler

View file

@ -13,7 +13,5 @@ browser:build:
variables:
RAILS_ENV: "production"
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_unseeded[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:unseeded"
- bundle exec rake zammad:db:unseeded
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_unseeded\\r\\e[0K"
- bundle exec rake assets:precompile

View file

@ -27,3 +27,9 @@
- .template_browser-core_chrome
variables:
TEST_SLICE: "5"
6_chrome:
extends:
- .template_browser-core_chrome
variables:
TEST_SLICE: "6"

View file

@ -28,3 +28,9 @@
- .template_browser-core_firefox
variables:
TEST_SLICE: "5"
6_firefox:
extends:
- .template_browser-core_firefox
variables:
TEST_SLICE: "6"

View file

@ -14,13 +14,10 @@ include:
- .env_base
- .variables_app_restart_cmd
- .variables_es
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "test"
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_prepare[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:prepare"
- bundle exec rake zammad:ci:test:prepare
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_prepare\\r\\e[0K"
- bundle exec rspec --fail-fast --pattern "spec/system/**/*_spec.rb" -t integration --profile 10
.template_browser-integration_capybara_chrome: &template_browser-integration_capybara_chrome
@ -41,16 +38,13 @@ include:
- .env_base
- .variables_app_restart_cmd
- .services_postgresql_selenium_chrome
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "production"
AUTO_WIZARD_FILE: "contrib/auto_wizard_test.json"
script:
- RAILS_ENV=test bundle exec rake db:create
- cp $AUTO_WIZARD_FILE auto_wizard.json
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_start[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:start"
- bundle exec rake zammad:ci:test:start
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_start\\r\\e[0K"
- bundle exec rails test $TEST_FILE
.template_browser-integration_import_chrome: &template_browser-integration_import_chrome
@ -60,15 +54,12 @@ include:
extends:
- .env_base
- .services_postgresql_selenium_chrome
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "production"
RAILS_SERVE_STATIC_FILES: "true"
script:
- RAILS_ENV=test bundle exec rake db:create
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_start[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:start"
- bundle exec rake zammad:ci:test:start
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_ci_test_start\\r\\e[0K"
- bundle exec rails test $TEST_FILE
# we need at least one job to store and include this template

View file

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

View file

@ -1,12 +1,16 @@
include:
- local: '/.gitlab/ci/integration/clearbit.yml'
- local: '/.gitlab/ci/integration/email_helper_deliver.yml'
- local: '/.gitlab/ci/integration/es.yml'
- local: '/.gitlab/ci/integration/other.yml'
- local: '/.gitlab/ci/integration/geo.yml'
- local: '/.gitlab/ci/integration/otrs.yml'
- local: '/.gitlab/ci/integration/slack.yml'
- local: '/.gitlab/ci/integration/user_agent.yml'
.template_integration: &template_integration
extends:
- .env_base
- .services_mysql_postgresql_imap
- .services_mysql_postgresql
- .rules_integration_manual_start
tags:
- integration

View file

@ -0,0 +1,7 @@
clearbit:
extends:
- .template_integration
script:
- bundle exec rake zammad:db:unseeded
- bundle exec rails test test/integration/clearbit_test.rb
allow_failure: true

View file

@ -0,0 +1,11 @@
email_helper_deliver:
extends:
- .template_integration
- .tags_mail
- .services_mysql_postgresql_imap
script:
- bundle exec rake zammad:db:unseeded
- bundle exec rails test test/integration/email_helper_test.rb
- bundle exec rails test test/integration/email_deliver_test.rb
- bundle exec rails test test/integration/email_keep_on_server_test.rb
- bundle exec rails test test/integration/email_postmaster_to_sender.rb

View file

@ -7,23 +7,20 @@
tags:
- integration
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_unseeded[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:unseeded"
- bundle exec rake zammad:db:unseeded
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_unseeded\\r\\e[0K"
- bundle exec rails test test/integration/elasticsearch_active_test.rb
- bundle exec rails test test/integration/elasticsearch_test.rb
- bundle exec rspec --tag searchindex --tag ~type:system --profile 10
- bundle exec rails test test/integration/report_test.rb
# Lowest supported version
"rspec:es:7.8":
es:7:
<<: *template_integration_es
variables:
ELASTICSEARCH_TAG: '7'
RAILS_ENV: "test"
es:7.8:
<<: *template_integration_es
variables:
ELASTICSEARCH_TAG: '7.8.1'
RAILS_ENV: "test"
# Highest supported version (except for newer releases that are not yet in CI)
"rspec:es:7.16":
<<: *template_integration_es
variables:
ELASTICSEARCH_TAG: '7.16'
RAILS_ENV: "test"

View file

@ -0,0 +1,8 @@
geo:
extends:
- .template_integration
script:
- bundle exec rake zammad:db:unseeded
- bundle exec rails test test/integration/geo_calendar_test.rb
- bundle exec rails test test/integration/geo_location_test.rb
- bundle exec rails test test/integration/geo_ip_test.rb

View file

@ -1,27 +0,0 @@
"minitest:integration:other":
extends:
- .template_integration
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_unseeded[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:unseeded"
- bundle exec rake zammad:db:unseeded
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_unseeded\\r\\e[0K"
- echo "email_helper_deliver tests..."
- bundle exec rails test test/integration/email_helper_test.rb
- bundle exec rails test test/integration/email_deliver_test.rb
- bundle exec rails test test/integration/email_keep_on_server_test.rb
- bundle exec rails test test/integration/email_postmaster_to_sender.rb
- echo "Clearbit test..."
- bundle exec rails test test/integration/clearbit_test.rb
- echo "Geo tests..."
- bundle exec rails test test/integration/geo_calendar_test.rb
- bundle exec rails test test/integration/geo_location_test.rb
- bundle exec rails test test/integration/geo_ip_test.rb
- echo "Slack test..."
- bundle exec rails test test/integration/slack_test.rb
- echo "UserAgent tests..."
- bundle exec rails test test/integration/user_agent_test.rb
- export ZAMMAD_PROXY_TEST=true
- bundle exec rails test test/integration/user_agent_test.rb
allow_failure: true

View file

@ -2,83 +2,81 @@
extends:
- .template_integration
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_unseeded[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:unseeded"
- bundle exec rake zammad:db:unseeded
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_unseeded\\r\\e[0K"
- bundle exec rails test test/integration/otrs_import_test.rb
variables:
FF_NETWORK_PER_BUILD: 1 # https://docs.gitlab.com/runner/configuration/feature-flags.html
IMPORT_OTRS_ENDPOINT: 'http://zammad-ci-otrsimport-app/otrs/public.pl?Action=ZammadMigrator'
TZ: 'Europe/Berlin' # Required for the zammad-ci-otrsimport-app containers
IMPORT_OTRS_ENDPOINT: "http://zammad-ci-otrsimport-app/otrs/public.pl?Action=ZammadMigrator"
TZ: "Europe/Berlin" # Required for the zammad-ci-otrsimport-app containers
'minitest:integration:otrs:6':
otrs:6:
<<: *template_integration_otrs
services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable
- name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable
- name: registry.znuny.com/docker/zammad-postgresql:stable
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
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs6
- name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs6
alias: zammad-ci-otrsimport-app
'minitest:integration:otrs:5':
otrs:5:
<<: *template_integration_otrs
services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable
- name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable
- name: registry.znuny.com/docker/zammad-postgresql:stable
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
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs5
- name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs5
alias: zammad-ci-otrsimport-app
'minitest:integration:otrs:4':
otrs:4:
<<: *template_integration_otrs
services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable
- name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable
- name: registry.znuny.com/docker/zammad-postgresql:stable
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
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs4
- name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs4
alias: zammad-ci-otrsimport-app
'minitest:integration:otrs:33':
otrs:33:
<<: *template_integration_otrs
services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable
- name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable
- name: registry.znuny.com/docker/zammad-postgresql:stable
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
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs33
- name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs33
alias: zammad-ci-otrsimport-app
'minitest:integration:otrs:32':
otrs:32:
<<: *template_integration_otrs
services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable
- name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable
- name: registry.znuny.com/docker/zammad-postgresql:stable
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
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs32
- name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs32
alias: zammad-ci-otrsimport-app
'minitest:integration:otrs:31':
otrs:31:
<<: *template_integration_otrs
services:
- name: $CI_REGISTRY/docker/zammad-mysql:stable
- name: registry.znuny.com/docker/zammad-mysql:stable
alias: mysql
- name: $CI_REGISTRY/docker/zammad-postgresql:stable
- name: registry.znuny.com/docker/zammad-postgresql:stable
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
- name: $CI_REGISTRY/docker/zammad-ci-otrsimport-app:otrs31
- name: registry.znuny.com/docker/zammad-ci-otrsimport-app:otrs31
alias: zammad-ci-otrsimport-app

View file

@ -0,0 +1,13 @@
slack:
extends:
- .template_integration
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
- if: '$CI_COMMIT_BRANCH =~ /^private/'
when: manual
allow_failure: true
- when: on_success
script:
- bundle exec rake zammad:db:unseeded
- bundle exec rails test test/integration/slack_test.rb

View file

@ -0,0 +1,8 @@
user_agent:
extends:
- .template_integration
script:
- bundle exec rake zammad:db:unseeded
- bundle exec rails test test/integration/user_agent_test.rb
- export ZAMMAD_PROXY_TEST=true
- bundle exec rails test test/integration/user_agent_test.rb

View file

@ -6,28 +6,15 @@
- .rules_singletest
before_script:
- 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
.template_pre_rails: &template_pre_rails
stage: pre
extends:
- .tags_docker
- .rules_singletest
- .services_postgresql
before_script:
- source /etc/profile.d/rvm.sh # ensure RVM is loaded
- source /opt/rh/rh-nodejs*/enable # ensure Node.js is available
- echo -e "\\e[0Ksection_start:`date +%s`:bundle_install[collapsed=true]\\r\\e[0Kbundle install"
rubocop:
<<: *template_pre
script:
- bundle install -j $(nproc) --path vendor
- echo -e "\\e[0Ksection_end:`date +%s`:bundle_install\\r\\e[0K"
- bundle exec ruby .gitlab/configure_environment.rb
- source .gitlab/environment.env
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_init[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:init"
- bundle exec rake zammad:db:init
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_init\\r\\e[0K"
- bundle exec rubocop --parallel
# Must be a separate job because it uses a custom image.
"lint: shellcheck":
shellcheck:
<<: *template_pre
image: koalaman/shellcheck-alpine:stable
before_script:
@ -35,65 +22,48 @@
script:
- shellcheck -S warning $(find . -name "*.sh" -o -name "functions" | grep -v "/vendor/")
"lint: i18n, rails & security":
<<: *template_pre_rails
zeitwerk_check:
<<: *template_pre
extends:
- .tags_docker
- .services_postgresql
script:
- bundle install -j $(nproc) --path vendor
- bundle exec ruby .gitlab/configure_environment.rb
- source .gitlab/environment.env
- bundle exec rake zammad:db:init
- bundle exec rails zeitwerk:check
brakeman:
<<: *template_pre
artifacts:
expire_in: 1 week
paths:
- tmp/brakeman-report.html
when: on_failure
script:
- echo "Checking .po file syntax..."
- for FILE in i18n/*.pot i18n/*.po; do echo "Checking $FILE"; msgfmt -o /dev/null -c $FILE; done
- echo "Checking .pot catalog consistency..."
- bundle exec rails generate translation_catalog --check
- echo "Brakeman security check..."
- bundle install -j $(nproc) --path vendor
- bundle exec brakeman -o /dev/stdout -o tmp/brakeman-report.html
- echo "bundler-audit security check..."
coffeelint:
<<: *template_pre
script:
- coffeelint app/
bundle-audit:
<<: *template_pre
script:
- gem install bundler-audit
- bundle-audit update
- bundle-audit --ignore CVE-2015-9284
- echo "Rails zeitwerk:check autoloader check..."
- bundle exec rails zeitwerk:check
"lint: ruby, js & css":
<<: *template_pre
script:
- echo "Coffeelint check..."
- coffeelint --rules ./.coffeelint/rules/* app/
- echo "Stylelint check..."
- yarn install
- yarn lint:css
- echo "Rubocop check..."
- echo -e "\\e[0Ksection_start:`date +%s`:bundle_install[collapsed=true]\\r\\e[0Kbundle install"
- bundle install -j $(nproc) --path vendor
- echo -e "\\e[0Ksection_end:`date +%s`:bundle_install\\r\\e[0K"
- bundle exec rubocop --parallel
# Must be a separate job because it may fail and is only executed for develop.
"lint: orphaned ruby gems":
<<: *template_pre_rails
allow_failure: true
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: always
- when: manual
script:
- bundle exec rake zammad:ci:bundle:orphaned 5
# Executed on a dedicated runner.
"push to github":
github:
<<: *template_pre
tags:
- deploy
before_script:
- test -d $HOME/.ssh || mkdir $HOME/.ssh
- ssh-keyscan github.com >> $HOME/.ssh/known_hosts
- eval $(ssh-agent -s)
- echo "$PUSH_TO_GITHUB_SSH_PRIVATE_KEY" | ssh-add -
- ssh-add -l
- "" # no RVM present in deploy ENV
script:
- git fetch --unshallow
- script/build/sync_repo.sh git@github.com:zammad/zammad.git
global_refresh_envs:
@ -105,7 +75,7 @@ global_refresh_envs:
resource_group: global_refresh_envs
# allow download via the web UI to restore ENVs in case global cache got deleted (see: `.gitlab-ci.yml`)
artifacts:
expire_in: 1 week
expire_in: 1 day
paths:
- fresh.env
rules:

View file

@ -7,9 +7,7 @@ include:
- .env_base
- .variables_rspec_slicing
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_init[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:init"
- bundle exec rake zammad:db:init
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_init\\r\\e[0K"
- echo "RSpec filter:" "$RSPEC_EXAMPLE_MATCHES"
- bundle exec rspec --require ./spec/rspec_extensions.rb --example-matches "$RSPEC_EXAMPLE_MATCHES" --exclude-pattern "spec/{system,integration}/**/*_spec.rb" -t ~searchindex --profile 10
@ -25,8 +23,13 @@ rspec:integration:
- .rules_integration_manual_start
variables:
RAILS_ENV: "test"
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
- if: '$CI_COMMIT_BRANCH =~ /^private/ && $INTEGRATION_TESTS != "enabled"'
when: manual
allow_failure: true
- when: always
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_init[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:init"
- bundle exec rake zammad:db:init
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_init\\r\\e[0K"
- bundle exec rspec -t type:integration --profile 10

View file

@ -8,9 +8,7 @@ include:
variables:
RAILS_ENV: "test"
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_db_init[collapsed=true]\\r\\e[0Kbundle exec rake zammad:db:init"
- bundle exec rake zammad:db:init
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_init\\r\\e[0K"
- bundle exec rake test:units
- bundle exec rails test test/integration/object_manager_test.rb
- bundle exec rails test test/integration/package_test.rb

View file

@ -1,5 +1,5 @@
#!/usr/bin/env ruby
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'yaml'
require 'resolv'

View file

@ -86,7 +86,7 @@ This MR does not require any follow-up.
- [ ] Implementation satisfies specification
- [ ] Changes confirmed by manual testing
- [ ] [Code style](https://git.zammad.com/zammad/zammad/-/wikis/Coding-style-guide) is appropriate
- [ ] [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:

View file

@ -1,23 +0,0 @@
## What does this MR do?
<!--Insert the link to a Asana card in (), or describe the task/changec if there is no related task (but normally there should be always a referenced task) -->
[Asana Task Link]()
## ToDo Checklist
- [ ] Checked that the needed functionality is not already available in a common component.
- [ ] Checked if newly created components can be added in a common way (e.g. common component).
- [ ] Created or changed story for common component.
- [ ] Covered common component with Jest-Test
- [ ] Checked that i didn't add a API request inside of a common component.
- [ ] Covered new functionality with Jest-Test(*)
- [ ] When relevant: Covered new GraphQL (Mutation/Query) with a request test.
(*) Jest tests are normally only needed for the common components or other typescript functionality, because the other functionality will be tested with selenium tests and own GraphQL-API tests (with this we avoid that we need always to mock the graphql calls). But for sure special frontend handling should also be tested with a jest test.
## QA Checklist (to be filled by the reviewer)
- [ ] Implementation satisfies specification
- [ ] Changes confirmed by manual testing
- [ ] [Code style](https://git.zammad.com/zammad/zammad/-/wikis/Coding-style-guide) is appropriate
- [ ] Code is properly covered with tests

View file

@ -1,17 +0,0 @@
## What does this MR do?
<!--Insert the link to a Asana card in (), or describe the task/changec if there is no related task (but normally there should be always a referenced task) -->
[Asana Task Link]()
## ToDo Checklist
- [ ] Checked that the feature will also work in the scope of packages.
- [ ] Added comments for "special" core code parts.
- [ ] Added the feature in the "developer manual" with some clear explanation and examples for the usage.
## QA Checklist (to be filled by the reviewer)
- [ ] Implementation satisfies specification
- [ ] Changes confirmed by manual testing
- [ ] [Code style](https://git.zammad.com/zammad/zammad/-/wikis/Coding-style-guide) is appropriate
- [ ] Code is properly covered with tests

View file

@ -1,6 +1,3 @@
# Don't complain when changing branches with different overcommit configurations.
verify_signatures: false
CommitMsg:
ALL:
enabled: false
@ -12,25 +9,10 @@ PreCommit:
enabled: false
RuboCop:
enabled: true
on_warn: fail
on_warn: fail # Treat all warnings as failures
CoffeeLint:
# .coffeelint/rules/* not supported in YAML, specify all rules separately.
flags:
[
'--reporter=csv',
'--rules',
'./.coffeelint/rules/detect_translatable_string.coffee',
]
enabled: true
on_warn: fail
exclude: 'public/assets/chat/**/*'
CustomScript:
enabled: true
description: 'Check if translation catalog is up-to-date'
required_executable: 'rails'
flags: ['generate', 'translation_catalog', '--check']
Stylelint:
enabled: true
on_warn: fail # Treat all warnings as failures
PostCheckout:
ALL:
@ -59,3 +41,4 @@ PreRebase:
PrepareCommitMsg:
ALL:
enabled: false

View file

@ -56,18 +56,6 @@ targets:
- libimlib2
- libimlib2-dev
- 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:
dependencies:
- curl

View file

@ -1,6 +0,0 @@
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
}

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop

View file

@ -1,90 +0,0 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
module RuboCop
module Cop
module Zammad
class DetectTranslatableString < Base
extend AutoCorrector
MSG = 'This string looks like it should be marked as translatable via __(...).'.freeze
def on_str(node)
# Constants like __FILE__ are handled as strings, but don't respond to begin.
return if !node.loc.respond_to?(:begin) || !node.loc.begin
return if part_of_ignored_node?(node)
return if !offense?(node)
add_offense(node) do |corrector|
corrector.replace(node, "__(#{node.source})")
end
end
def on_regexp(node)
ignore_node(node)
end
METHOD_NAME_BLOCKLIST = %i[
__ translate
include? eql? parse
debug info warn error fatal unknown log log_error
].freeze
def on_send(node)
ignore_node(node) if METHOD_NAME_BLOCKLIST.include? node.method_name
end
private
PARENT_SOURCE_BLOCKLIST = [
# Ignore logged strings
'Rails.logger'
].freeze
NODE_START_BLOCKLIST = [
# Only look at strings starting with upper case letters
%r{[^A-Z]},
# Ignore strings starting with three upper case letters like SELECT, POST etc.
%r{[A-Z]{3}},
].freeze
NODE_CONTAIN_BLOCKLIST = [
# Ignore strings with interpolation.
'#{',
# Ignore Email addresses
'@'
].freeze
def offense?(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# Ignore Hash Keys
return false if node.parent.type.eql?(:pair) && node.parent.children.first.equal?(node)
# Ignore equality checks like ... == 'My String'
return false if node.left_sibling.eql?(:==)
# Remove quotes
node_source = node.source[1..-2]
# Only match strings with at least two words
return false if node_source.split.count < 2
NODE_START_BLOCKLIST.each do |entry|
return false if node_source.start_with? entry
end
NODE_CONTAIN_BLOCKLIST.each do |entry|
return false if node_source.include? entry
end
parent_source = node.parent.source
PARENT_SOURCE_BLOCKLIST.each do |entry|
return false if parent_source.include? entry
end
true
end
end
end
end
end

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop
@ -17,7 +17,7 @@ module RuboCop
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
MSG = 'Add a `db_strategy: :reset` to your context/decribe when you are creating object manager attributes!'.freeze

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop
@ -54,9 +54,7 @@ and check if there are reset_column_information function calls existing for the
end
def reset_class(node)
# simplify namespaced class names
# Rubocop can't reliably convert table names to namespaced class names
node.children[0].const_name.gsub '::', ''
node.children[0].children[1].to_s
end
def table_class(node)

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop

View file

@ -1,17 +0,0 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
module RuboCop
module Cop
module Zammad
class ForbidTranslatableMarker < Base
MSG = <<~ERROR_MESSAGE.freeze
Don't use __() in Zammad core migrations. Translatable strings should be marked where they are defined, e.g. in the DB seeds.
ERROR_MESSAGE
def on_send(node)
add_offense(node) if node.method_name.eql? :__
end
end
end
end
end

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'capybara/rspec/matchers'

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
module RuboCop
module Cop
@ -9,7 +9,7 @@ module RuboCop
extend AutoCorrector
MSG = 'Copyright update required (use auto-correct to rectify this).'.freeze
COPYRIGHT = "# Copyright (C) 2012-#{Date.today.year} Zammad Foundation, https://zammad-foundation.org/".freeze # rubocop:disable Rails/Date
COPYRIGHT = "# Copyright (C) 2012-#{Date.today.year} Zammad Foundation, http://zammad-foundation.org/".freeze # rubocop:disable Rails/Date
def on_new_investigation
if processed_source.raw_source.include? '# Copyright (C) 2012-'

View file

@ -189,10 +189,6 @@ Rails/SkipsModelValidations:
- "**/*_spec.rb"
- "**/*_examples.rb"
Rails/ReversibleMigration:
Description: This cop checks whether the change method of the migration file is reversible.
Enabled: false
Style/ClassAndModuleChildren:
Description: 'Checks style of children classes and modules.'
Enabled: false
@ -321,25 +317,6 @@ Zammad/ExistsResetColumnInformation:
- 'db/migrate/201*_*.rb'
- 'db/migrate/2020*_*.rb'
Zammad/DetectTranslatableString:
Enabled: true
Include:
- "app/**/*.rb"
- "db/**/*.rb"
- "lib/**/*.rb"
Exclude:
- "db/migrate/**/*.rb"
- "db/addon/**/*.rb"
- "lib/generators/**/*.rb"
- "lib/sequencer/**/*.rb"
- "lib/import/**/*.rb"
- "lib/tasks/**/*.rb"
Zammad/ForbidTranslatableMarker:
Enabled: true
Include:
- "db/migrate/*.rb"
Zammad/ExistsDbStrategy:
Include:
- "spec/**/*.rb"

View file

@ -1,7 +1,6 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require_relative 'cop/zammad/exists_condition'
require_relative 'cop/zammad/detect_translatable_string'
require_relative 'cop/zammad/exists_date_time_precision'
require_relative 'cop/zammad/exists_db_strategy'
require_relative 'cop/zammad/exists_reset_column_information'
@ -11,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/update_copyright'
require_relative 'cop/zammad/forbid_rand'
require_relative 'cop/zammad/forbid_translatable_marker'

View file

@ -412,6 +412,16 @@ RSpec/MessageSpies:
- 'spec/lib/import/otrs/ticket_spec.rb'
- 'spec/lib/import/otrs/user_factory_spec.rb'
- 'spec/lib/import/otrs/user_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/base_examples.rb'
- 'spec/lib/import/zendesk/object_attribute/checkbox_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/date_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/decimal_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/dropdown_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/integer_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/regexp_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/tagger_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/text_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/textarea_spec.rb'
- 'spec/lib/ldap/group_spec.rb'
- 'spec/lib/ldap/guid_spec.rb'
- 'spec/lib/ldap/user_spec.rb'
@ -473,6 +483,16 @@ RSpec/MultipleExpectations:
- 'spec/lib/import/otrs/priority_factory_spec.rb'
- 'spec/lib/import/otrs/requester_spec.rb'
- 'spec/lib/import/otrs/state_factory_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/base_examples.rb'
- 'spec/lib/import/zendesk/object_attribute/checkbox_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/date_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/decimal_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/dropdown_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/integer_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/regexp_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/tagger_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/text_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/textarea_spec.rb'
- 'spec/lib/ldap/group_spec.rb'
- 'spec/lib/ldap/guid_spec.rb'
- 'spec/lib/ldap/user_spec.rb'
@ -640,6 +660,16 @@ RSpec/VerifiedDoubles:
- 'spec/db/migrate/issue_2460_fix_corrupted_twitter_ids_spec.rb'
- 'spec/jobs/communicate_twitter_job_spec.rb'
- 'spec/lib/external_sync_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/base_examples.rb'
- 'spec/lib/import/zendesk/object_attribute/checkbox_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/date_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/decimal_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/dropdown_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/integer_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/regexp_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/tagger_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/text_spec.rb'
- 'spec/lib/import/zendesk/object_attribute/textarea_spec.rb'
- 'spec/lib/ldap_spec.rb'
- 'spec/lib/sequencer/sequence/import/ldap/users_spec.rb'
- 'spec/lib/sequencer/unit/import/zendesk/sub_sequence/base_examples.rb'

View file

@ -883,6 +883,7 @@ Metrics/PerceivedComplexity:
- 'lib/twitter_sync.rb'
- 'lib/user_agent.rb'
- 'test/browser/admin_object_manager_test.rb'
- 'test/browser/keyboard_shortcuts_test.rb'
- 'test/browser_test_helper.rb'
- 'test/integration/slack_test.rb'

View file

@ -1,50 +0,0 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-standard-scss",
"stylelint-prettier/recommended"
],
"rules": {
"alpha-value-notation": null,
"block-no-empty": null,
"color-function-notation": "legacy",
"declaration-block-no-duplicate-properties": null,
"declaration-block-no-redundant-longhand-properties": null,
"declaration-block-no-shorthand-property-overrides": null,
"declaration-block-single-line-max-declarations": null,
"font-family-no-missing-generic-family-keyword": null,
"function-calc-no-unspaced-operator": null,
"function-comma-space-after": null,
"hue-degree-notation": null,
"keyframes-name-pattern": null,
"max-empty-lines": null,
"no-descending-specificity": null,
"no-duplicate-selectors": null,
"number-max-precision": null,
"selector-class-pattern": null,
"selector-list-comma-newline-after": null,
"selector-no-vendor-prefix": null,
"selector-pseudo-element-no-unknown": null,
"scss/at-extend-no-missing-placeholder": null,
"scss/at-rule-no-unknown": null,
"scss/dollar-variable-pattern": null,
"scss/double-slash-comment-whitespace-inside": null,
"scss/no-global-function-names": null,
"value-no-vendor-prefix": null,
"property-no-unknown": [true, { "ignoreProperties": ["scroll-snap-mode"] }],
"property-no-vendor-prefix": null
},
"ignoreFiles": [
"public/assets/*.css",
"public/assets/chat/chat.css",
"public/assets/doorkeeper/**",
"**/reset*.css",
"**/bootstrap*.css",
"**/jquery*.css",
"**/cropper.css",
"**/fineuploader.css",
"**/qunit*.css",
"**/svg-dimensions.css",
"vendor/**"
]
}

View file

@ -1,195 +1,15 @@
# Change Log
## [5.1.1](https://github.com/zammad/zammad/tree/5.1.1) (2022-04-20)
[Full Changelog](https://github.com/zammad/zammad/compare/5.1.0...5.1.1)
**Implemented enhancements:**
- Allow reauthentication of Google / Microsoft 365 accounts [3240](https://github.com/zammad/zammad/issues/3240) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[channel](https://github.com/zammad/zammad/labels/channel)]
**Fixed bugs:**
- Error on second migration of an microsoft365 channel undefined method `options' for nil:NilClass [4060](https://github.com/zammad/zammad/issues/4060) [[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%20by%20payment)]
- Freshdesk migration which doesn't support time entries runs in unwanted behaviour [4052](https://github.com/zammad/zammad/issues/4052) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Freshdesk-Migration does not like no Companies / Organisations within the source [4051](https://github.com/zammad/zammad/issues/4051) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Cannot encrypt if multiple S/MIME certificates exist and one is expired [4029](https://github.com/zammad/zammad/issues/4029) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Core Workflow: Does show wrong field list if you only have admin permissions and not ticket.agent permissions [4035](https://github.com/zammad/zammad/issues/4035) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Can't delete smime certificate - ERROR: duplicate key value violates unique constraint [4049](https://github.com/zammad/zammad/issues/4049) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Knowledge Base on-the-fly updating does not work [4026](https://github.com/zammad/zammad/issues/4026) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Core Workflow - Unable to select "has changed" logic when creating new workflow. It is also replaced with "is" in previously created workflows. [4046](https://github.com/zammad/zammad/issues/4046) [[bug](https://github.com/zammad/zammad/labels/bug)]
- undefined method `to_hash` on editing select fields in the admin interface after migration to 5.1 [4027](https://github.com/zammad/zammad/issues/4027) [[bug](https://github.com/zammad/zammad/labels/bug)]
- KB Public menus scroll bar positioning incorrect [4008](https://github.com/zammad/zammad/issues/4008) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Problems with duplicate records in Translations table [4020](https://github.com/zammad/zammad/issues/4020) [[bug](https://github.com/zammad/zammad/labels/bug)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- Tree select value cannot be set to "-" (empty) with Trigger/Scheduler/Core workflow [4024](https://github.com/zammad/zammad/issues/4024) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Admin macros are not usable with admin permissions only [4032](https://github.com/zammad/zammad/issues/4032) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Admin SLA index view does not show update time if "for agent respond" is selected [4033](https://github.com/zammad/zammad/issues/4033) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Core Workflow: Stop after match is not saved [4034](https://github.com/zammad/zammad/issues/4034) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- Freshdesk import error when a inline image source attribute contains no clean url [4028](https://github.com/zammad/zammad/issues/4028) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Mention history does not show properly who got added [3984](https://github.com/zammad/zammad/issues/3984) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[history](https://github.com/zammad/zammad/labels/history)]
- Obsolete notice field in admin calendar view [4023](https://github.com/zammad/zammad/issues/4023) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)]
- Error “customer_id required” on Macro execution [4022](https://github.com/zammad/zammad/issues/4022) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[macros](https://github.com/zammad/zammad/labels/macros)]
- Translations are not available in API after syncing [4016](https://github.com/zammad/zammad/issues/4016) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Upgraded to 5.1.0: pending time doesnt show a date [4018](https://github.com/zammad/zammad/issues/4018) [[bug](https://github.com/zammad/zammad/labels/bug)] [[translation](https://github.com/zammad/zammad/labels/translation)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- UI is not updated right after importing users csv file [3919](https://github.com/zammad/zammad/issues/3919) [[bug](https://github.com/zammad/zammad/labels/bug)]
- LDAP with many groups (<5k) and group role relation (>50) will crash in frontend [3994](https://github.com/zammad/zammad/issues/3994) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[LDAP](https://github.com/zammad/zammad/labels/LDAP)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
## [5.1.0](https://github.com/zammad/zammad/tree/5.1.0) (2022-03-14)
## [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)
**Implemented enhancements:**
- added russian translations to mail notifications [3780](https://github.com/zammad/zammad/pull/3780) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[notification](https://github.com/zammad/zammad/labels/notification)]
- Draft Sharing: Add history entry for updating and deleting of a draft [3983](https://github.com/zammad/zammad/issues/3983) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[draft sharing](https://github.com/zammad/zammad/labels/draft%20sharing)]
- Draft Sharing: Improve sidebar icon order for ticket creation [3982](https://github.com/zammad/zammad/issues/3982) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[draft sharing](https://github.com/zammad/zammad/labels/draft%20sharing)]
- Make sidebar attachments unique [3930](https://github.com/zammad/zammad/issues/3930) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Draft Sharing [629](https://github.com/zammad/zammad/issues/629) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[feature backlog](https://github.com/zammad/zammad/labels/feature%20backlog)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Limit access to KB Categories based on roles [2603](https://github.com/zammad/zammad/issues/2603) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Enhance CTI integration texts [2753](https://github.com/zammad/zammad/issues/2753) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)]
- Show which escalation type escalated in ticket zoom [3928](https://github.com/zammad/zammad/issues/3928) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Enable migration button feature for account migration MS365/Google channel [3960](https://github.com/zammad/zammad/issues/3960) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[needs verification](https://github.com/zammad/zammad/labels/needs%20verification)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Rename Third-Party login: Office 365 to Microsoft 365 [3245](https://github.com/zammad/zammad/issues/3245) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[third party issue](https://github.com/zammad/zammad/labels/third%20party%20issue)]
- Zammad backups (database and filesystem) are world-readable by default [3893](https://github.com/zammad/zammad/issues/3893) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Add confirmation dialog on visibility change of an article or in article creation [3924](https://github.com/zammad/zammad/issues/3924) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Be able to select more than one owner or organization in condition for overviews/triggers/schedulers like you can do it for state, priority or group [3900](https://github.com/zammad/zammad/issues/3900) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Zammad misses "weeks" for relative time events [2371](https://github.com/zammad/zammad/issues/2371) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Note is not being updated because of the lack of lastname [2429](https://github.com/zammad/zammad/issues/2429) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend%20%2F%20JS%20app)]
- Display callback urls for third-party applications [3622](https://github.com/zammad/zammad/issues/3622) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- SLA description only available in english [556](https://github.com/zammad/zammad/issues/556) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- 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%20by%20payment)] [[specification required](https://github.com/zammad/zammad/labels/specification%20required)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- Allow image popup and download within Chat [3210](https://github.com/zammad/zammad/issues/3210) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[chat](https://github.com/zammad/zammad/labels/chat)]
- Display name not used [2275](https://github.com/zammad/zammad/issues/2275) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend%20%2F%20JS%20app)]
- 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%2FUI)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)]
- Import for kayako during the setup [3698](https://github.com/zammad/zammad/issues/3698) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[import](https://github.com/zammad/zammad/labels/import)]
- Login site wording could be better [3000](https://github.com/zammad/zammad/issues/3000) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- 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%20by%20payment)]
- 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%20by%20payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail%20processing)]
**Fixed bugs:**
- Report profile "new profile" button does not match coloring scheme [4007](https://github.com/zammad/zammad/issues/4007) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)]
- "Note - visibility confirmation dialog" setting also requests confirmation for e.g. email and phone articles [4009](https://github.com/zammad/zammad/issues/4009) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- Ensure 4 column selections within UI does not cover add/remove buttons [3609](https://github.com/zammad/zammad/issues/3609) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)]
- KB RTL text direction has wrong spacing between some elements [3925](https://github.com/zammad/zammad/issues/3925) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[regression](https://github.com/zammad/zammad/labels/regression)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)] [[good first issue](https://github.com/zammad/zammad/labels/good%20first%20issue)]
- Fixes: Fix knowledge base spacing and layout [3987](https://github.com/zammad/zammad/pull/3987)
- Longer category names break boxes in mobile version [3665](https://github.com/zammad/zammad/issues/3665) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- KB: granular permissions misconfiguration is allowed by UI [3997](https://github.com/zammad/zammad/issues/3997) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Can not start a row in a knowledge base article with a linked answer [3965](https://github.com/zammad/zammad/issues/3965) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Long role names get broken due to bad overflow [3999](https://github.com/zammad/zammad/issues/3999) [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Overviews are not shown if `group_by` is used with a tree select attribute [4004](https://github.com/zammad/zammad/issues/4004) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Unable to upgrade to Zammad 5.1 [4000](https://github.com/zammad/zammad/issues/4000) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Select field in bulk operations out of view port [3995](https://github.com/zammad/zammad/issues/3995) [[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%2FUI)] [[overviews](https://github.com/zammad/zammad/labels/overviews)]
- No longer public KB answers do not return http 404 [3915](https://github.com/zammad/zammad/issues/3915) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Selecting custom ports for mail channel ends in 'host not reachable' [3964](https://github.com/zammad/zammad/issues/3964) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[channel](https://github.com/zammad/zammad/labels/channel)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Draft Sharing: Draft stays after new ticket creation [3981](https://github.com/zammad/zammad/issues/3981) [[bug](https://github.com/zammad/zammad/labels/bug)] [[question](https://github.com/zammad/zammad/labels/question)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[draft sharing](https://github.com/zammad/zammad/labels/draft%20sharing)]
- Modal backdrop not covering some UI parts [3974](https://github.com/zammad/zammad/issues/3974) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)]
- KB: Roles are displayed twice in permission dialog [3977](https://github.com/zammad/zammad/issues/3977) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- KB: Unpermitted categories are displayed after browsing [3978](https://github.com/zammad/zammad/issues/3978) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Frequent “Lost connection to MySQL server during query” errors resulting in client-side Error 500 [3969](https://github.com/zammad/zammad/issues/3969) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Not translated text with forwarding e-mails [3920](https://github.com/zammad/zammad/issues/3920) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- S/MIME function buttons no longer working in tickets [3957](https://github.com/zammad/zammad/issues/3957) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)]
- Migration of the MS365 account fails by upper and lower case differences in email address [3956](https://github.com/zammad/zammad/issues/3956) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Opening organization views throws console traces [3958](https://github.com/zammad/zammad/issues/3958) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)]
- Elasticsearch-Rebuild does not index from new to old [3955](https://github.com/zammad/zammad/issues/3955) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Can not chose SSL yes and port 143 when setting up mail account [3921](https://github.com/zammad/zammad/issues/3921) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Uncaught TypeError in ticket zoom highlighter [3950](https://github.com/zammad/zammad/issues/3950)
- New online notifications blocks data privacy user deletion [3942](https://github.com/zammad/zammad/issues/3942) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[data privacy](https://github.com/zammad/zammad/labels/data%20privacy)]
- Multiselects shows wrong display values in overviews [3944](https://github.com/zammad/zammad/issues/3944) [[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%20by%20payment)]
- dead lock on user update in high load environment [3940](https://github.com/zammad/zammad/issues/3940) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Zammad UI should silently discard Cache / apply2file errors [3685](https://github.com/zammad/zammad/issues/3685) [[bug](https://github.com/zammad/zammad/labels/bug)] [[waiting for feedback](https://github.com/zammad/zammad/labels/waiting%20for%20feedback)] [[can't reproduce](https://github.com/zammad/zammad/labels/can%27t%20reproduce)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Startup of Zammad does not synchronize the custom branding logo [3933](https://github.com/zammad/zammad/issues/3933) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Postgresql Backup & Restore failing on default package installations [3865](https://github.com/zammad/zammad/issues/3865) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Multiselect field support [3917](https://github.com/zammad/zammad/issues/3917) [[feature backlog](https://github.com/zammad/zammad/labels/feature%20backlog)] [[API](https://github.com/zammad/zammad/labels/API)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[form](https://github.com/zammad/zammad/labels/form)]
- JS error on editing textareas admin object manager attributes [3889](https://github.com/zammad/zammad/issues/3889) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)]
- Various translation fixes [3918](https://github.com/zammad/zammad/pull/3918)
- Make form style for `customer`-input consistent [3886](https://github.com/zammad/zammad/pull/3886) [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)]
- Wrong size for textareas in triggers and core workflow [3909](https://github.com/zammad/zammad/issues/3909) [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[trigger](https://github.com/zammad/zammad/labels/trigger)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- Placetel API v1 EOL within January 2022 [3910](https://github.com/zammad/zammad/issues/3910) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[third party issue](https://github.com/zammad/zammad/labels/third%20party%20issue)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Freshdesk import ends up in Zammad interface without navigation [3879](https://github.com/zammad/zammad/issues/3879) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[import](https://github.com/zammad/zammad/labels/import)]
- Changing ticket status from "new" to any other status always results in uncommited status "closed" [3880](https://github.com/zammad/zammad/issues/3880) [[bug](https://github.com/zammad/zammad/labels/bug)] [[can't reproduce](https://github.com/zammad/zammad/labels/can%27t%20reproduce)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- Usage of freshdesk import without freshdesk admin permission leads to an unstable system/missing data [3905](https://github.com/zammad/zammad/issues/3905) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Deactivation of signature does not clear it from groups [3129](https://github.com/zammad/zammad/issues/3129) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)]
- Ticket object does not get a rollback after failing bulk action [3817](https://github.com/zammad/zammad/issues/3817) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[bulk](https://github.com/zammad/zammad/labels/bulk)]
- `/assets/fonts/` changed to `/fonts/` [3892](https://github.com/zammad/zammad/issues/3892) [[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%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Search is not triggered/updated if url of search is updated new search item or new search is triggered via global search [3873](https://github.com/zammad/zammad/issues/3873) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Overview select fields are sorted by key [3869](https://github.com/zammad/zammad/issues/3869) [[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%20by%20payment)]
- Text rendering does not work for e-mails (no new lines) received in Zammad [3870](https://github.com/zammad/zammad/issues/3870) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Zammad 5 mail template double signature [3816](https://github.com/zammad/zammad/issues/3816) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%20by%20payment)]
- API creates empty tickets without articles if data is missing [2421](https://github.com/zammad/zammad/issues/2421) [[bug](https://github.com/zammad/zammad/labels/bug)] [[API](https://github.com/zammad/zammad/labels/API)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- 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%20by%20payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- 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%2FUI)] [[reporting](https://github.com/zammad/zammad/labels/reporting)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%2FUI)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend%20%2F%20JS%20app)]
- Date of datepicker is not localized [3866](https://github.com/zammad/zammad/issues/3866) [[bug](https://github.com/zammad/zammad/labels/bug)]
- 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%20%2F%20JS%20app)]
- 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%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[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%2FUI)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[integration](https://github.com/zammad/zammad/labels/integration)]
- "Is required" untranslatable [2709](https://github.com/zammad/zammad/issues/2709) [[translation](https://github.com/zammad/zammad/labels/translation)]
- Profile out of office toasters untranslatable [2666](https://github.com/zammad/zammad/issues/2666) [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- obsolete / double translations [2665](https://github.com/zammad/zammad/issues/2665) [[translation](https://github.com/zammad/zammad/labels/translation)]
- Missing translation for insufficient permissions for <object> [3275](https://github.com/zammad/zammad/issues/3275) [[translation](https://github.com/zammad/zammad/labels/translation)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- 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%20by%20payment)]
- 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%20by%20payment)]
- 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%2FUI)] [[escalation logic](https://github.com/zammad/zammad/labels/escalation%20logic)]
- Removing tags from tickets return HTTP 201 [3842](https://github.com/zammad/zammad/issues/3842) [[bug](https://github.com/zammad/zammad/labels/bug)] [[API](https://github.com/zammad/zammad/labels/API)]
- 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)]
- 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%20by%20payment)]
- 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%20workflows)]
- 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%20by%20payment)] [[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%20by%20payment)]
- Zammad database credentials are world-readable [3828](https://github.com/zammad/zammad/issues/3828) [[bug](https://github.com/zammad/zammad/labels/bug)]
- 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%20by%20payment)]
- 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%20logic)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%20by%20payment)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)] [[specification required](https://github.com/zammad/zammad/labels/specification%20required)]
- Not displayed fields should not impact the edit screen [3819](https://github.com/zammad/zammad/issues/3819) [[bug](https://github.com/zammad/zammad/labels/bug)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- 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%2FUI)]
- Default Priority on ticket creation not changeable [2852](https://github.com/zammad/zammad/issues/2852) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[:construction: refactoring :construction:](https://github.com/zammad/zammad/labels/%3Aconstruction%3A%20refactoring%20%3Aconstruction%3A)]
- 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%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- 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%20by%20payment)]
- 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)]
- [REVIEW] Fix/trigger variables missing [3225](https://github.com/zammad/zammad/pull/3225)
- Adding private keys allows adding certificates [3727](https://github.com/zammad/zammad/issues/3727) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Agent role permissions are ignored when there is only a single group [3437](https://github.com/zammad/zammad/issues/3437) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)]
- 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%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- 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)]
- 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%20workflows)]
- Job scheduling respects time zone [3802](https://github.com/zammad/zammad/issues/3802) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%20by%20payment)]
- 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)]
- OS package upgrade fails (activity_stream_object_id) [3797](https://github.com/zammad/zammad/issues/3797) [[bug](https://github.com/zammad/zammad/labels/bug)]
- 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%20%2F%20JS%20app)]
- 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)]
- 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)]
- 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%2FUI)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[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%2FUI)]
- 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%20by%20payment)]
- 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)]
- Usage of inactive object attributes in SLAs will crash admin SLA interface [3769](https://github.com/zammad/zammad/issues/3769) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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)]
- Broken dialog whiling uploading oversized attachment [3774](https://github.com/zammad/zammad/issues/3774) [[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%2FUI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- 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%20workflows)]
- 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%20%2F%20update)]
- 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%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- 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%20%2F%20update)]
- Fix postinstall.sh getting es_url [3775](https://github.com/zammad/zammad/pull/3775)
- 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%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- [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%20%2F%20update)]
- 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%2FUI)]
- 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%20by%20payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)] [[specification required](https://github.com/zammad/zammad/labels/specification%20required)] [[theming / skinning](https://github.com/zammad/zammad/labels/theming%20%2F%20skinning)]
- 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%2FUI)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Fix polish translations [3760](https://github.com/zammad/zammad/pull/3760)
- 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%20workflows)]
- 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%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]

25
Gemfile
View file

@ -1,9 +1,9 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
source 'https://gems.sutty.nl'
# core - base
ruby '2.7.5'
ruby '2.7.3'
gem 'rails', '~> 6.0.0'
# core - rails additions
@ -94,9 +94,6 @@ gem 'omniauth-saml'
gem 'omniauth-twitter'
gem 'omniauth-weibo-oauth2'
# Rate limiting
gem 'rack-attack'
# channels
gem 'gmail_xoauth'
gem 'koala'
@ -152,17 +149,14 @@ gem 'viewpoint', require: false
# integrations - S/MIME
gem 'openssl'
gem 'lograge'
# Translation sync
gem 'PoParser', require: false
# Gems used only for develop/test and not required
# in production environments by default.
group :development, :test do
# app boottime improvement
gem 'spring'
gem 'spring-commands-rspec'
gem 'spring-commands-testunit'
# debugging
gem 'byebug'
@ -174,13 +168,17 @@ group :development, :test do
# test frameworks
gem 'rails-controller-testing'
gem 'rspec-rails'
gem 'rspec-retry'
gem 'shoulda-matchers'
gem 'test-unit'
# for testing Pundit authorisation policies in RSpec
gem 'pundit-matchers'
# code coverage
gem 'coveralls', require: false
gem 'simplecov'
gem 'simplecov-rcov'
# UI tests w/ Selenium
gem 'capybara'
gem 'selenium-webdriver'
@ -205,6 +203,9 @@ group :development, :test do
gem 'rubocop-rails'
gem 'rubocop-rspec'
# changelog generation
gem 'github_changelog_generator'
# generate random test data
gem 'factory_bot_rails'
gem 'faker'
@ -235,5 +236,5 @@ end
# without having your changes overwritten during upgrades.)
# ZAMMAD DEVS: Consult the internal wiki
# (or else risk pushing unwanted changes to Gemfile.lock!)
# https://git.zammad.com/zammad/zammad/wikis/Tips#user-content-customizing-the-gemfile
# https://git.znuny.com/zammad/zammad/wikis/Tips#user-content-customizing-the-gemfile
eval_gemfile 'Gemfile.local' if File.exist?('Gemfile.local')

View file

@ -19,70 +19,68 @@ GIT
GEM
remote: https://gems.sutty.nl/
specs:
PoParser (3.2.6)
simple_po_parser (~> 1.1.6)
aasm (5.2.0)
concurrent-ruby (~> 1.0)
actioncable (6.0.4.8)
actionpack (= 6.0.4.8)
actioncable (6.0.4.1)
actionpack (= 6.0.4.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.0.4.8)
actionpack (= 6.0.4.8)
activejob (= 6.0.4.8)
activerecord (= 6.0.4.8)
activestorage (= 6.0.4.8)
activesupport (= 6.0.4.8)
actionmailbox (6.0.4.1)
actionpack (= 6.0.4.1)
activejob (= 6.0.4.1)
activerecord (= 6.0.4.1)
activestorage (= 6.0.4.1)
activesupport (= 6.0.4.1)
mail (>= 2.7.1)
actionmailer (6.0.4.8)
actionpack (= 6.0.4.8)
actionview (= 6.0.4.8)
activejob (= 6.0.4.8)
actionmailer (6.0.4.1)
actionpack (= 6.0.4.1)
actionview (= 6.0.4.1)
activejob (= 6.0.4.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.0.4.8)
actionview (= 6.0.4.8)
activesupport (= 6.0.4.8)
actionpack (6.0.4.1)
actionview (= 6.0.4.1)
activesupport (= 6.0.4.1)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.4.8)
actionpack (= 6.0.4.8)
activerecord (= 6.0.4.8)
activestorage (= 6.0.4.8)
activesupport (= 6.0.4.8)
actiontext (6.0.4.1)
actionpack (= 6.0.4.1)
activerecord (= 6.0.4.1)
activestorage (= 6.0.4.1)
activesupport (= 6.0.4.1)
nokogiri (>= 1.8.5)
actionview (6.0.4.8)
activesupport (= 6.0.4.8)
actionview (6.0.4.1)
activesupport (= 6.0.4.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.4.8)
activesupport (= 6.0.4.8)
activejob (6.0.4.1)
activesupport (= 6.0.4.1)
globalid (>= 0.3.6)
activemodel (6.0.4.8)
activesupport (= 6.0.4.8)
activerecord (6.0.4.8)
activemodel (= 6.0.4.8)
activesupport (= 6.0.4.8)
activerecord-import (1.3.0)
activerecord (>= 4.2)
activerecord-nulldb-adapter (0.8.0)
activerecord (>= 5.2.0, < 7.1)
activemodel (6.0.4.1)
activesupport (= 6.0.4.1)
activerecord (6.0.4.1)
activemodel (= 6.0.4.1)
activesupport (= 6.0.4.1)
activerecord-import (1.2.0)
activerecord (>= 3.2)
activerecord-nulldb-adapter (0.7.0)
activerecord (>= 5.2.0, < 6.3)
activerecord-session_store (2.0.0)
actionpack (>= 5.2.4.1)
activerecord (>= 5.2.4.1)
multi_json (~> 1.11, >= 1.11.2)
rack (>= 2.0.8, < 3)
railties (>= 5.2.4.1)
activestorage (6.0.4.8)
actionpack (= 6.0.4.8)
activejob (= 6.0.4.8)
activerecord (= 6.0.4.8)
activestorage (6.0.4.1)
actionpack (= 6.0.4.1)
activejob (= 6.0.4.1)
activerecord (= 6.0.4.1)
marcel (~> 1.0.0)
activesupport (6.0.4.8)
activesupport (6.0.4.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@ -95,37 +93,54 @@ GEM
argon2 (2.1.1)
ffi (~> 1.14)
ffi-compiler (~> 1.0)
argon2 (2.1.1-x86_64-linux-musl)
argon2 (2.0.3-x86_64-linux-musl)
ffi (~> 1.14)
ffi-compiler (~> 1.0)
ast (2.4.2)
autoprefixer-rails (10.4.2.0)
async (1.30.1)
console (~> 1.10)
nio4r (~> 2.3)
timers (~> 4.1)
async-http (0.56.5)
async (>= 1.25)
async-io (>= 1.28)
async-pool (>= 0.2)
protocol-http (~> 0.22.0)
protocol-http1 (~> 0.14.0)
protocol-http2 (~> 0.14.0)
async-http-faraday (0.11.0)
async-http (~> 0.42)
faraday
async-io (1.32.2)
async
async-pool (0.3.9)
async (>= 1.25)
autoprefixer-rails (10.3.3.0)
execjs (~> 2)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
biz (1.8.2)
clavius (~> 1.0)
tzinfo
bootsnap (1.11.1)
msgpack (~> 1.2)
bootsnap (1.11.1-x86_64-linux-musl)
msgpack (~> 1.2)
brakeman (5.2.1)
bootsnap (1.9.1)
msgpack (~> 1.0)
bootsnap (1.9.1-x86_64-linux-musl)
msgpack (~> 1.0)
brakeman (5.1.1)
browser (5.3.1)
buftok (0.2.0)
builder (3.2.4)
byebug (11.1.3)
byebug (11.1.3-x86_64-linux-musl)
capybara (3.36.0)
capybara (3.35.3)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
childprocess (4.1.0)
childprocess (3.0.0)
chunky_png (1.4.0)
clavius (1.0.4)
clearbit (0.3.3)
@ -144,24 +159,33 @@ GEM
json
composite_primary_keys (12.0.10)
activerecord (~> 6.0.0)
concurrent-ruby (1.1.10)
concurrent-ruby (1.1.9)
console (1.13.1)
fiber-local
coveralls (0.7.1)
multi_json (~> 1.3)
rest-client
simplecov (>= 0.7)
term-ansicolor
thor
crack (0.4.5)
rexml
crass (1.0.6)
csv (3.2.2)
csv (3.2.0)
daemons (1.4.1)
dalli (3.2.1)
dalli (2.7.11)
debug_inspector (1.1.0)
debug_inspector (1.1.0-x86_64-linux-musl)
delayed_job (4.1.10)
activesupport (>= 3.0, < 8.0)
delayed_job_active_record (4.1.7)
activerecord (>= 3.0, < 8.0)
delayed_job (4.1.9)
activesupport (>= 3.0, < 6.2)
delayed_job_active_record (4.1.6)
activerecord (>= 3.0, < 6.2)
delayed_job (>= 3.0, < 5)
deprecation_toolkit (1.5.1)
activesupport (>= 4.2)
diff-lcs (1.5.0)
diff-lcs (1.4.4)
diffy (3.4.0)
docile (1.4.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.5.4)
@ -172,54 +196,61 @@ GEM
eco-source
execjs
eco-source (1.1.0.rc.1)
em-websocket (0.5.3)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
http_parser.rb (~> 0.6.0)
equalizer (0.0.11)
erubi (1.10.0)
eventmachine (1.2.7)
eventmachine (1.2.7-x86_64-linux-musl)
execjs (2.8.1)
factory_bot (6.2.1)
factory_bot (6.2.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.2.0)
factory_bot (~> 6.2.0)
railties (>= 5.0.0)
faker (2.20.0)
i18n (>= 1.8.11, < 2)
faraday (1.10.0)
faker (2.19.0)
i18n (>= 1.6, < 2)
faraday (1.8.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-http-cache (2.2.0)
faraday (>= 0.8)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday_middleware (1.1.0)
faraday (~> 1.0)
ffi (1.15.5)
ffi (1.15.5-x86_64-linux-musl)
ffi (1.15.4-x86_64-linux-musl)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
formatador (1.1.0)
gli (2.21.0)
globalid (1.0.0)
fiber-local (1.0.0)
formatador (0.3.0)
github_changelog_generator (1.16.4)
activesupport
async (>= 1.25.0)
async-http-faraday
faraday-http-cache
multi_json
octokit (~> 4.6)
rainbow (>= 2.2.1)
rake (>= 10.0)
gli (2.20.1)
globalid (0.5.2)
activesupport (>= 5.0)
gmail_xoauth (0.4.2)
oauth (>= 0.3.6)
@ -242,7 +273,7 @@ GEM
guard
guard-compat (~> 1.1)
hashdiff (1.0.1)
hashie (5.0.0)
hashie (4.1.0)
hiredis (0.6.3)
hiredis (0.6.3-x86_64-linux-musl)
htmlentities (4.3.4)
@ -255,68 +286,58 @@ GEM
http-cookie (1.0.4)
domain_name (~> 0.5)
http-form_data (2.3.0)
http-parser (1.2.3)
ffi-compiler (>= 1.0, < 2.0)
http-parser (1.2.3-x86_64-linux-musl)
ffi-compiler (>= 1.0, < 2.0)
http_parser.rb (0.6.0)
http_parser.rb (0.6.0-x86_64-linux-musl)
httpclient (2.8.3)
i18n (1.10.0)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
icalendar (2.7.1)
ice_cube (~> 0.16)
icalendar-recurrence (1.1.3)
icalendar (~> 2.0)
ice_cube (~> 0.16)
ice_cube (0.16.4)
ice_cube (0.16.3)
inflection (1.0.0)
iniparse (1.5.0)
interception (0.5)
json (2.6.1)
json (2.6.1-x86_64-linux-musl)
json (2.5.1-x86_64-linux-musl)
jwt (2.3.0)
kgio (2.11.4)
kgio (2.11.4-x86_64-linux-musl)
koala (3.1.0)
koala (3.0.0)
addressable
faraday (< 2)
faraday
json (>= 1.8)
rexml
libv8 (8.4.255.0)
libv8 (8.4.255.0-x86_64-linux)
listen (3.7.1)
listen (3.7.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
little-plugger (1.1.4)
logging (2.3.0)
little-plugger (~> 1.1)
multi_json (~> 1.14)
lograge (0.12.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.16.0)
loofah (2.12.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lumberjack (1.2.8)
marcel (1.0.2)
matrix (0.4.2)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
messagebird-rest (3.0.0)
method_source (1.0.0)
mime-types (3.4.1)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
mini_mime (1.1.2)
mini_portile2 (2.8.0)
mime-types-data (3.2021.0901)
mini_mime (1.1.1)
mini_portile2 (2.6.1)
mini_racer (0.2.9)
libv8 (>= 6.9.411)
minitest (5.15.0)
msgpack (1.4.5)
msgpack (1.4.5-x86_64-linux-musl)
minitest (5.14.4)
msgpack (1.4.2)
msgpack (1.4.2-x86_64-linux-musl)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
@ -329,27 +350,30 @@ GEM
netrc (0.11.0)
nio4r (2.5.8)
nio4r (2.5.8-x86_64-linux-musl)
nokogiri (1.13.6)
mini_portile2 (~> 2.8.0)
nokogiri (1.12.5)
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
nokogiri (1.13.6-x86_64-linux-musl)
mini_portile2 (~> 2.8.0)
nokogiri (1.12.5-x86_64-linux-musl)
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
nori (2.6.0)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
oauth (0.5.8)
oauth2 (1.4.9)
faraday (>= 0.17.3, < 3.0)
oauth (0.5.6)
oauth2 (1.4.7)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-facebook (9.0.0)
omniauth-facebook (8.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.4.0)
omniauth (~> 1.5)
@ -370,7 +394,7 @@ GEM
omniauth-oauth (1.2.0)
oauth
omniauth (>= 1.0, < 3)
omniauth-oauth2 (1.7.2)
omniauth-oauth2 (1.7.1)
oauth2 (~> 1.4)
omniauth (>= 1.9, < 3)
omniauth-rails_csrf_protection (0.1.2)
@ -385,18 +409,25 @@ GEM
omniauth-weibo-oauth2 (0.5.2)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0)
openssl (3.0.0)
openssl (3.0.0-x86_64-linux-musl)
openssl (2.2.0)
openssl (2.2.0-x86_64-linux-musl)
overcommit (0.58.0)
childprocess (>= 0.6.3, < 5)
iniparse (~> 1.4)
rexml (~> 3.2)
parallel (1.21.0)
parser (3.1.1.0)
parser (3.0.2.0)
ast (~> 2.4.1)
pg (0.21.0)
pg (0.21.0-x86_64-linux-musl)
power_assert (2.0.1)
protocol-hpack (1.4.2)
protocol-http (0.22.5)
protocol-http1 (0.14.2)
protocol-http (~> 0.22)
protocol-http2 (0.14.2)
protocol-hpack (~> 1.4)
protocol-http (~> 0.18)
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
@ -412,37 +443,35 @@ GEM
binding_of_caller (~> 1.0)
pry (~> 0.13)
public_suffix (4.0.6)
puma (4.3.12)
puma (4.3.10)
nio4r (~> 2.0)
puma (4.3.12-x86_64-linux-musl)
puma (4.3.8-x86_64-linux-musl)
nio4r (~> 2.0)
pundit (2.2.0)
pundit (2.1.1)
activesupport (>= 3.0.0)
pundit-matchers (1.7.0)
rspec-rails (>= 3.0.0)
racc (1.6.0)
racc (1.6.0-x86_64-linux-musl)
rack (2.2.3.1)
rack-attack (6.6.0)
rack (>= 1.0, < 3)
racc (1.5.2)
racc (1.5.2-x86_64-linux-musl)
rack (2.2.3)
rack-livereload (0.3.17)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (6.0.4.8)
actioncable (= 6.0.4.8)
actionmailbox (= 6.0.4.8)
actionmailer (= 6.0.4.8)
actionpack (= 6.0.4.8)
actiontext (= 6.0.4.8)
actionview (= 6.0.4.8)
activejob (= 6.0.4.8)
activemodel (= 6.0.4.8)
activerecord (= 6.0.4.8)
activestorage (= 6.0.4.8)
activesupport (= 6.0.4.8)
rails (6.0.4.1)
actioncable (= 6.0.4.1)
actionmailbox (= 6.0.4.1)
actionmailer (= 6.0.4.1)
actionpack (= 6.0.4.1)
actiontext (= 6.0.4.1)
actionview (= 6.0.4.1)
activejob (= 6.0.4.1)
activemodel (= 6.0.4.1)
activerecord (= 6.0.4.1)
activestorage (= 6.0.4.1)
activesupport (= 6.0.4.1)
bundler (>= 1.3.0)
railties (= 6.0.4.8)
railties (= 6.0.4.1)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@ -453,39 +482,37 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.2)
loofah (~> 2.3)
railties (6.0.4.8)
actionpack (= 6.0.4.8)
activesupport (= 6.0.4.8)
railties (6.0.4.1)
actionpack (= 6.0.4.1)
activesupport (= 6.0.4.1)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.1.1)
raindrops (0.20.0)
raindrops (0.20.0-x86_64-linux-musl)
rainbow (3.0.0)
raindrops (0.19.2)
raindrops (0.19.2-x86_64-linux-musl)
rake (13.0.6)
rb-fsevent (0.11.1)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
rchardet (1.8.0)
redis (4.6.0)
regexp_parser (2.2.1)
request_store (1.5.1)
rack (>= 1.4)
redis (4.4.0)
regexp_parser (2.1.1)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rexml (3.2.5)
rspec-core (3.11.0)
rspec-support (~> 3.11.0)
rspec-expectations (3.11.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.11.0)
rspec-mocks (3.11.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.11.0)
rspec-rails (5.1.1)
rspec-support (~> 3.10.0)
rspec-rails (5.0.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
railties (>= 5.2)
@ -493,22 +520,19 @@ GEM
rspec-expectations (~> 3.10)
rspec-mocks (~> 3.10)
rspec-support (~> 3.10)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.11.0)
rszr (0.5.2)
rspec-support (3.10.2)
rszr (0.5.2-x86_64-linux-musl)
rubocop (1.26.0)
rubocop (1.22.1)
parallel (~> 1.10)
parser (>= 3.1.0.0)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.16.0, < 2.0)
rubocop-ast (>= 1.12.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.16.0)
parser (>= 3.1.1.0)
rubocop-ast (1.12.0)
parser (>= 3.0.1.1)
rubocop-faker (1.1.0)
faker (>= 2.12.0)
rubocop (>= 0.82.0)
@ -516,17 +540,17 @@ GEM
activesupport
rubocop
rubocop-rspec
rubocop-performance (1.13.3)
rubocop-performance (1.11.5)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.13.2)
rubocop-rails (2.12.3)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.7.0, < 2.0)
rubocop-rspec (2.9.0)
rubocop-rspec (2.5.0)
rubocop (~> 1.19)
ruby-progressbar (1.11.0)
ruby-saml (1.14.0)
ruby-saml (1.13.0)
nokogiri (>= 1.10.5)
rexml
ruby2_keywords (0.0.5)
@ -542,41 +566,60 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.1.0)
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
shellany (0.0.1)
shoulda-matchers (5.1.0)
shoulda-matchers (5.0.0)
activesupport (>= 5.2.0)
simple_oauth (0.3.1)
simple_po_parser (1.1.6)
simplecov (0.21.2)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov-rcov (0.2.3)
simplecov (>= 0.4.1)
simplecov_json_formatter (0.1.3)
slack-notifier (2.4.0)
slack-ruby-client (1.0.0)
slack-ruby-client (0.17.0)
faraday (>= 1.0)
faraday_middleware
gli
hashie
websocket-driver
slop (3.6.0)
spring (4.0.0)
spring (3.0.0)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
spring-commands-testunit (1.0.1)
spring (>= 0.9.1)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets-rails (3.2.2)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sync (0.5.0)
tcr (0.2.2)
telegramAPI (1.4.2)
rest-client (~> 2.0, >= 2.0.2)
telephone_number (1.4.14)
test-unit (3.5.3)
telephone_number (1.4.12)
term-ansicolor (1.7.1)
tins (~> 1.0)
test-unit (3.4.7)
power_assert
thor (1.2.1)
thor (1.1.0)
thread_safe (0.3.6)
tilt (2.0.10)
twilio-ruby (5.65.1)
timers (4.3.3)
tins (1.29.1)
sync
twilio-ruby (5.59.0)
faraday (>= 0.9, < 2.0)
jwt (>= 1.5, <= 2.5)
nokogiri (>= 1.6, < 2.0)
@ -600,16 +643,16 @@ GEM
unf_ext (0.0.8)
unf_ext (0.0.8-x86_64-linux-musl)
unicode-display_width (2.1.0)
unicorn (6.1.0)
unicorn (6.0.0)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn (6.1.0-x86_64-linux-musl)
unicorn (6.0.0-x86_64-linux-musl)
kgio (~> 2.6)
raindrops (~> 0.7)
valid_email2 (4.0.3)
valid_email2 (4.0.0)
activemodel (>= 3.2)
mail (~> 2.5)
vcr (6.1.0)
vcr (6.0.0)
viewpoint (1.1.1)
httpclient
logging
@ -627,10 +670,10 @@ GEM
writeexcel (1.0.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.5.4)
zendesk_api (1.35.0)
zeitwerk (2.4.2)
zendesk_api (1.33.0)
faraday (>= 0.9.0, < 2.0.0)
hashie (>= 3.5.2, < 6.0.0)
hashie (>= 3.5.2, < 5.0.0)
inflection
mini_mime
multipart-post (~> 2.0)
@ -640,7 +683,6 @@ PLATFORMS
x86_64-linux-musl
DEPENDENCIES
PoParser
aasm
activerecord-import
activerecord-nulldb-adapter
@ -660,6 +702,7 @@ DEPENDENCIES
coffee-rails
coffeelint
composite_primary_keys
coveralls
csv
daemons
dalli
@ -674,6 +717,7 @@ DEPENDENCIES
execjs
factory_bot_rails
faker
github_changelog_generator
gmail_xoauth
guard
guard-livereload
@ -685,7 +729,6 @@ DEPENDENCIES
json
koala
libv8
lograge
mail!
messagebird-rest
mime-types
@ -713,7 +756,6 @@ DEPENDENCIES
puma (~> 4)
pundit
pundit-matchers
rack-attack
rack-livereload
rails (~> 6.0.0)
rails-controller-testing
@ -721,7 +763,6 @@ DEPENDENCIES
rchardet (>= 1.8.0)
redis
rspec-rails
rspec-retry
rszr (= 0.5.2)
rubocop
rubocop-faker
@ -732,9 +773,13 @@ DEPENDENCIES
sassc-rails
selenium-webdriver
shoulda-matchers
simplecov
simplecov-rcov
slack-notifier
slack-ruby-client
spring
spring-commands-rspec
spring-commands-testunit
sprockets (~> 3.7.2)
tcr
telegramAPI
@ -752,7 +797,7 @@ DEPENDENCIES
zendesk_api
RUBY VERSION
ruby 2.7.5p203
ruby 2.7.3p183
BUNDLED WITH
2.2.20
2.2.27

View file

@ -1,4 +1,4 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
# A sample Guardfile
# More info at https://github.com/guard/guard#readme

View file

@ -1,5 +1,5 @@
#!/usr/bin/env rake
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

View file

@ -1,3 +1,3 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
App.Config.set('api_path', 'api/v1')
App.Config.set('image_path', '/assets/images')

View file

@ -77,7 +77,8 @@ class App.Controller extends Spine.Controller
# release bindings
if @el
@el.off()
@el.undelegate()
@el.unbind()
@el.empty()
# release spine bindings (see release() of spine.coffee)
@ -113,7 +114,7 @@ class App.Controller extends Spine.Controller
if window.clipboardData # IE
window.clipboardData.setData('Text', text)
else
window.prompt(__('Copy to clipboard: Ctrl+C, Enter'), text)
window.prompt('Copy to clipboard: Ctrl+C, Enter', text)
# disable all delay's and interval's
disconnectClient: ->
@ -219,7 +220,7 @@ class App.Controller extends Spine.Controller
userInfo: (data) ->
el = data.el || $('[data-id="customer_info"]')
el.off()
el.unbind()
# start customer info controller
new App.WidgetUser(
@ -299,17 +300,15 @@ class App.Controller extends Spine.Controller
frontendTimeUpdateItem: (item, currentVal) =>
timestamp = item.attr('datetime')
return if timestamp is 'null'
time = @humanTime(timestamp, item.hasClass('escalation'))
# only do dom updates on changes
time = @humanTime(timestamp, item.hasClass('escalation'))
return if time is currentVal
newTitle = App.i18n.translateTimestamp(timestamp)
if item.attr('timezone')
newTitle += ' ' + item.attr('timezone')
if !item.hasClass('noTitle')
item.attr('title', newTitle)
item.html(time)

View file

@ -59,9 +59,7 @@ class App.ControllerModal extends App.Controller
false
content: ->
# coffeelint: disable=detect_translatable_string
"You need to implement a '@content()' method!"
# coffeelint: enable=detect_translatable_string
'You need to implement a one @content()!'
update: =>
if @message
@ -108,7 +106,7 @@ class App.ControllerModal extends App.Controller
if @buttonSubmit is true
@buttonSubmit = 'Submit'
if @buttonCancel is true
@buttonCancel = __('Cancel & Go Back')
@buttonCancel = 'Cancel & Go Back'
@update()
@ -181,7 +179,7 @@ class App.ControllerModal extends App.Controller
form = @el
# focus first input, select or textarea
form.find('input:not([disabled]):not([type="hidden"]):not(".btn"), select:not([disabled]), textarea:not([disabled])').first().trigger('focus')
form.find('input:not([disabled]):not([type="hidden"]):not(".btn"), select:not([disabled]), textarea:not([disabled])').first().focus()
@initalFormParams = @formParams()

View file

@ -1,15 +0,0 @@
class App.ControllerConfirm extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: __('Yes')
buttonClass: 'btn--danger'
head: __('Confirmation')
small: true
content: ->
App.i18n.translateContent(@message)
onSubmit: =>
@close()
if @callback
@callback()

View file

@ -1,3 +0,0 @@
class App.ControllerArticlePublicConfirm extends App.ControllerConfirm
head: __('Publish Article')
message: __('Do you really want to set the visibility of this article to "public"?')

View file

@ -1,5 +1,5 @@
class App.ControllerForm extends App.Controller
fullFormSubmitLabel: __('Submit')
fullFormSubmitLabel: 'Submit'
fullFormSubmitAdditionalClasses: ''
fullFormButtonsContainerClass: ''
fullFormAdditionalButtons: [] # [{className: 'js-class', text: 'Label'}]
@ -34,8 +34,11 @@ class App.ControllerForm extends App.Controller
@form.prepend('<div class="alert alert--danger js-danger js-alert hide" role="alert"></div>')
@form.prepend('<div class="alert alert--success js-success hide" role="alert"></div>')
# Fix for Issue #2510 - Zammad Customers shown as Agents in IE
# Previously the handlers are called directly, before the DOM elements are ready, thereby causing a race condition under IE11.
# Now we only dispatch the handlers after the DOM is ready.
if @handlers.length
@dispatchHandlers()
$(@dispatchHandlers)
# if element is given, prepend form to it
if @el
@ -157,7 +160,7 @@ class App.ControllerForm extends App.Controller
for eventSelector, callback of @events
do (eventSelector, callback) ->
evs = eventSelector.split(' ')
fieldset.find(evs[1]).on(evs[0], (e) -> callback(e))
fieldset.find(evs[1]).bind(evs[0], (e) -> callback(e))
# bind tool tips
fieldset.find('.js-helpMessage').tooltip()
@ -170,7 +173,7 @@ class App.ControllerForm extends App.Controller
# input text field with max. 100 size
attribute_config = {
name: 'subject'
display: __('Subject')
display: 'Subject'
tag: 'input'
type: 'text'
limit: 100
@ -182,7 +185,7 @@ class App.ControllerForm extends App.Controller
# colection as relation with auto completion
attribute_config = {
name: 'customer_id'
display: __('Customer')
display: 'Customer'
tag: 'autocompletion'
# auto completion params, endpoints, ui,...
type: 'text'
@ -190,7 +193,7 @@ class App.ControllerForm extends App.Controller
null: false
relation: 'User'
autocapitalize: false
help: __('Select the customer of the ticket or create one.')
help: 'Select the customer of the ticket or create one.'
helpLink: '<a href="" class="customer_new">&raquo;</a>'
callback: @userInfo
class: 'span7'
@ -199,7 +202,7 @@ class App.ControllerForm extends App.Controller
# colection as relation
attribute_config = {
name: 'priority_id'
display: __('Priority')
display: 'Priority'
tag: 'select'
multiple: false
null: false
@ -213,7 +216,7 @@ class App.ControllerForm extends App.Controller
# colection as options
attribute_config = {
name: 'priority_id'
display: __('Priority')
display: 'Priority'
tag: 'select'
multiple: false
null: false
@ -275,7 +278,7 @@ class App.ControllerForm extends App.Controller
attribute.autocomplete = 'autocomplete="' + attribute.autocomplete + '"'
# set default values
if attribute.value is undefined && 'default' of attribute && !@params?.id
if attribute.value is undefined && 'default' of attribute
attribute.value = attribute.default
# set params value
@ -313,7 +316,7 @@ class App.ControllerForm extends App.Controller
item_bind = item.find('.richtext-content')
item_event = 'blur'
item_bind.on(item_event, (e) =>
item_bind.bind(item_event, (e) =>
@lastChangedAttribute = attribute.name
params = App.ControllerForm.params(@form)
for handler in @handlers
@ -415,11 +418,11 @@ class App.ControllerForm extends App.Controller
if !@constructor.fieldIsMandatory(field_by_name)
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')
if !@constructor.fieldIsMandatory(field_by_data)
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')
optional: (name, el = @form) ->
@ -431,11 +434,11 @@ class App.ControllerForm extends App.Controller
if @constructor.fieldIsMandatory(field_by_name)
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')
if @constructor.fieldIsMandatory(field_by_data)
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')
readonly: (name, el = @form) ->
@ -527,9 +530,6 @@ class App.ControllerForm extends App.Controller
param[item.name] = [param[item.name], value]
else
param[item.name].push value
else
if item.multiselect && typeof value is 'string'
param[item.name] = new Array(value)
else
param[item.name] = value
@ -784,7 +784,7 @@ class App.ControllerForm extends App.Controller
# set autofocus by delay to make validation testable
App.Delay.set(
->
lookupForm.find('.has-error').find('input, textarea, select').first().trigger('focus')
lookupForm.find('.has-error').find('input, textarea, select').first().focus()
200
'validate'
)

View file

@ -1,8 +1,8 @@
class App.ControllerGenericDescription extends App.ControllerModal
buttonClose: true
buttonCancel: false
buttonSubmit: __('Close')
head: __('Description')
buttonSubmit: 'Close'
head: 'Description'
content: =>
marked(App.i18n.translateContent(@description))

View file

@ -1,13 +1,13 @@
class App.ControllerGenericDestroyConfirm extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: __('delete')
buttonSubmit: 'delete'
buttonClass: 'btn--danger'
head: __('Confirmation')
head: 'Confirm'
small: true
content: ->
App.i18n.translateContent('Do you really want to delete this object?')
App.i18n.translateContent('Sure to delete this object?')
onSubmit: =>
options = @options || {}
@ -19,3 +19,19 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal
@log 'errors'
@showAlert(data.human_error || data.error)
@item.destroy(options)
class App.ControllerConfirm extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: 'yes'
buttonClass: 'btn--danger'
head: 'Confirm'
small: true
content: ->
App.i18n.translateContent(@message)
onSubmit: =>
@close()
if @callback
@callback()

View file

@ -51,5 +51,5 @@ class App.ControllerGenericEdit extends App.ControllerModal
App[ ui.genericObject ].fetch(id: @id)
ui.log 'errors'
ui.formEnable(e)
ui.controller.showAlert(details.error_human || details.error || __('The object could not be updated.'))
ui.controller.showAlert(details.error_human || details.error || 'Unable to update object!')
)

View file

@ -1,9 +1,9 @@
class App.ControllerErrorModal extends App.ControllerModal
buttonClose: true
buttonCancel: false
buttonSubmit: __('Close')
buttonSubmit: 'Close'
#buttonClass: 'btn--danger'
head: __('Error')
head: 'Error'
#small: true
#shown: true
showTrySupport: true

View file

@ -5,7 +5,7 @@ class App.GenericHistory extends App.ControllerModal
buttonClose: true
buttonCancel: false
buttonSubmit: false
head: __('History')
head: 'History'
shown: false
constructor: ->
@ -18,7 +18,7 @@ class App.GenericHistory extends App.ControllerModal
content = $ App.view('generic/history')(
items: localItem
)
content.find('a[data-type="sortorder"]').on('click', (e) =>
content.find('a[data-type="sortorder"]').bind('click', (e) =>
e.preventDefault()
@sortorder()
)
@ -44,8 +44,6 @@ class App.GenericHistory extends App.ControllerModal
if item.object is 'Ticket::Article'
item.object = 'Article'
if item.object is 'Ticket::SharedDraftZoom'
item.object = 'Draft'
data = item
data.created_by = App.User.find( item.created_by_id )
@ -100,7 +98,7 @@ class App.GenericHistory extends App.ControllerModal
content += " '#{ @translateItemValue(item, item.value_from) }'"
if item.value_to
if item.value_from || item.object is 'Mention'
if item.value_from
content += ' &rarr;'
content += " '#{ @translateItemValue(item, item.value_to) }'"
else if item.value_from
@ -114,14 +112,6 @@ class App.GenericHistory extends App.ControllerModal
newItems
translateItemValue: ({object, attribute}, value) ->
if object is 'Mention'
result = '-'
if value
user = App.User.find(value)
if user
result = user.displayName()
return result
localAttribute = @objectAttribute(object, attribute)
if localAttribute && localAttribute.tag is 'datetime'
return App.i18n.translateTimestamp(value)

View file

@ -51,5 +51,5 @@ class App.ControllerGenericNew extends App.ControllerModal
fail: (settings, details) ->
ui.log 'errors', details
ui.formEnable(e)
ui.controller.showAlert(details.error_human || details.error || __('The object could not be created.'))
ui.controller.showAlert(details.error_human || details.error || 'Unable to create object!')
)

View file

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

View file

@ -1,5 +1,5 @@
class App.ControllerReorderModal extends App.ControllerModal
head: __('Drag to reorder')
head: 'Drag to reorder'
content: ->
view = $(App.view('reorder_modal')())
@ -10,7 +10,7 @@ class App.ControllerReorderModal extends App.ControllerModal
true
overview: ['title']
attribute_list: [
{ name: 'title', display: __('Name') }
{ name: 'title', display: 'Name' }
]
objects: @items
)
@ -21,7 +21,7 @@ class App.ControllerReorderModal extends App.ControllerModal
onShown: ->
super
@$('.js-submit').trigger('focus')
@$('.js-submit').focus()
save: ->
ids = @$('tr.item').toArray().map (el) -> parseInt(el.dataset.id)
@ -49,3 +49,4 @@ class App.ControllerReorderModal extends App.ControllerModal
onSubmit: ->
super
@save()

View file

@ -406,7 +406,7 @@ class App.ControllerTable extends App.Controller
if @bindCheckbox.events
for event, callback of @bindCheckbox.events
do (table, event, callback) ->
table.on(event, 'input[name="bulk"]', (e) ->
table.delegate('input[name="bulk"]', event, (e) ->
e.stopPropagation()
id = $(e.currentTarget).parents('tr').data('id')
checked = $(e.currentTarget).prop('checked')
@ -424,12 +424,12 @@ class App.ControllerTable extends App.Controller
if @checkbox
# click first tr>td, catch click
table.on('click', 'tr > td:nth-child(1)', (e) ->
table.delegate('tr > td:nth-child(1)', 'click', (e) ->
e.stopPropagation()
)
# bind on full bulk click
table.on('change', 'input[name="bulk_all"]', (e) =>
table.delegate('input[name="bulk_all"]', 'change', (e) =>
e.stopPropagation()
clicks = []
if $(e.currentTarget).prop('checked')
@ -493,6 +493,16 @@ class App.ControllerTable extends App.Controller
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) ->
sorted = Object.keys(objects).sort()
@ -515,7 +525,7 @@ class App.ControllerTable extends App.Controller
objectsToShow = @objectsOfPage(@pagerShownPage)
if @groupBy
# 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
objectsGrouped = { '': objectsToShow }
@ -631,7 +641,7 @@ class App.ControllerTable extends App.Controller
if @clone
@actions.push
name: 'clone'
display: __('Clone')
display: 'Clone'
icon: 'clipboard'
class: 'create js-clone'
callback: (id) =>
@ -650,7 +660,7 @@ class App.ControllerTable extends App.Controller
if @destroy
@actions.push
name: 'delete'
display: __('Delete')
display: 'Delete'
icon: 'trash'
class: 'danger js-delete'
callback: (id) =>
@ -662,7 +672,7 @@ class App.ControllerTable extends App.Controller
if @actions.length
@headers.push
name: 'action'
display: __('Action')
display: 'Action'
width: '50px'
displayWidth: 50
align: 'right'
@ -855,15 +865,11 @@ class App.ControllerTable extends App.Controller
@objects = localObjects
@lastSortedobjects = localObjects
groupObjectName: (object, key = undefined, options = {}) ->
groupObjectName: (object, key = undefined) ->
group = object
if key
if key not of object
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)
if _.isEmpty(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

@ -20,7 +20,7 @@ class App.ControllerWizardModal extends App.ControllerFullPage
@hideAlert(name)
@$('.setup.wizard').addClass('hide')
@$(".setup.wizard.#{name}").removeClass('hide')
@$(".setup.wizard.#{name} input, .setup.wizard.#{name} select").first().trigger('focus')
@$(".setup.wizard.#{name} input, .setup.wizard.#{name} select").first().focus()
showAlert: (screen, message) =>
@$(".#{screen}").find('.alert').first().removeClass('hide').text(App.i18n.translatePlain(message))

View file

@ -11,7 +11,7 @@ class App.ChannelEmailFilter extends App.Controller
template = $( '<div><div class="overview"></div><a data-type="new" class="btn btn--success">' + App.i18n.translateContent('New') + '</a></div>' )
description = __('With filters you can e. g. dispatch new tickets into certain groups or set a certain priority for tickets of a VIP customer.')
description = 'With filters you can e. g. dispatch new tickets into certain groups or set a certain priority for tickets of a VIP customer.'
new App.ControllerTable(
el: template.find('.overview')
@ -28,7 +28,7 @@ class App.ChannelEmailFilter extends App.Controller
e.preventDefault()
new App.ControllerGenericNew(
pageData:
object: __('Postmaster Filter')
object: 'Postmaster Filter'
genericObject: 'PostmasterFilter'
container: @el.closest('.content')
callback: @load
@ -40,7 +40,7 @@ class App.ChannelEmailFilter extends App.Controller
new App.ControllerGenericEdit(
id: id,
pageData:
object: __('Postmaster Filter')
object: 'Postmaster Filter'
genericObject: 'PostmasterFilter'
container: @el.closest('.content')
callback: @load

View file

@ -11,11 +11,11 @@ class App.ChannelEmailSignature extends App.Controller
template = $( '<div><div class="overview"></div><a data-type="new" class="btn btn--success">' + App.i18n.translateContent('New') + '</a></div>' )
description = __('''
You can define different signatures for each group, which allows you to use a different signature for every department.
description = '''
You can define different signatures for each group. So you can have different email signatures for different departments.
Once you have created a signature here, you will also need to edit the groups where you want to use it.
''')
Once you have created a signature here, you need also to edit the groups where you want to use it.
'''
new App.ControllerTable(
el: template.find('.overview')
@ -46,7 +46,7 @@ class ChannelEmailSignatureEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
head: __('Signature')
head: 'Signature'
content: =>
if @object
@ -90,5 +90,5 @@ class ChannelEmailSignatureEdit extends App.ControllerModal
fail: (settings, details) =>
@log 'errors', details
@formEnable(e)
@form.showAlert(details.error_human || details.error || __('The object could not be created.'))
@form.showAlert(details.error_human || details.error || 'Unable to create object!')
)

View file

@ -1,6 +1,6 @@
class ChannelChat extends App.ControllerSubContent
requiredPermission: 'admin.channel_chat'
header: __('Chat')
header: 'Chat'
events:
'change .js-params': 'updateParams'
'input .js-params': 'updateParams'
@ -32,74 +32,74 @@ class ChannelChat extends App.ControllerSubContent
name: 'chatId'
default: '1'
type: 'Number'
description: __('Identifier of the chat topic.')
description: 'Identifier of the chat-topic.'
}
{
name: 'show'
default: true
type: 'Boolean'
description: __('Show the chat when ready.')
description: 'Show the chat when ready.'
}
{
name: 'target'
default: "$('body')"
type: 'jQuery Object'
description: __('Where to append the chat to.')
description: 'Where to append the chat to.'
}
{
name: 'host'
default: '(Empty)'
type: 'String'
description: __("If left empty, the host gets auto-detected - in this case %s. The auto-detection reads out the host from the <script> tag. If you don't include it via a <script> tag you need to specify the host.")
description: "If left empty, the host gets auto-detected - in this case %s. The auto-detection reads out the host from the <script> tag. If you don't include it via a <script> tag you need to specify the host."
descriptionSubstitute: window.location.origin
}
{
name: 'debug'
default: false
type: 'Boolean'
description: __('Enables console logging.')
description: 'Enables console logging.'
}
{
name: 'title'
default: "'<strong>Chat</strong> with us!'"
type: 'String'
description: __('Welcome Title shown on the closed chat. Can contain HTML.')
description: 'Welcome Title shown on the closed chat. Can contain HTML.'
}
{
name: 'fontSize'
default: 'undefined'
type: 'String'
description: __('CSS font-size with a unit like 12px, 1.5em. If left undefined it inherits the font-size of the website.')
description: 'CSS font-size with a unit like 12px, 1.5em. If left to undefined it inherits the font-size of the website.'
}
{
name: 'flat'
default: 'false'
type: 'Boolean'
description: __('Removes the shadows for a flat look.')
description: 'Removes the shadows for a flat look.'
}
{
name: 'buttonClass'
default: "'open-zammad-chat'"
type: 'String'
description: __('Add this class to a button on your page that should open the chat.')
description: 'Add this class to a button on your page that should open the chat.'
}
{
name: 'inactiveClass'
default: "'is-inactive'"
type: 'String'
description: __('This class gets added to the button on initialization and will be removed once the chat connection is established.')
description: 'This class gets added to the button on initialization and gets removed once the chat connection got established.'
}
{
name: 'cssAutoload'
default: 'true'
type: 'Boolean'
description: __('Automatically loads the chat.css file. If you want to use your own css, just set it to false.')
description: 'Automatically loads the chat.css file. If you want to use your own css, just set it to false.'
}
{
name: 'cssUrl'
default: 'undefined'
type: 'String'
description: __('Location of an external chat.css file.')
description: 'Location of an external chat.css file.'
}
]
@ -204,7 +204,7 @@ class ChannelChat extends App.ControllerSubContent
onUrlSubmit: (event) ->
event.preventDefault() if event
@urlInput.trigger('focus')
@urlInput.focus()
@changeDemoWebsite()
changeDemoWebsite: ->
@ -353,7 +353,7 @@ class ChannelChat extends App.ControllerSubContent
@code.each (i, block) ->
hljs.highlightBlock block
App.Config.set('Chat', { prio: 4000, name: __('Chat'), parent: '#channels', target: '#channels/chat', controller: ChannelChat, permission: ['admin.channel_chat'] }, 'NavBarAdmin')
App.Config.set('Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: ChannelChat, permission: ['admin.channel_chat'] }, 'NavBarAdmin')
class Topics extends App.Controller
events:
@ -373,9 +373,9 @@ class Topics extends App.Controller
new: (e) =>
new App.ControllerGenericNew(
pageData:
title: __('Chats')
object: __('Chat')
objects: __('Chats')
title: 'Chats'
object: 'Chat'
objects: 'Chats'
genericObject: 'Chat'
callback: @render
container: @el.closest('.content')
@ -389,7 +389,7 @@ class Topics extends App.Controller
id: id
genericObject: 'Chat'
pageData:
object: __('Chat')
object: 'Chat'
container: @el.closest('.content')
callback: @render
)

View file

@ -1,29 +1,29 @@
class ChannelEmail extends App.ControllerTabs
requiredPermission: 'admin.channel_email'
header: __('Email')
header: 'Email'
constructor: ->
super
@title __('Email'), true
@title 'Email', true
@tabs = [
{
name: __('Accounts'),
name: 'Accounts',
target: 'c-account',
controller: ChannelEmailAccountOverview,
},
{
name: __('Filter'),
name: 'Filter',
target: 'c-filter',
controller: App.ChannelEmailFilter,
},
{
name: __('Signatures'),
name: 'Signatures',
target: 'c-signature',
controller: App.ChannelEmailSignature,
},
{
name: __('Settings'),
name: 'Settings',
target: 'c-setting',
controller: App.SettingsArea,
params: { area: 'Email::Base' },
@ -142,7 +142,7 @@ class ChannelEmailAccountOverview extends App.Controller
e.preventDefault()
id = $(e.target).closest('.action').data('id')
new App.ControllerConfirm(
message: __('Are you sure?')
message: 'Sure?'
callback: =>
@ajax(
id: 'email_delete'
@ -197,7 +197,7 @@ class ChannelEmailAccountOverview extends App.Controller
channel_id = $(e.target).closest('.action').data('id')
new App.ControllerGenericNew(
pageData:
object: __('Email Address')
object: 'Email Address'
genericObject: 'EmailAddress'
container: @el.closest('.content')
item:
@ -210,7 +210,7 @@ class ChannelEmailAccountOverview extends App.Controller
id = $(e.target).closest('li').data('id')
new App.ControllerGenericEdit(
pageData:
object: __('Email Address')
object: 'Email Address'
genericObject: 'EmailAddress'
container: @el.closest('.content')
id: id
@ -254,11 +254,11 @@ class ChannelEmailEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
head: __('Channel')
head: 'Channel'
content: =>
configureAttributesBase = [
{ name: 'group_id', display: __('Destination Group'), tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
{ name: 'group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
]
@form = new App.ControllerForm(
model:
@ -298,7 +298,7 @@ class ChannelEmailEdit extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('The changes could not be saved.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
)
class ChannelEmailAccountWizard extends App.ControllerWizardModal
@ -307,7 +307,6 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
events:
'submit .js-intro': 'probeBasedOnIntro'
'submit .js-inbound': 'probeInbound'
'change .js-inbound [name=adapter]': 'toggleInboundAdapter'
'change .js-outbound [name=adapter]': 'toggleOutboundAdapter'
'submit .js-outbound': 'probleOutbound'
'click .js-goToSlide': 'goToSlide'
@ -372,10 +371,10 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
# base
configureAttributesBase = [
{ name: 'realname', display: __('Organization & Department Name'), tag: 'input', type: 'text', limit: 160, null: false, placeholder: __('Organization Support'), autocomplete: 'off' },
{ name: 'email', display: __('Email'), tag: 'input', type: 'email', limit: 120, null: false, placeholder: 'support@example.com', autocapitalize: false, autocomplete: 'off' },
{ name: 'password', display: __('Password'), tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'group_id', display: __('Destination Group'), tag: 'select', null: false, relation: 'Group', nulloption: true },
{ name: 'realname', display: 'Organization & Department Name', tag: 'input', type: 'text', limit: 160, null: false, placeholder: 'Organization Support', autocomplete: 'off' },
{ name: 'email', display: 'Email', tag: 'input', type: 'email', limit: 120, null: false, placeholder: 'support@example.com', autocapitalize: false, autocomplete: 'off' },
{ name: 'password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true },
]
@formMeta = new App.ControllerForm(
el: @$('.base-settings'),
@ -387,7 +386,7 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
# outbound
configureAttributesOutbound = [
{ name: 'adapter', display: __('Send Mails via'), tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
]
new App.ControllerForm(
el: @$('.base-outbound-type')
@ -401,22 +400,22 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
# inbound
configureAttributesInbound = [
{ name: 'adapter', display: __('Type'), tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
{ name: 'options::host', display: __('Host'), tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::user', display: __('User'), tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off' },
{ name: 'options::password', display: __('Password'), tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'options::ssl', display: __('SSL/STARTTLS'), tag: 'select', null: true, options: { 'off': __('No SSL'), 'ssl': __('SSL'), 'starttls': __('STARTTLS') }, default: 'ssl', translate: true, item_class: 'formGroup--halfSize' },
{ name: 'options::port', display: __('Port'), tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
{ name: 'options::folder', display: __('Folder'), tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, item_class: 'formGroup--halfSize' },
{ name: 'options::keep_on_server', display: __('Keep messages on server'), tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false, item_class: 'formGroup--halfSize' },
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off' },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'options::ssl', display: 'SSL/STARTTLS', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
{ name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, item_class: 'formGroup--halfSize' },
{ name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false, item_class: 'formGroup--halfSize' },
]
if !@channel
#Email Inbound form opened from new email wizard, show full settings
configureAttributesInbound = [
{ name: 'options::realname', display: __('Organization & Department Name'), tag: 'input', type: 'text', limit: 160, null: false, placeholder: __('Organization Support'), autocomplete: 'off' },
{ name: 'options::email', display: __('Email'), tag: 'input', type: 'email', limit: 120, null: false, placeholder: 'support@example.com', autocapitalize: false, autocomplete: 'off' },
{ name: 'options::group_id', display: __('Destination Group'), tag: 'select', null: false, relation: 'Group', nulloption: true },
{ name: 'options::realname', display: 'Organization & Department Name', tag: 'input', type: 'text', limit: 160, null: false, placeholder: 'Organization Support', autocomplete: 'off' },
{ name: 'options::email', display: 'Email', tag: 'input', type: 'email', limit: 120, null: false, placeholder: 'support@example.com', autocapitalize: false, autocomplete: 'off' },
{ name: 'options::group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true },
].concat(configureAttributesInbound)
@ -429,7 +428,20 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
ui.hide('options::folder')
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'),
model:
configure_attributes: configureAttributesInbound
@ -437,27 +449,9 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
params: @account.inbound
handlers: [
showHideFolder,
handlePort,
]
)
@toggleInboundAdapter()
form.el.find("select[name='options::ssl']").off('change').on('change', (e) ->
if $(e.target).val() is 'ssl'
form.el.find("[name='options::port']").val('993')
else if $(e.target).val() is 'off'
form.el.find("[name='options::port']").val('143')
)
toggleInboundAdapter: =>
form = @$('.base-inbound-settings')
adapter = form.find("select[name='adapter']")
starttls = form.find("select[name='options::ssl'] option[value='starttls']")
if adapter.val() isnt 'imap'
starttls.remove()
else if starttls.length < 1
starttls = $('<option/>').attr('value', 'starttls').text(__('STARTTLS'))
form.find("select[name='options::ssl']").append(starttls)
toggleOutboundAdapter: =>
@ -474,10 +468,10 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
adapter = @$('.js-outbound [name=adapter]').val()
if adapter is 'smtp'
configureAttributesOutbound = [
{ name: 'options::host', display: __('Host'), tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
{ name: 'options::user', display: __('User'), tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', },
{ name: 'options::password', display: __('Password'), tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'options::port', display: __('Port'), tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
]
@form = new App.ControllerForm(
el: @$('.base-outbound-settings')
@ -531,10 +525,10 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
else if data.result is 'duplicate'
@showSlide('js-intro')
@showAlert('js-intro', __('Account already exists!'))
@showAlert('js-intro', 'Account already exists!')
else
@showSlide('js-inbound')
@showAlert('js-inbound', __('The server settings could not be automatically detected. Please configure them manually.'))
@showAlert('js-inbound', 'Unable to detect your server settings. Manual configuration needed.')
@$('.js-inbound [name="options::user"]').val(@account['meta']['email'])
@$('.js-inbound [name="options::password"]').val(@account['meta']['password'])
@$('.js-inbound [name="options::email"]').val(@account['meta']['email'])
@ -611,16 +605,16 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
)
probeInboundMessagesFound: (data, verify) =>
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. We will move them all from your mailbox into Zammad.', data.content_messages)
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
@$('.js-inbound-acknowledge .js-messageFound').html(message)
if !verify
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
@$('.js-inbound-acknowledge .js-next').off('click.verify')
@$('.js-inbound-acknowledge .js-next').unbind('click.verify')
else
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
@$('.js-inbound-acknowledge .js-next').attr('data-slide', '')
@$('.js-inbound-acknowledge .js-next').off('click.verify').on('click.verify', (e) =>
@$('.js-inbound-acknowledge .js-next').unbind('click.verify').bind('click.verify', (e) =>
e.preventDefault()
@verify(@account)
)
@ -755,7 +749,7 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
@delay(
=>
@showSlide('js-intro')
@showAlert('js-intro', __('Email sending and receiving could not be verified. Please check your settings.'))
@showAlert('js-intro', 'Unable to verify sending and receiving. Please check your settings.')
2300
)
@ -765,7 +759,7 @@ class ChannelEmailAccountWizard extends App.ControllerWizardModal
@verify(@account, count + 1)
error: =>
@showSlide('js-intro')
@showAlert('js-intro', __('Email sending and receiving could not be verified. Please check your settings.'))
@showAlert('js-intro', 'Unable to verify sending and receiving. Please check your settings.')
)
hide: (e) =>
@ -836,7 +830,7 @@ class ChannelEmailNotificationWizard extends App.ControllerWizardModal
# outbound
configureAttributesOutbound = [
{ name: 'adapter', display: __('Send Mails via'), tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: @channelDriver.email.outbound },
]
new App.ControllerForm(
el: @$('.base-outbound-type')
@ -855,10 +849,10 @@ class ChannelEmailNotificationWizard extends App.ControllerWizardModal
adapter = @$('.js-outbound [name=adapter]').val()
if adapter is 'smtp'
configureAttributesOutbound = [
{ name: 'options::host', display: __('Host'), tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
{ name: 'options::user', display: __('User'), tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off' },
{ name: 'options::password', display: __('Password'), tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'options::port', display: __('Port'), tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off' },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true },
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
]
@form = new App.ControllerForm(
el: @$('.base-outbound-settings')
@ -906,4 +900,4 @@ class ChannelEmailNotificationWizard extends App.ControllerWizardModal
@enable(e)
)
App.Config.set('Email', { prio: 3000, name: __('Email'), parent: '#channels', target: '#channels/email', controller: ChannelEmail, permission: ['admin.channel_email'] }, 'NavBarAdmin')
App.Config.set('Email', { prio: 3000, name: 'Email', parent: '#channels', target: '#channels/email', controller: ChannelEmail, permission: ['admin.channel_email'] }, 'NavBarAdmin')

View file

@ -1,6 +1,6 @@
class ChannelFacebook extends App.ControllerSubContent
requiredPermission: 'admin.channel_facebook'
header: __('Facebook')
header: 'Facebook'
events:
'click .js-new': 'new'
'click .js-edit': 'edit'
@ -95,7 +95,7 @@ class ChannelFacebook extends App.ControllerSubContent
e.preventDefault()
id = $(e.target).closest('.action').data('id')
new App.ControllerConfirm(
message: __('Are you sure?')
message: 'Sure?'
callback: =>
@ajax(
id: 'facebook_delete'
@ -136,7 +136,7 @@ class ChannelFacebook extends App.ControllerSubContent
)
class AppConfig extends App.ControllerModal
head: __('Connect Facebook App')
head: 'Connect Facebook App'
shown: true
button: 'Connect'
buttonCancel: true
@ -178,15 +178,15 @@ class AppConfig extends App.ControllerModal
@isChanged = true
@close()
fail: =>
@el.find('.alert').removeClass('hidden').text(__('The entry could not be created.'))
@el.find('.alert').removeClass('hidden').text('Unable to create entry.')
)
return
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('App could not be verified.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to verify App.')
)
class AccountEdit extends App.ControllerModal
head: __('Facebook Account')
head: 'Facebook Account'
shown: true
buttonCancel: true
@ -242,7 +242,7 @@ class AccountEdit extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('The changes could not be saved.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
)
App.Config.set('Facebook', { prio: 5100, name: __('Facebook'), parent: '#channels', target: '#channels/facebook', controller: ChannelFacebook, permission: ['admin.channel_facebook'] }, 'NavBarAdmin')
App.Config.set('Facebook', { prio: 5100, name: 'Facebook', parent: '#channels', target: '#channels/facebook', controller: ChannelFacebook, permission: ['admin.channel_facebook'] }, 'NavBarAdmin')

View file

@ -1,7 +1,7 @@
# coffeelint: disable=no_unnecessary_double_quotes
class ChannelForm extends App.ControllerSubContent
requiredPermission: 'admin.channel_formular'
header: __('Form')
header: 'Form'
events:
'change form.js-paramsDesigner': 'updateParamsDesigner'
'keyup form.js-paramsDesigner': 'updateParamsDesigner'
@ -88,4 +88,4 @@ class ChannelForm extends App.ControllerSubContent
value = @paramsSetting.find('[name=group_id]').val()
App.Setting.set('form_ticket_create_group_id', value)
App.Config.set('Form', { prio: 2000, name: __('Form'), parent: '#channels', target: '#channels/form', controller: ChannelForm, permission: ['admin.channel_formular'] }, 'NavBarAdmin')
App.Config.set('Form', { prio: 2000, name: 'Form', parent: '#channels', target: '#channels/form', controller: ChannelForm, permission: ['admin.channel_formular'] }, 'NavBarAdmin')

View file

@ -1,29 +1,29 @@
class App.ChannelGoogle extends App.ControllerTabs
requiredPermission: 'admin.channel_google'
header: __('Google')
header: 'Google'
constructor: ->
super
@title __('Google'), true
@title 'Google', true
@tabs = [
{
name: __('Accounts'),
name: 'Accounts',
target: 'c-account',
controller: ChannelAccountOverview,
},
{
name: __('Filter'),
name: 'Filter',
target: 'c-filter',
controller: App.ChannelEmailFilter,
},
{
name: __('Signatures'),
name: 'Signatures',
target: 'c-signature',
controller: App.ChannelEmailSignature,
},
{
name: __('Settings'),
name: 'Settings',
target: 'c-setting',
controller: App.SettingsArea,
params: { area: 'Email::Base' },
@ -145,7 +145,7 @@ class ChannelAccountOverview extends App.ControllerSubContent
e.preventDefault()
id = $(e.target).closest('.action').data('id')
new App.ControllerConfirm(
message: __('Are you sure?')
message: 'Sure?'
callback: =>
@ajax(
id: 'google_delete'
@ -215,11 +215,11 @@ class ChannelAccountOverview extends App.ControllerSubContent
@load()
@notify
type: 'success'
msg: __('Rollback of channel migration succeeded!')
msg: 'Rollback of channel migration succeeded!'
error: (data) =>
@notify
type: 'error'
msg: __('Failed to roll back the migration of the channel!')
msg: 'Failed to rollback migration of the channel!'
)
groupChange: (e) =>
@ -237,7 +237,7 @@ class ChannelAccountOverview extends App.ControllerSubContent
channel_id = $(e.target).closest('.action').data('id')
new App.ControllerGenericNew(
pageData:
object: __('Email Address')
object: 'Email Address'
genericObject: 'EmailAddress'
container: @el.closest('.content')
item:
@ -250,7 +250,7 @@ class ChannelAccountOverview extends App.ControllerSubContent
id = $(e.target).closest('li').data('id')
new App.ControllerGenericEdit(
pageData:
object: __('Email Address')
object: 'Email Address'
genericObject: 'EmailAddress'
container: @el.closest('.content')
id: id
@ -271,12 +271,12 @@ class ChannelInboundEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
head: __('Channel')
head: 'Channel'
content: =>
configureAttributesBase = [
{ name: 'options::folder', display: __('Folder'), tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, placeholder: __('optional') },
{ name: 'options::keep_on_server', display: __('Keep messages on server'), tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false },
{ name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, placeholder: 'optional' },
{ name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false },
]
@form = new App.ControllerForm(
model:
@ -323,7 +323,7 @@ class ChannelInboundEdit extends App.ControllerModal
details = xhr.responseJSON || {}
@notify
type: 'error'
msg: App.i18n.translateContent(details.error_human || details.error || __('The changes could not be saved.'))
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to save changes.')
timeout: 6000
)
@ -331,11 +331,11 @@ class ChannelGroupEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
head: __('Channel')
head: 'Channel'
content: =>
configureAttributesBase = [
{ name: 'group_id', display: __('Destination Group'), tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
{ name: 'group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
]
@form = new App.ControllerForm(
model:
@ -375,11 +375,11 @@ class ChannelGroupEdit extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('The changes could not be saved.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
)
class AppConfig extends App.ControllerModal
head: __('Connect Google App')
head: 'Connect Google App'
shown: true
button: 'Connect'
buttonCancel: true
@ -421,11 +421,11 @@ class AppConfig extends App.ControllerModal
@isChanged = true
@close()
fail: =>
@el.find('.alert').removeClass('hidden').text(__('The entry could not be created.'))
@el.find('.alert').removeClass('hidden').text('Unable to create entry.')
)
return
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('App could not be verified.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to verify App.')
)
App.Config.set('google', { prio: 5000, name: __('Google'), parent: '#channels', target: '#channels/google', controller: App.ChannelGoogle, permission: ['admin.channel_google'] }, 'NavBarAdmin')
App.Config.set('google', { prio: 5000, name: 'Google', parent: '#channels', target: '#channels/google', controller: App.ChannelGoogle, permission: ['admin.channel_google'] }, 'NavBarAdmin')

View file

@ -1,29 +1,29 @@
class App.ChannelMicrosoft365 extends App.ControllerTabs
requiredPermission: 'admin.channel_microsoft365'
header: __('Microsoft 365')
header: 'Microsoft 365'
constructor: ->
super
@title __('Microsoft 365'), true
@title 'Microsoft 365', true
@tabs = [
{
name: __('Accounts'),
name: 'Accounts',
target: 'c-account',
controller: ChannelAccountOverview,
},
{
name: __('Filter'),
name: 'Filter',
target: 'c-filter',
controller: App.ChannelEmailFilter,
},
{
name: __('Signatures'),
name: 'Signatures',
target: 'c-signature',
controller: App.ChannelEmailSignature,
},
{
name: __('Settings'),
name: 'Settings',
target: 'c-setting',
controller: App.SettingsArea,
params: { area: 'Email::Base' },
@ -95,12 +95,8 @@ class ChannelAccountOverview extends App.ControllerSubContent
channels.push channel
# on a channel migration we need to auto redirect
# the user to the "Add Account" functionality after
# the filled up the external credentials
if @channel_id
item = App.Channel.find(@channel_id)
if item && item.area != 'Microsoft365::Account'
# auto redirect to gmail account linking if we have no account
if @channel_id && channels.length < 1
@new()
return
@ -115,14 +111,9 @@ class ChannelAccountOverview extends App.ControllerSubContent
not_used_email_addresses: not_used_email_addresses
)
# on a channel creation we will auto open the edit
# dialog after the redirect back to zammad to optional
# change the inbound configuration, but not for
# migrated channel because we guess that the inbound configuration
# is already correct for them.
if @channel_id
item = App.Channel.find(@channel_id)
if item && item.area == 'Microsoft365::Account' && item.options && item.options.backup_imap_classic is undefined
if item && item.options && item.options.backup_imap_classic is undefined
@editInbound(undefined, @channel_id, true)
@channel_id = undefined
@ -145,7 +136,7 @@ class ChannelAccountOverview extends App.ControllerSubContent
e.preventDefault()
id = $(e.target).closest('.action').data('id')
new App.ControllerConfirm(
message: __('Are you sure?')
message: 'Sure?'
callback: =>
@ajax(
id: 'microsoft365_delete'
@ -215,11 +206,11 @@ class ChannelAccountOverview extends App.ControllerSubContent
@load()
@notify
type: 'success'
msg: __('Rollback of channel migration succeeded!')
msg: 'Rollback of channel migration succeeded!'
error: (data) =>
@notify
type: 'error'
msg: __('Failed to roll back the migration of the channel!')
msg: 'Failed to rollback migration of the channel!'
)
groupChange: (e) =>
@ -237,7 +228,7 @@ class ChannelAccountOverview extends App.ControllerSubContent
channel_id = $(e.target).closest('.action').data('id')
new App.ControllerGenericNew(
pageData:
object: __('Email Address')
object: 'Email Address'
genericObject: 'EmailAddress'
container: @el.closest('.content')
item:
@ -250,7 +241,7 @@ class ChannelAccountOverview extends App.ControllerSubContent
id = $(e.target).closest('li').data('id')
new App.ControllerGenericEdit(
pageData:
object: __('Email Address')
object: 'Email Address'
genericObject: 'EmailAddress'
container: @el.closest('.content')
id: id
@ -271,12 +262,12 @@ class ChannelInboundEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
head: __('Channel')
head: 'Channel'
content: =>
configureAttributesBase = [
{ name: 'options::folder', display: __('Folder'), tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false },
{ name: 'options::keep_on_server', display: __('Keep messages on server'), tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false },
{ name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false },
{ name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false },
]
@form = new App.ControllerForm(
model:
@ -323,7 +314,7 @@ class ChannelInboundEdit extends App.ControllerModal
details = xhr.responseJSON || {}
@notify
type: 'error'
msg: App.i18n.translateContent(details.error_human || details.error || __('The changes could not be saved.'))
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to save changes.')
timeout: 6000
)
@ -331,11 +322,11 @@ class ChannelGroupEdit extends App.ControllerModal
buttonClose: true
buttonCancel: true
buttonSubmit: true
head: __('Channel')
head: 'Channel'
content: =>
configureAttributesBase = [
{ name: 'group_id', display: __('Destination Group'), tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
{ name: 'group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
]
@form = new App.ControllerForm(
model:
@ -375,11 +366,11 @@ class ChannelGroupEdit extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('The changes could not be saved.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
)
class AppConfig extends App.ControllerModal
head: __('Connect Microsoft 365 App')
head: 'Connect Microsoft 365 App'
shown: true
button: 'Connect'
buttonCancel: true
@ -421,11 +412,11 @@ class AppConfig extends App.ControllerModal
@isChanged = true
@close()
fail: =>
@el.find('.alert').removeClass('hidden').text(__('The entry could not be created.'))
@el.find('.alert').removeClass('hidden').text('Unable to create entry.')
)
return
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('App could not be verified.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to verify App.')
)
App.Config.set('microsoft365', { prio: 5000, name: __('Microsoft 365'), parent: '#channels', target: '#channels/microsoft365', controller: App.ChannelMicrosoft365, permission: ['admin.channel_microsoft365'] }, 'NavBarAdmin')
App.Config.set('microsoft365', { prio: 5000, name: 'Microsoft 365', parent: '#channels', target: '#channels/microsoft365', controller: App.ChannelMicrosoft365, permission: ['admin.channel_microsoft365'] }, 'NavBarAdmin')

View file

@ -1,13 +1,13 @@
class ChannelSms extends App.ControllerTabs
requiredPermission: 'admin.channel_sms'
header: __('SMS')
header: 'SMS'
constructor: ->
super
@title __('SMS'), true
@title 'SMS', true
@tabs = [
{
name: __('Accounts'),
name: 'Accounts',
target: 'c-account',
controller: ChannelSmsAccountOverview,
},
@ -136,11 +136,11 @@ class ChannelSmsAccountOverview extends App.Controller
)
class ChannelSmsAccount extends App.ControllerModal
head: __('SMS Account')
head: 'SMS Account'
buttonCancel: true
centerButtons: [
{
text: __('Test')
text: 'Test'
className: 'js-test'
}
]
@ -164,13 +164,13 @@ class ChannelSmsAccount extends App.ControllerModal
el: el.find('.js-channelAdapterSelector')
model:
configure_attributes: [
{ name: 'options::adapter', display: __('Provider'), tag: 'select', null: false, options: options, nulloption: true }
{ name: 'options::adapter', display: 'Provider', tag: 'select', null: false, options: options, nulloption: true }
]
className: ''
params: @channel
)
@renderAdapterOptions(@channel.options?.adapter, el)
el.find('[name="options::adapter"]').on('change', (e) =>
el.find('[name="options::adapter"]').bind('change', (e) =>
@renderAdapterOptions(e.target.value, el)
)
el
@ -198,7 +198,7 @@ class ChannelSmsAccount extends App.ControllerModal
el: el.find('.js-channelWebhook')
model:
configure_attributes: [
{ name: 'options::webhook', display: __('Webhook'), tag: 'input', type: 'text', limit: 200, null: false, default: webhook, disabled: true },
{ name: 'options::webhook', display: 'Webhook', tag: 'input', type: 'text', limit: 200, null: false, default: webhook, disabled: true },
]
className: ''
params: @channel
@ -262,7 +262,7 @@ class ChannelSmsAccount extends App.ControllerModal
fail: (settings, details) ->
ui.log 'errors', details
ui.formEnable(e)
ui.showAlert(details.error_human || details.error || __('The object could not be updated.'))
ui.showAlert(details.error_human || details.error || 'Unable to update object!')
)
onTest: (e) ->
@ -273,11 +273,11 @@ class ChannelSmsAccount extends App.ControllerModal
)
class ChannelSmsNotification extends App.ControllerModal
head: __('SMS Notification')
head: 'SMS Notification'
buttonCancel: true
centerButtons: [
{
text: __('Test')
text: 'Test'
className: 'js-test'
}
]
@ -303,13 +303,13 @@ class ChannelSmsNotification extends App.ControllerModal
el: el.find('.js-channelAdapterSelector')
model:
configure_attributes: [
{ name: 'options::adapter', display: __('Provider'), tag: 'select', null: false, options: options, nulloption: true }
{ name: 'options::adapter', display: 'Provider', tag: 'select', null: false, options: options, nulloption: true }
]
className: ''
params: @channel
)
@renderAdapterOptions(@channel.options?.adapter, el)
el.find('[name="options::adapter"]').on('change', (e) =>
el.find('[name="options::adapter"]').bind('change', (e) =>
@renderAdapterOptions(e.target.value, el)
)
el
@ -376,7 +376,7 @@ class ChannelSmsNotification extends App.ControllerModal
fail: (settings, details) ->
ui.log 'errors', details
ui.formEnable(e)
ui.showAlert(details.error_human || details.error || __('The object could not be updated.'))
ui.showAlert(details.error_human || details.error || 'Unable to update object!')
)
onTest: (e) ->
@ -387,15 +387,15 @@ class ChannelSmsNotification extends App.ControllerModal
)
class TestModal extends App.ControllerModal
head: __('Test SMS provider')
head: 'Test SMS provider'
buttonCancel: true
content: ->
form = new App.ControllerForm(
model:
configure_attributes: [
{ name: 'recipient', display: __('Recipient'), tag: 'input', null: false }
{ name: 'message', display: __('Message'), tag: 'input', null: false, default: __('Test message from Zammad') }
{ name: 'recipient', display: 'Recipient', tag: 'input', null: false }
{ name: 'message', display: 'Message', tag: 'input', null: false, default: 'Test message from Zammad' }
]
className: ''
)
@ -435,8 +435,8 @@ class TestModal extends App.ControllerModal
data = JSON.parse(xhr.responseText)
@formEnable(@el)
@el.find('.js-danger')
.text(@T(data.error || __('SMS test failed.')))
.text(@T(data.error || 'Unable to perform test'))
.removeClass('hide')
)
App.Config.set('SMS', { prio: 3100, name: __('SMS'), parent: '#channels', target: '#channels/sms', controller: ChannelSms, permission: ['admin.channel_sms'] }, 'NavBarAdmin')
App.Config.set('SMS', { prio: 3100, name: 'SMS', parent: '#channels', target: '#channels/sms', controller: ChannelSms, permission: ['admin.channel_sms'] }, 'NavBarAdmin')

View file

@ -63,7 +63,7 @@ class ChannelTelegram extends App.ControllerSubContent
e.preventDefault()
id = $(e.target).closest('.action').data('id')
new App.ControllerConfirm(
message: __('Are you sure?')
message: 'Sure?'
callback: =>
@ajax(
id: 'telegram_delete'
@ -104,7 +104,7 @@ class ChannelTelegram extends App.ControllerSubContent
)
class BotAdd extends App.ControllerModal
head: __('Add Telegram Bot')
head: 'Add Telegram Bot'
shown: true
button: 'Add'
buttonCancel: true
@ -149,12 +149,12 @@ class BotAdd extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
error_message = App.i18n.translateContent(data.error || __('The Telegram bot could not be saved.'))
error_message = App.i18n.translateContent(data.error || 'Unable to save Bot.')
@el.find('.alert').removeClass('hidden').text(error_message)
)
class BotEdit extends App.ControllerModal
head: __('Telegram Account')
head: 'Telegram Account'
shown: true
buttonCancel: true
@ -197,8 +197,8 @@ class BotEdit extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
error_message = App.i18n.translateContent(data.error || __('The changes could not be saved.'))
error_message = App.i18n.translateContent(data.error || 'Unable to save changes.')
@el.find('.alert').removeClass('hidden').text(error_message)
)
App.Config.set('Telegram', { prio: 5100, name: __('Telegram'), parent: '#channels', target: '#channels/telegram', controller: ChannelTelegram, permission: ['admin.channel_telegram'] }, 'NavBarAdmin')
App.Config.set('Telegram', { prio: 5100, name: 'Telegram', parent: '#channels', target: '#channels/telegram', controller: ChannelTelegram, permission: ['admin.channel_telegram'] }, 'NavBarAdmin')

View file

@ -102,7 +102,7 @@ class ChannelTwitter extends App.ControllerSubContent
e.preventDefault()
id = $(e.target).closest('.action').data('id')
new App.ControllerConfirm(
message: __('Are you sure?')
message: 'Sure?'
callback: =>
@ajax(
id: 'twitter_delete'
@ -143,7 +143,7 @@ class ChannelTwitter extends App.ControllerSubContent
)
class AppConfig extends App.ControllerModal
head: __('Connect Twitter App')
head: 'Connect Twitter App'
shown: true
button: 'Connect'
buttonCancel: true
@ -185,15 +185,15 @@ class AppConfig extends App.ControllerModal
@isChanged = true
@close()
fail: =>
@el.find('.alert').removeClass('hidden').text(__('The entry could not be created.'))
@el.find('.alert').removeClass('hidden').text('Unable to create entry.')
)
return
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('App could not be verified.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to verify App.')
)
class AccountEdit extends App.ControllerModal
head: __('Twitter Account')
head: 'Twitter Account'
shown: true
buttonCancel: true
@ -219,7 +219,7 @@ class AccountEdit extends App.ControllerModal
term: ''
group_id: ''
renderSearchTerms()
content.find('.js-searchTermList [name="search::term"]').last().trigger('focus')
content.find('.js-searchTermList [name="search::term"]').last().focus()
removeSearchTerm = (event) =>
index = $(event.currentTarget).attr('data-index')
@ -248,7 +248,7 @@ class AccountEdit extends App.ControllerModal
renderSearchTerms()
content.find('.js-searchTermAdd').on('click', addSearchTerm)
content.find('.js-searchTermAdd').click(addSearchTerm)
content.find('.js-searchTermList').on('click', '.js-searchTermRemove', removeSearchTerm)
content.find('.js-mentionsGroup').replaceWith createGroupSelection(@channel.options.sync.mentions.group_id, 'mentions')
@ -296,7 +296,7 @@ class AccountEdit extends App.ControllerModal
error: (xhr) =>
data = JSON.parse(xhr.responseText)
@formEnable(e)
@el.find('.alert').removeClass('hidden').text(data.error || __('The changes could not be saved.'))
@el.find('.alert').removeClass('hidden').text(data.error || 'Unable to save changes.')
)
App.Config.set('Twitter', { prio: 5000, name: __('Twitter'), parent: '#channels', target: '#channels/twitter', controller: ChannelTwitter, permission: ['admin.channel_twitter'] }, 'NavBarAdmin')
App.Config.set('Twitter', { prio: 5000, name: 'Twitter', parent: '#channels', target: '#channels/twitter', controller: ChannelTwitter, permission: ['admin.channel_twitter'] }, 'NavBarAdmin')

View file

@ -1,14 +1,14 @@
class ChannelWeb extends App.ControllerTabs
requiredPermission: 'admin.channel_web'
header: __('Web')
header: 'Web'
constructor: ->
super
@title __('Web'), true
@title 'Web', true
@tabs = [
{
name: __('Settings'),
name: 'Settings',
target: 'w-setting',
controller: App.SettingsArea, params: { area: 'CustomerWeb::Base' },
},
@ -16,4 +16,4 @@ class ChannelWeb extends App.ControllerTabs
@render()
App.Config.set('Web', { prio: 1000, name: __('Web'), parent: '#channels', target: '#channels/web', controller: ChannelWeb, permission: ['admin.channel_web'] }, 'NavBarAdmin')
App.Config.set('Web', { prio: 1000, name: 'Web', parent: '#channels', target: '#channels/web', controller: ChannelWeb, permission: ['admin.channel_web'] }, 'NavBarAdmin')

View file

@ -38,7 +38,7 @@ class App.DashboardFirstSteps extends App.Controller
e.preventDefault()
new App.InviteUser(
#container: @el.closest('.content')
head: __('Invite Colleagues')
head: 'Invite Colleagues'
screen: 'invite_agent'
)
@ -46,7 +46,7 @@ class App.DashboardFirstSteps extends App.Controller
e.preventDefault()
new App.InviteUser(
#container: @el.closest('.content')
head: __('Invite Customer')
head: 'Invite Customer'
screen: 'invite_customer'
signup: true
)
@ -82,7 +82,7 @@ class App.DashboardFirstSteps extends App.Controller
e.preventDefault()
modal = new App.ControllerModal(
head: __('Test Ticket')
head: 'Test Ticket'
#container: @el.parents('.content')
content: @testTicketLoading
shown: true

View file

@ -2,22 +2,22 @@ class App.FirstStepsClues extends App.Controller
clues: [
{
container: '.js-dashboardMenuItem'
headline: __('Dashboard')
text: __('Here you see a quick overview of your and other agents\' performance.')
headline: 'Dashboard'
text: 'Here you see a quick overview of your and other agents\' performance.'
actions: [
'hover'
]
}
{
container: '.search-holder'
headline: __('Search')
text: __('Here you can search for tickets, customers, and organizations. Use the asterisk §*§ to find anything, e.g. §smi*§ or §rosent*l§. You also can use ||quotation marks|| for searching phrases: §"some phrase"§.')
headline: 'Search'
text: 'Here you can search for tickets, customers and organizations. Use the wildcard §*§ to find everything. E. g. §smi*§ or §rosent*l§. You also can use ||double quotes|| for searching phrases §"some phrase"§.'
actions: []
}
{
container: '.user-menu .add'
headline: __('Create')
text: __('Here you can create new tickets. Also, if you have the permission, you can create new customers and organizations.')
headline: 'Create'
text: 'Here you can create new tickets. Also if you have the permissions you can create new customers and organizations.'
actions: [
'hover .navigation',
'hover .user-menu .add'
@ -25,8 +25,8 @@ class App.FirstStepsClues extends App.Controller
}
{
container: '.user-menu .user .dropdown-menu'
headline: __('Personal Settings')
text: __('Here you can sign out, change the frontend language, and see your last viewed items.')
headline: 'Personal Settings'
text: 'Here you can sign out, change the frontend language and see your last viewed items.'
actions: [
'hover .navigation',
'click .user-menu .user .js-action',
@ -35,8 +35,8 @@ class App.FirstStepsClues extends App.Controller
}
{
container: '.js-overviewsMenuItem'
headline: __('Overviews')
text: __('Here you find your ticket overviews for open, assigned, and escalated tickets.')
headline: 'Overviews'
text: 'Here you find your ticket overviews for open, assigned and escalated tickets.'
actions: [
'hover'
]

View file

@ -24,7 +24,7 @@ class Stats extends App.ControllerDashboardStatsBase
for id, channel of data.StatsTicketChannelDistribution.channels
channel.overal_percentage = Math.round((channel.inbound + channel.outbound) / totalTickets * 100) || 0
data.StatsTicketChannelDistribution.description = __('How many of your tickets are coming from email, phone, Twitter, or Facebook? (Shows percentages for both inbound and outbound tickets.)')
data.StatsTicketChannelDistribution.description = 'How many of your tickets are coming from email, phone, Twitter, or Facebook? (Shows percentages for both inbound and outbound tickets.)'
content = App.view('dashboard/stats/ticket_channel_distribution')(data)

View file

@ -6,7 +6,7 @@ class Stats extends App.ControllerDashboardStatsBase
own: 0
total: 0
data.StatsTicketEscalation.description = __('How many escalated tickets do you have open? (Mr. Bubbles gets grumpy if you have too many…)')
data.StatsTicketEscalation.description = 'How many escalated tickets do you have open? (Mr. Bubbles gets grumpy if you have too many…)'
content = App.view('dashboard/stats/ticket_escalation')(data)

View file

@ -7,7 +7,7 @@ class Stats extends App.ControllerDashboardStatsBase
in_process: 0
average_per_agent: 0
data.StatsTicketInProcess.description = __('What percentage of your tickets have you responded to, updated, or modified in some way today?')
data.StatsTicketInProcess.description = 'What percentage of your tickets have you responded to, updated, or modified in some way today?'
content = App.view('dashboard/stats/ticket_in_process')(data)

View file

@ -8,7 +8,7 @@ class Stats extends App.ControllerDashboardStatsBase
total: 0
average_per_agent: 0
data.StatsTicketLoadMeasure.description = __('Out of all open tickets (company-wide), how many are assigned to you?')
data.StatsTicketLoadMeasure.description = 'Out of all open tickets (company-wide), how many are assigned to you?'
content = App.view('dashboard/stats/ticket_load_measure')(data)

View file

@ -6,7 +6,7 @@ class Stats extends App.ControllerDashboardStatsBase
percent: 0
average_per_agent: 0
data.StatsTicketReopen.description = __('How many of your tickets have been re-opened after being marked “closed”?')
data.StatsTicketReopen.description = 'How many of your tickets have been re-opened after being marked “closed”?'
content = App.view('dashboard/stats/ticket_reopen')(data)
if @$('.ticket_reopen').length > 0

View file

@ -7,7 +7,7 @@ class Stats extends App.ControllerDashboardStatsBase
state: 'supergood'
average_per_agent: 0
data.StatsTicketWaitingTime.description = __('How long did each customer have to wait, on average, to get a response from you today?')
data.StatsTicketWaitingTime.description = 'How long has each customer had to wait, on average, to get a response from you today?'
content = App.view('dashboard/stats/ticket_waiting_time')(data)
if @$('.ticket_waiting_time').length > 0

View file

@ -10,9 +10,9 @@ App.Config.set('User', {
class: 'user'
}, 'NavBarRight' )
App.Config.set('Admin', { prio: 9000, parent: '', name: __('Admin'), translate: true, target: '#manage', icon: 'cog', permission: ['admin.*'] }, 'NavBarRight')
App.Config.set('New', { prio: 20000, parent: '', name: __('New'), translate: true, target: '#new', class: 'add', icon: 'plus' }, 'NavBarRight')
App.Config.set('Misc', { prio: 90000, parent: '', name: __('Tools'), translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar')
App.Config.set('Admin', { prio: 9000, parent: '', name: 'Admin', translate: true, target: '#manage', icon: 'cog', permission: ['admin.*'] }, 'NavBarRight')
App.Config.set('New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add', icon: 'plus' }, 'NavBarRight')
App.Config.set('Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar')
# only for testing
#App.Config.set('Misc1', { prio: 1600, parent: '#tools', name: __('Test 1'), target: '#test1', permission: ['admin'] }, 'NavBar')
#App.Config.set('Misc2', { prio: 1700, parent: '#tools', name: __('Test 2'), target: '#test2', permission: ['admin'] }, 'NavBar')
#App.Config.set('Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', permission: ['admin'] }, 'NavBar')
#App.Config.set('Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', permission: ['admin'] }, 'NavBar')

View file

@ -1,10 +1,10 @@
class CheckMk extends App.ControllerIntegrationBase
featureIntegration: 'check_mk_integration'
featureName: __('Checkmk')
featureName: 'Checkmk'
featureConfig: 'check_mk_config'
description: [
[__('This service receives HTTP requests or emails from %s and creates tickets with host and service.'), 'Checkmk']
[__('If the host and service have recovered, the ticket can be closed automatically.')]
['This service receives http requests or emails from %s and creates tickets with host and service.', 'Checkmk']
['If the host and service has recovered, the ticket can be closed automatically.']
]
render: =>
@ -52,9 +52,9 @@ class Form extends App.Controller
App.Config.set(
'IntegrationCheckMk'
{
name: __('Checkmk')
name: 'Checkmk'
target: '#system/integration/check_mk'
description: __('An open-source monitoring tool.')
description: 'An open source monitoring tool.'
controller: CheckMk
state: State
permission: ['admin.integration.check_mk']

View file

@ -1,9 +1,10 @@
class Clearbit extends App.ControllerIntegrationBase
featureIntegration: 'clearbit_integration'
featureName: __('Clearbit')
featureName: 'Clearbit'
featureConfig: 'clearbit_config'
description: [
[__('Automatically enrich your customers and organizations with fresh, up-to-date intel. Map data directly to object fields.')]
['Automatically enrich your customers and organizations with fresh, up-to-date intel. Map data directly to object fields.
']
]
render: =>
@ -61,9 +62,9 @@ class Form extends App.Controller
if !@config
@config = @currentConfig()
settings = [
{ name: 'api_key', display: __('API Key'), tag: 'input', type: 'text', limit: 100, null: false, placeholder: '...', note: __('Your API key.') },
{ name: 'organization_autocreate', display: __('Auto create'), tag: 'boolean', type: 'boolean', null: false, note: __('Create organizations automatically if record has one.') },
{ name: 'organization_shared', display: __('Shared'), tag: 'boolean', type: 'boolean', null: false, note: __('New organizations are shared.') },
{ name: 'api_key', display: 'API Key', tag: 'input', type: 'text', limit: 100, null: false, placeholder: '...', note: 'Your api key.' },
{ name: 'organization_autocreate', display: 'Auto create', tag: 'boolean', type: 'boolean', null: false, note: 'Create organizations automatically if record has one.' },
{ name: 'organization_shared', display: 'Shared', tag: 'boolean', type: 'boolean', null: false, note: 'New organizations are shared.' },
]
@html App.view('integration/clearbit')(
@ -151,9 +152,9 @@ class State
App.Config.set(
'IntegrationClearbit'
{
name: __('Clearbit')
name: 'Clearbit'
target: '#system/integration/clearbit'
description: __('A powerful service to get more information about your customers.')
description: 'A powerful service to get more information about your customers.'
controller: Clearbit
state: State
permission: ['admin.integration.clearbit']

View file

@ -1,10 +1,10 @@
class Cti extends App.ControllerIntegrationBase
featureIntegration: 'cti_integration'
featureName: __('CTI (generic)')
featureName: 'CTI (generic)'
featureConfig: 'cti_config'
description: [
[__('This service shows you contacts of incoming calls and a caller list in realtime.')]
[__('Caller ID of outbound calls can be changed as well.')]
['This service shows you contacts of incoming calls and a caller list in realtime.']
['Also caller id of outbound calls can be changed.']
]
events:
'click .js-select': 'selectAll'
@ -135,7 +135,7 @@ class Form extends App.Controller
}
)
# blocked caller IDs
# blocked caller ids
config.inbound.block_caller_ids = []
@$('.js-inboundBlockCallerId .js-row').each(->
caller_id = $(@).find('input[name="caller_id"]').val()
@ -259,9 +259,9 @@ class State
App.Config.set(
'IntegrationCti'
{
name: __('CTI (generic)')
name: 'CTI (generic)'
target: '#system/integration/cti'
description: __('Generic API to integrate VoIP service provider with real-time push.')
description: 'Generic API to integrate VoIP service provider with realtime push.'
controller: Cti
state: State
}

View file

@ -1,9 +1,9 @@
class Exchange extends App.ControllerIntegrationBase
featureIntegration: 'exchange_integration'
featureName: __('Exchange')
featureName: 'Exchange'
featureConfig: 'exchange_config'
description: [
[__('This service enables Zammad to connect with your Exchange server.')]
['This service enables Zammad to connect with your Exchange server.']
]
events:
'change .js-switch input': 'switch'
@ -282,7 +282,7 @@ class ConnectionWizard extends App.ControllerWizardModal
if !_.isEmpty(detailsRaw)
details = JSON.parse(detailsRaw)
@showSlide('js-discover')
@showAlert('js-discover', details.error || __('Server operation failed.'))
@showAlert('js-discover', details.error || 'Unable to perform backend.')
)
folders: (e) =>
@ -323,7 +323,7 @@ class ConnectionWizard extends App.ControllerWizardModal
if !_.isEmpty(detailsRaw)
details = JSON.parse(detailsRaw)
@showSlide('js-bind')
@showAlert('js-bind', details.error || __('Server operation failed.'))
@showAlert('js-bind', details.error || 'Unable to perform backend.')
)
foldersShow: (alreadyShown) =>
@ -429,7 +429,7 @@ class ConnectionWizard extends App.ControllerWizardModal
if !_.isEmpty(detailsRaw)
details = JSON.parse(detailsRaw)
@showSlide('js-folders')
@showAlert('js-folders', details.error || __('Server operation failed.'))
@showAlert('js-folders', details.error || 'Unable to perform backend.')
)
mappingShow: (alreadyShown) =>
@ -554,9 +554,9 @@ class ConnectionWizard extends App.ControllerWizardModal
App.Config.set(
'IntegrationExchange'
{
name: __('Exchange')
name: 'Exchange'
target: '#system/integration/exchange'
description: __('Exchange integration for contacts management.')
description: 'Exchange integration for contacts management.'
controller: Exchange
state: State
permission: ['admin.integration.exchange']

View file

@ -1,9 +1,9 @@
class GitHub extends App.ControllerIntegrationBase
featureIntegration: 'github_integration'
featureName: __('GitHub')
featureName: 'GitHub'
featureConfig: 'github_config'
description: [
[__('This service allows you to connect %s with %s.'), 'GitHub', 'Zammad']
['This service allows you to connect %s with %s.', 'GitHub', 'Zammad']
]
events:
'change .js-switch input': 'switch'
@ -60,7 +60,7 @@ class Form extends App.Controller
details = data.responseJSON || {}
App.Event.trigger 'notify', {
type: 'error'
msg: App.i18n.translateContent(details.error_human || details.error || __('Saving failed.'))
msg: App.i18n.translateContent(details.error_human || details.error || 'Unable to save!')
}
)
@ -71,9 +71,9 @@ class State
App.Config.set(
'IntegrationGitHub'
{
name: __('GitHub')
name: 'GitHub'
target: '#system/integration/github'
description: __('Link GitHub issues to your tickets.')
description: 'Link GitHub issues to your tickets.'
controller: GitHub
state: State
}

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