zendesk_apps_support 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/LICENSE +13 -0
  2. data/README.md +3 -0
  3. data/config/locales/en.yml +26 -0
  4. data/config/locales/translations/zendesk_apps_support.yml +54 -0
  5. data/lib/zendesk_apps_support.rb +20 -0
  6. data/lib/zendesk_apps_support/app_file.rb +42 -0
  7. data/lib/zendesk_apps_support/app_version.rb +68 -0
  8. data/lib/zendesk_apps_support/default_styles.scss +21 -0
  9. data/lib/zendesk_apps_support/engine.rb +11 -0
  10. data/lib/zendesk_apps_support/i18n.rb +28 -0
  11. data/lib/zendesk_apps_support/package.rb +100 -0
  12. data/lib/zendesk_apps_support/sass_functions.rb +22 -0
  13. data/lib/zendesk_apps_support/src.js.erb +24 -0
  14. data/lib/zendesk_apps_support/stylesheet_compiler.rb +25 -0
  15. data/lib/zendesk_apps_support/validations/manifest.rb +48 -0
  16. data/lib/zendesk_apps_support/validations/source.rb +43 -0
  17. data/lib/zendesk_apps_support/validations/templates.rb +20 -0
  18. data/lib/zendesk_apps_support/validations/translations.rb +38 -0
  19. data/lib/zendesk_apps_support/validations/validation_error.rb +103 -0
  20. data/spec/app/app.css +6 -0
  21. data/spec/app/app.js +12 -0
  22. data/spec/app/assets/logo-small.png +0 -0
  23. data/spec/app/assets/logo.png +0 -0
  24. data/spec/app/manifest.json +11 -0
  25. data/spec/app/templates/layout.hdbs +11 -0
  26. data/spec/app/translations/en.json +5 -0
  27. data/spec/app_file_spec.rb +27 -0
  28. data/spec/app_version_spec.rb +61 -0
  29. data/spec/i18n_spec.rb +22 -0
  30. data/spec/package_spec.rb +84 -0
  31. data/spec/validations/jshint_error_spec.rb +17 -0
  32. data/spec/validations/manifest_spec.rb +39 -0
  33. data/spec/validations/source_spec.rb +21 -0
  34. data/spec/validations/templates_spec.rb +13 -0
  35. data/spec/validations/translations_spec.rb +58 -0
  36. data/spec/validations/validation_serialization_spec.rb +96 -0
  37. metadata +212 -0
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2012 Zendesk
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,3 @@
1
+ ## Zendesk Apps Support
2
+
3
+ Classes to manage and validate zendesk apps
@@ -0,0 +1,26 @@
1
+ # This is a generated file. Please do not edit it.
2
+ ---
3
+ en:
4
+ txt:
5
+ apps:
6
+ admin:
7
+ error:
8
+ app_build:
9
+ jshint:
10
+ one: ! 'JSHint error in %{file}: %{errors}'
11
+ other: ! 'JSHint errors in %{file}: %{errors}'
12
+ manifest_not_json: manifest is not proper JSON. %{errors}
13
+ missing_manifest: Could not find manifest.json
14
+ manifest_keys:
15
+ missing:
16
+ one: ! 'Missing required field in manifest: %{missing_keys}'
17
+ other: ! 'Missing required fields in manifest: %{missing_keys}'
18
+ missing_source: Could not find app.js
19
+ style_in_template: <style> tag in %{template}. Use an app.css file instead.
20
+ invalid_default_locale: ! '%{defaultLocale} is not a valid defaultLocale.
21
+ Only two- and three-letter ISO 639 language codes are allowed.'
22
+ translation:
23
+ invalid_locale: ! '%{file} is not a valid locale. Only two- and three-letter
24
+ ISO 639 language codes are allowed.'
25
+ not_json: ! '%{file} is not valid JSON. %{errors}'
26
+ not_json_object: ! '%{file} is not a JSON object.'
@@ -0,0 +1,54 @@
1
+ # This file is contains translations in Zendesk's custom format. The rake task
2
+ # `i18n:standardize` will generate a version that is compatible with the i18n
3
+ # gem (and thus Rails). Both versions should be checked in.
4
+ title: "Apps Support"
5
+
6
+ parts:
7
+ - translation:
8
+ key: "txt.apps.admin.error.app_build.jshint.one"
9
+ title: "App builder job: JSHint error message"
10
+ value: "JSHint error in %{file}: %{errors}"
11
+ - translation:
12
+ key: "txt.apps.admin.error.app_build.jshint.other"
13
+ title: "App builder job: JSHint error messages"
14
+ value: "JSHint errors in %{file}: %{errors}"
15
+ - translation:
16
+ key: "txt.apps.admin.error.app_build.manifest_not_json"
17
+ title: "App builder job: manifest is invalid JSON error"
18
+ value: "manifest is not proper JSON. %{errors}"
19
+ - translation:
20
+ key: "txt.apps.admin.error.app_build.missing_manifest"
21
+ title: "App builder job: missing manifest error"
22
+ value: "Could not find manifest.json"
23
+ - translation:
24
+ key: "txt.apps.admin.error.app_build.manifest_keys.missing.one"
25
+ title: "App builder job: missing manifest fields error"
26
+ value: "Missing required field in manifest: %{missing_keys}"
27
+ - translation:
28
+ key: "txt.apps.admin.error.app_build.manifest_keys.missing.other"
29
+ title: "App builder job: missing manifest fields error"
30
+ value: "Missing required fields in manifest: %{missing_keys}"
31
+ - translation:
32
+ key: "txt.apps.admin.error.app_build.missing_source"
33
+ title: "App builder job: missing app.js error"
34
+ value: "Could not find app.js"
35
+ - translation:
36
+ key: "txt.apps.admin.error.app_build.style_in_template"
37
+ title: "App builder job: <style> tags in template error"
38
+ value: "<style> tag in %{template}. Use an app.css file instead."
39
+ - translation:
40
+ key: "txt.apps.admin.error.app_build.invalid_default_locale"
41
+ title: "App builder job: invalid default locale"
42
+ value: "%{defaultLocale} is not a valid default locale. Only two- and three-letter ISO 639 language codes are allowed."
43
+ - translation:
44
+ key: "txt.apps.admin.error.app_build.translation.invalid_locale"
45
+ title: "App builder job: invalid locale file name"
46
+ value: "%{file} is not a valid locale. Only two- and three-letter ISO 639 language codes are allowed."
47
+ - translation:
48
+ key: "txt.apps.admin.error.app_build.translation.not_json"
49
+ title: "App builder job: translation file is invalid json"
50
+ value: "%{file} is not valid JSON. %{errors}"
51
+ - translation:
52
+ key: "txt.apps.admin.error.app_build.translation.not_json_object"
53
+ title: "App builder job: translation file is not a JSON object"
54
+ value: "%{file} is not a JSON object."
@@ -0,0 +1,20 @@
1
+ module ZendeskAppsSupport
2
+
3
+ require 'zendesk_apps_support/sass_functions'
4
+ require 'zendesk_apps_support/engine'
5
+
6
+ autoload :AppFile, 'zendesk_apps_support/app_file'
7
+ autoload :I18n, 'zendesk_apps_support/i18n'
8
+ autoload :Package, 'zendesk_apps_support/package'
9
+ autoload :AppVersion, 'zendesk_apps_support/app_version'
10
+ autoload :StylesheetCompiler, 'zendesk_apps_support/stylesheet_compiler'
11
+
12
+ module Validations
13
+ autoload :ValidationError, 'zendesk_apps_support/validations/validation_error'
14
+ autoload :Manifest, 'zendesk_apps_support/validations/manifest'
15
+ autoload :Source, 'zendesk_apps_support/validations/source'
16
+ autoload :Templates, 'zendesk_apps_support/validations/templates'
17
+ autoload :Translations, 'zendesk_apps_support/validations/translations'
18
+ autoload :JSHintValidationError, 'zendesk_apps_support/validations/validation_error'
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ module ZendeskAppsSupport
2
+
3
+ class AppFile
4
+
5
+ attr_reader :relative_path
6
+
7
+ def initialize(package, relative_path)
8
+ @relative_path = relative_path
9
+ @file = File.new(package.root.join(relative_path))
10
+ end
11
+
12
+ def read
13
+ File.read @file.path
14
+ end
15
+
16
+ def =~(regex)
17
+ @relative_path =~ regex
18
+ end
19
+
20
+ alias_method :to_s, :relative_path
21
+
22
+ def method_missing(sym, *args, &block)
23
+ if @file.respond_to?(sym)
24
+ @file.call(sym, *args, &block)
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ # Unless Ruby 1.9
31
+ def respond_to?(sym, include_private = false)
32
+ @file.respond_to?(sym, include_private) || super
33
+ end
34
+
35
+ # If Ruby 1.9
36
+ def respond_to_missing?(sym, include_private = false)
37
+ @file.respond_to_missing?(sym, include_private) || super
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,68 @@
1
+ require 'multi_json'
2
+
3
+ module ZendeskAppsSupport
4
+
5
+ # At any point in time, we support up to three versions:
6
+ # * deprecated -- we will still serve apps targeting the deprecated version,
7
+ # but newly created or updated apps CANNOT target it
8
+ # * current -- we will serve apps targeting the current version;
9
+ # newly created or updated apps SHOULD target it
10
+ # * future -- we will serve apps targeting the future version;
11
+ # newly created or updates apps MAY target it, but it
12
+ # may change without notice
13
+ class AppVersion
14
+
15
+ DEPRECATED = '0.4'.freeze
16
+ CURRENT = '0.5'.freeze
17
+ FUTURE = nil
18
+
19
+ TO_BE_SERVED = [ DEPRECATED, CURRENT, FUTURE ].compact.freeze
20
+ VALID_FOR_UPDATE = [ CURRENT, FUTURE ].compact.freeze
21
+
22
+ def initialize(version)
23
+ @version = version.to_s
24
+ @version.freeze
25
+ freeze
26
+ end
27
+
28
+ def servable?
29
+ TO_BE_SERVED.include?(@version)
30
+ end
31
+
32
+ def valid_for_update?
33
+ VALID_FOR_UPDATE.include?(@version)
34
+ end
35
+
36
+ def deprecated?
37
+ @version == DEPRECATED
38
+ end
39
+
40
+ def obsolete?
41
+ !servable?
42
+ end
43
+
44
+ def blank?
45
+ @version.nil? || @version == ''
46
+ end
47
+
48
+ def present?
49
+ !blank?
50
+ end
51
+
52
+ def to_s
53
+ @version
54
+ end
55
+
56
+ def to_json(*options)
57
+ MultiJson.encode(@version)
58
+ end
59
+
60
+ def ==(other)
61
+ @version == other.to_s
62
+ end
63
+
64
+ end
65
+
66
+ AppVersion.freeze
67
+
68
+ end
@@ -0,0 +1,21 @@
1
+ header {
2
+ border-bottom: 1px dotted #CCC; margin-bottom: 12px;
3
+
4
+ h3 { line-height: 30px; }
5
+ hr { margin-top: 0; }
6
+
7
+ .logo {
8
+ background: transparent app-asset-url("logo-small.png") no-repeat;
9
+ background-size: 25px 25px; float: right; height: 25px; width: 25px;
10
+ }
11
+
12
+ .app-warning-icon {
13
+ cursor: pointer;
14
+ float: right;
15
+ margin-left: 2px;
16
+ padding: 5px;
17
+ }
18
+ }
19
+
20
+ h3 { font-size: 14px; }
21
+ footer { background: none; border: 0 }
@@ -0,0 +1,11 @@
1
+ if Object.const_defined?(:Rails) && Rails.const_defined?(:Engine)
2
+
3
+ module ZendeskAppsSupport
4
+
5
+ class Engine < Rails::Engine
6
+ engine_name 'zendesk_apps_support'
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,28 @@
1
+ module ZendeskAppsSupport
2
+ module I18n
3
+ class << self
4
+ def t(key, *args)
5
+ i18n.t(key, *args)
6
+ end
7
+
8
+ def set_locale(locale)
9
+ i18n.locale = locale
10
+ end
11
+
12
+ private
13
+
14
+ def i18n
15
+ @i18n ||= begin
16
+ require 'i18n'
17
+ ::I18n.load_path += locale_files
18
+ ::I18n
19
+ end
20
+ end
21
+
22
+ def locale_files
23
+ Dir[ File.expand_path('../../../config/locales/*.yml', __FILE__) ] -
24
+ Dir[ File.expand_path('../../../config/locales/*.zendesk.yml', __FILE__) ]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,100 @@
1
+ require 'pathname'
2
+ require 'erubis'
3
+ require 'json'
4
+
5
+ module ZendeskAppsSupport
6
+ class Package
7
+
8
+ DEFAULT_SCSS = File.read(File.expand_path('../default_styles.scss', __FILE__))
9
+ SRC_TEMPLATE = Erubis::Eruby.new( File.read(File.expand_path('../src.js.erb', __FILE__)) )
10
+
11
+ attr_reader :root
12
+
13
+ def initialize(dir)
14
+ @root = Pathname.new(File.expand_path(dir))
15
+ end
16
+
17
+ def validate
18
+ Validations::Manifest.call(self) +
19
+ Validations::Source.call(self) +
20
+ Validations::Templates.call(self) +
21
+ Validations::Translations.call(self)
22
+ end
23
+
24
+ def files
25
+ non_tmp_files
26
+ end
27
+
28
+ def template_files
29
+ files.select { |f| f =~ /^templates\/.*\.hdbs$/ }
30
+ end
31
+
32
+ def translation_files
33
+ files.select { |f| f =~ /^translations\// }
34
+ end
35
+
36
+ def manifest_json
37
+ JSON.parse(File.read(File.join(root, "manifest.json")), :symbolize_names => true)
38
+ end
39
+
40
+ def readified_js(app_name, app_id, asset_url_prefix, settings={})
41
+ manifest = manifest_json
42
+ source = File.read(File.join(root, "app.js"))
43
+ name = app_name || manifest[:name] || 'Local App'
44
+ location = manifest[:location]
45
+ app_class_name = "app-#{app_id}"
46
+ author = manifest[:author]
47
+ translations = JSON.parse(File.read(File.join(root, "translations/en.json")))
48
+ framework_version = manifest[:frameworkVersion]
49
+ templates = compiled_templates(app_id, asset_url_prefix)
50
+
51
+ settings["title"] = name
52
+
53
+ SRC_TEMPLATE.result(
54
+ :name => name,
55
+ :source => source,
56
+ :location => location,
57
+ :asset_url_prefix => asset_url_prefix,
58
+ :app_class_name => app_class_name,
59
+ :author => author,
60
+ :translations => translations,
61
+ :framework_version => framework_version,
62
+ :templates => templates,
63
+ :settings => settings,
64
+ :app_id => app_id
65
+ )
66
+ end
67
+
68
+ private
69
+
70
+ def compiled_templates(app_id, asset_url_prefix)
71
+ css_file = File.join(root, "app.css")
72
+ customer_css = File.exist?(css_file) ? File.read(css_file) : ""
73
+ compiled_css = ZendeskAppsSupport::StylesheetCompiler.new(DEFAULT_SCSS + customer_css, app_id, asset_url_prefix).compile
74
+
75
+ templates = begin
76
+ Dir["#{root.to_s}/templates/*.hdbs"].inject({}) do |h, file|
77
+ str = File.read(file)
78
+ str.chomp!
79
+ h[File.basename(file, File.extname(file))] = str
80
+ h
81
+ end
82
+ end
83
+
84
+ templates.tap do |templates|
85
+ templates['layout'] = "<style>\n#{compiled_css}</style>\n#{templates['layout']}"
86
+ end
87
+ end
88
+
89
+ def non_tmp_files
90
+ files = []
91
+ Dir[ root.join('**/**') ].each do |f|
92
+ next unless File.file?(f)
93
+ relative_file_name = f.sub(/#{root}\/?/, '')
94
+ next if relative_file_name =~ /^tmp\//
95
+ files << AppFile.new(self, relative_file_name)
96
+ end
97
+ files
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,22 @@
1
+ require 'sass'
2
+
3
+ module Sass::Script::Functions
4
+
5
+ module AppAssetUrl
6
+ def app_asset_url(name)
7
+ assert_type name, :String
8
+ result = %Q{url("#{app_asset_url_helper(name)}")}
9
+ Sass::Script::String.new(result)
10
+ end
11
+
12
+ private
13
+
14
+ def app_asset_url_helper(name)
15
+ url_builder = options[:app_asset_url_builder]
16
+ url_builder.app_asset_url(name.value)
17
+ end
18
+ end
19
+
20
+ include AppAssetUrl
21
+
22
+ end
@@ -0,0 +1,24 @@
1
+ (function() {
2
+ with( require('apps/framework/app_scope') ) {
3
+
4
+ var source = <%= source %>;
5
+
6
+ ZendeskApps[<%= name.to_json %>] = ZendeskApps.defineApp(source)
7
+ .reopenClass({ location: <%= location.to_json %> })
8
+ .reopen({
9
+ assetUrlPrefix: <%= asset_url_prefix.to_json %>,
10
+ appClassName: <%= app_class_name.to_json %>,
11
+ author: {
12
+ name: <%= author[:name].to_json %>,
13
+ email: <%= author[:email].to_json %>
14
+ },
15
+ translations: <%= translations.to_json %>,
16
+ templates: <%= templates.to_json %>,
17
+ frameworkVersion: <%= framework_version.to_json %>
18
+ });
19
+
20
+ }
21
+
22
+ ZendeskApps[<%= name.to_json %>].install({"id": <%= app_id %>, "app_id": <%= app_id %>, "settings": <%= settings.to_json %>});
23
+
24
+ }());