zendesk_apps_support 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}());
|