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.
- data/LICENSE +13 -0
- data/README.md +3 -0
- data/config/locales/en.yml +26 -0
- data/config/locales/translations/zendesk_apps_support.yml +54 -0
- data/lib/zendesk_apps_support.rb +20 -0
- data/lib/zendesk_apps_support/app_file.rb +42 -0
- data/lib/zendesk_apps_support/app_version.rb +68 -0
- data/lib/zendesk_apps_support/default_styles.scss +21 -0
- data/lib/zendesk_apps_support/engine.rb +11 -0
- data/lib/zendesk_apps_support/i18n.rb +28 -0
- data/lib/zendesk_apps_support/package.rb +100 -0
- data/lib/zendesk_apps_support/sass_functions.rb +22 -0
- data/lib/zendesk_apps_support/src.js.erb +24 -0
- data/lib/zendesk_apps_support/stylesheet_compiler.rb +25 -0
- data/lib/zendesk_apps_support/validations/manifest.rb +48 -0
- data/lib/zendesk_apps_support/validations/source.rb +43 -0
- data/lib/zendesk_apps_support/validations/templates.rb +20 -0
- data/lib/zendesk_apps_support/validations/translations.rb +38 -0
- data/lib/zendesk_apps_support/validations/validation_error.rb +103 -0
- data/spec/app/app.css +6 -0
- data/spec/app/app.js +12 -0
- data/spec/app/assets/logo-small.png +0 -0
- data/spec/app/assets/logo.png +0 -0
- data/spec/app/manifest.json +11 -0
- data/spec/app/templates/layout.hdbs +11 -0
- data/spec/app/translations/en.json +5 -0
- data/spec/app_file_spec.rb +27 -0
- data/spec/app_version_spec.rb +61 -0
- data/spec/i18n_spec.rb +22 -0
- data/spec/package_spec.rb +84 -0
- data/spec/validations/jshint_error_spec.rb +17 -0
- data/spec/validations/manifest_spec.rb +39 -0
- data/spec/validations/source_spec.rb +21 -0
- data/spec/validations/templates_spec.rb +13 -0
- data/spec/validations/translations_spec.rb +58 -0
- data/spec/validations/validation_serialization_spec.rb +96 -0
- 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.
|
data/README.md
ADDED
@@ -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,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
|
+
}());
|