Added example.

This commit is contained in:
agolybev
2015-04-29 19:10:50 +03:00
parent 9fa5abd662
commit 5a5952e41f
288 changed files with 66614 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*
!/log/.keep
/tmp

View File

@@ -0,0 +1,46 @@
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.0'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use Unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'uuid'

View File

@@ -0,0 +1,171 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.2.0)
actionpack (= 4.2.0)
actionview (= 4.2.0)
activejob (= 4.2.0)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.0)
actionview (= 4.2.0)
activesupport (= 4.2.0)
rack (~> 1.6.0)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.1)
actionview (4.2.0)
activesupport (= 4.2.0)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.1)
activejob (4.2.0)
activesupport (= 4.2.0)
globalid (>= 0.3.0)
activemodel (4.2.0)
activesupport (= 4.2.0)
builder (~> 3.1)
activerecord (4.2.0)
activemodel (= 4.2.0)
activesupport (= 4.2.0)
arel (~> 6.0)
activesupport (4.2.0)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
arel (6.0.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
byebug (3.5.1)
columnize (~> 0.8)
debugger-linecache (~> 1.2)
slop (~> 3.6)
coffee-rails (4.1.0)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
coffee-script (2.3.0)
coffee-script-source
execjs
coffee-script-source (1.8.0)
columnize (0.9.0)
debug_inspector (0.0.2)
debugger-linecache (1.2.0)
erubis (2.7.0)
execjs (2.2.2)
globalid (0.3.0)
activesupport (>= 4.1.0)
hike (1.2.3)
i18n (0.7.0)
jbuilder (2.2.6)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
jquery-rails (4.0.3)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (1.8.2)
loofah (2.0.1)
nokogiri (>= 1.5.9)
macaddr (1.7.1)
systemu (~> 2.6.2)
mail (2.6.3)
mime-types (>= 1.16, < 3)
mime-types (2.4.3)
mini_portile (0.6.2)
minitest (5.5.1)
multi_json (1.10.1)
nokogiri (1.6.6.1-x86-mingw32)
mini_portile (~> 0.6.0)
rack (1.6.0)
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.0)
actionmailer (= 4.2.0)
actionpack (= 4.2.0)
actionview (= 4.2.0)
activejob (= 4.2.0)
activemodel (= 4.2.0)
activerecord (= 4.2.0)
activesupport (= 4.2.0)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.0)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.5)
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.1)
loofah (~> 2.0)
railties (4.2.0)
actionpack (= 4.2.0)
activesupport (= 4.2.0)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (10.4.2)
rdoc (4.2.0)
json (~> 1.4)
sass (3.4.10)
sass-rails (5.0.1)
railties (>= 4.0.0, < 5.0)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (~> 1.1)
sdoc (0.4.1)
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)
slop (3.6.0)
sprockets (2.12.3)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.2.4)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
sqlite3 (1.3.10-x86-mingw32)
systemu (2.6.4)
thor (0.19.1)
thread_safe (0.3.4)
tilt (1.4.1)
turbolinks (2.5.3)
coffee-rails
tzinfo (1.2.2)
thread_safe (~> 0.1)
tzinfo-data (1.2014.10)
tzinfo (>= 1.0.0)
uglifier (2.7.0)
execjs (>= 0.3.0)
json (>= 1.8.0)
uuid (2.3.7)
macaddr (~> 1.0)
web-console (2.0.0)
activemodel (~> 4.0)
binding_of_caller (>= 0.7.2)
railties (~> 4.0)
sprockets-rails (>= 2.0, < 4.0)
PLATFORMS
x86-mingw32
DEPENDENCIES
byebug
coffee-rails (~> 4.1.0)
jbuilder (~> 2.0)
jquery-rails
rails (= 4.2.0)
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
sqlite3
turbolinks
tzinfo-data
uglifier (>= 1.3.0)
uuid
web-console (~> 2.0)

View File

@@ -0,0 +1,28 @@
== README
This README would normally document whatever steps are necessary to get the
application up and running.
Things you may want to cover:
* Ruby version
* System dependencies
* Configuration
* Database creation
* Database initialization
* How to run the test suite
* Services (job queues, cache servers, search engines, etc.)
* Deployment instructions
* ...
Please feel free to use a different markup language if you do not plan to run
<tt>rake doc:app</tt>.

View File

@@ -0,0 +1,6 @@
# 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.
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,13 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//= require_tree .

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,576 @@
/*!
* jQuery blockUI plugin
* Version 2.55 (18-JAN-2013)
* @requires jQuery v1.7 or later
*
* Examples at: http://malsup.com/jquery/block/
* Copyright (c) 2007-2013 M. Alsup
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Thanks to Amir-Hossein Sobhi for some excellent contributions!
*/
;(function() {
"use strict";
function setup($) {
$.fn._fadeIn = $.fn.fadeIn;
var noOp = $.noop || function() {};
// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
// retarded userAgent strings on Vista)
var msie = /MSIE/.test(navigator.userAgent);
var ie6 = /MSIE 6.0/.test(navigator.userAgent);
var mode = document.documentMode || 0;
// var setExpr = msie && (($.browser.version < 8 && !mode) || mode < 8);
var setExpr = $.isFunction( document.createElement('div').style.setExpression );
// global $ methods for blocking/unblocking the entire page
$.blockUI = function(opts) { install(window, opts); };
$.unblockUI = function(opts) { remove(window, opts); };
// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
$.growlUI = function(title, message, timeout, onClose) {
var $m = $('<div class="growlUI"></div>');
if (title) $m.append('<h1>'+title+'</h1>');
if (message) $m.append('<h2>'+message+'</h2>');
if (timeout === undefined) timeout = 3000;
$.blockUI({
message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
timeout: timeout, showOverlay: false,
onUnblock: onClose,
css: $.blockUI.defaults.growlCSS
});
};
// plugin method for blocking element content
$.fn.block = function(opts) {
var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
this.each(function() {
var $el = $(this);
if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
return;
$el.unblock({ fadeOut: 0 });
});
return this.each(function() {
if ($.css(this,'position') == 'static') {
this.style.position = 'relative';
$(this).data('blockUI.static', true);
}
this.style.zoom = 1; // force 'hasLayout' in ie
install(this, opts);
});
};
// plugin method for unblocking element content
$.fn.unblock = function(opts) {
return this.each(function() {
remove(this, opts);
});
};
$.blockUI.version = 2.55; // 2nd generation blocking at no extra cost!
// override these in your code to change the default behavior and style
$.blockUI.defaults = {
// message displayed when blocking (use null for no message)
message: '<h1>Please wait...</h1>',
title: null, // title string; only used when theme == true
draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
theme: false, // set to true to use with jQuery UI themes
// styles for the message when blocking; if you wish to disable
// these and use an external stylesheet then do this in your code:
// $.blockUI.defaults.css = {};
css: {
padding: 0,
margin: 0,
width: '30%',
top: '40%',
left: '35%',
textAlign: 'center',
color: '#000',
border: '3px solid #aaa',
backgroundColor:'#fff',
cursor: 'wait'
},
// minimal style set used when themes are used
themedCSS: {
//width: '30%',
top: '20%',
left: '50%',
marginLeft: "-325px"
},
// styles for the overlay
overlayCSS: {
backgroundColor: '#000',
opacity: 0.6,
cursor: 'wait'
},
// style to replace wait cursor before unblocking to correct issue
// of lingering wait cursor
cursorReset: 'default',
// styles applied when using $.growlUI
growlCSS: {
width: '350px',
top: '10px',
left: '',
right: '10px',
border: 'none',
padding: '5px',
opacity: 0.6,
cursor: 'default',
color: '#fff',
backgroundColor: '#000',
'-webkit-border-radius':'10px',
'-moz-border-radius': '10px',
'border-radius': '10px'
},
// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
// (hat tip to Jorge H. N. de Vasconcelos)
/*jshint scripturl:true */
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
// force usage of iframe in non-IE browsers (handy for blocking applets)
forceIframe: false,
// z-index for the blocking overlay
baseZ: 1000,
// set these to true to have the message automatically centered
centerX: true, // <-- only effects element blocking (page block controlled via css above)
centerY: true,
// allow body element to be stetched in ie6; this makes blocking look better
// on "short" pages. disable if you wish to prevent changes to the body height
allowBodyStretch: true,
// enable if you want key and mouse events to be disabled for content that is blocked
bindEvents: true,
// be default blockUI will supress tab navigation from leaving blocking content
// (if bindEvents is true)
constrainTabKey: true,
// fadeIn time in millis; set to 0 to disable fadeIn on block
fadeIn: 200,
// fadeOut time in millis; set to 0 to disable fadeOut on unblock
fadeOut: 400,
// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
timeout: 0,
// disable if you don't want to show the overlay
showOverlay: true,
// if true, focus will be placed in the first available input field when
// page blocking
focusInput: true,
// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
// no longer needed in 2012
// applyPlatformOpacityRules: true,
// callback method invoked when fadeIn has completed and blocking message is visible
onBlock: null,
// callback method invoked when unblocking has completed; the callback is
// passed the element that has been unblocked (which is the window object for page
// blocks) and the options that were passed to the unblock call:
// onUnblock(element, options)
onUnblock: null,
// callback method invoked when the overlay area is clicked.
// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
onOverlayClick: null,
// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
quirksmodeOffsetHack: 4,
// class name of the message block
blockMsgClass: 'blockMsg',
// if it is already blocked, then ignore it (don't unblock and reblock)
ignoreIfBlocked: false
};
// private data and functions follow...
var pageBlock = null;
var pageBlockEls = [];
function install(el, opts) {
var css, themedCSS;
var full = (el == window);
var msg = (opts && opts.message !== undefined ? opts.message : undefined);
opts = $.extend({}, $.blockUI.defaults, opts || {});
if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
return;
opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
if (opts.onOverlayClick)
opts.overlayCSS.cursor = 'pointer';
themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
msg = msg === undefined ? opts.message : msg;
// remove the current block (if there is one)
if (full && pageBlock)
remove(window, {fadeOut:0});
// if an existing element is being used as the blocking content then we capture
// its current place in the DOM (and current display style) so we can restore
// it when we unblock
if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
var node = msg.jquery ? msg[0] : msg;
var data = {};
$(el).data('blockUI.history', data);
data.el = node;
data.parent = node.parentNode;
data.display = node.style.display;
data.position = node.style.position;
if (data.parent)
data.parent.removeChild(node);
}
$(el).data('blockUI.onUnblock', opts.onUnblock);
var z = opts.baseZ;
// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
// layer1 is the iframe layer which is used to supress bleed through of underlying content
// layer2 is the overlay layer which has opacity and a wait cursor (by default)
// layer3 is the message content that is displayed while blocking
var lyr1, lyr2, lyr3, s;
if (msie || opts.forceIframe)
lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
else
lyr1 = $('<div class="blockUI" style="display:none"></div>');
if (opts.theme)
lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
else
lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
if (opts.theme && full) {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
if ( opts.title ) {
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
}
s += '<div class="ui-widget-content ui-dialog-content"></div>';
s += '</div>';
}
else if (opts.theme) {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
if ( opts.title ) {
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
}
s += '<div class="ui-widget-content ui-dialog-content"></div>';
s += '</div>';
}
else if (full) {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
}
else {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
}
lyr3 = $(s);
// if we have a message, style it
if (msg) {
if (opts.theme) {
lyr3.css(themedCSS);
lyr3.addClass('ui-widget-content');
}
else
lyr3.css(css);
}
// style the overlay
if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
lyr2.css(opts.overlayCSS);
lyr2.css('position', full ? 'fixed' : 'absolute');
// make iframe layer transparent in IE
if (msie || opts.forceIframe)
lyr1.css('opacity',0.0);
//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
$.each(layers, function() {
this.appendTo($par);
});
if (opts.theme && opts.draggable && $.fn.draggable) {
lyr3.draggable({
handle: '.ui-dialog-titlebar',
cancel: 'li'
});
}
// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
if (ie6 || expr) {
// give body 100% height
if (full && opts.allowBodyStretch && $.support.boxModel)
$('html,body').css('height','100%');
// fix ie6 issue when blocked element has a border width
if ((ie6 || !$.support.boxModel) && !full) {
var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
var fixT = t ? '(0 - '+t+')' : 0;
var fixL = l ? '(0 - '+l+')' : 0;
}
// simulate fixed position
$.each(layers, function(i,o) {
var s = o[0].style;
s.position = 'absolute';
if (i < 2) {
if (full)
s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
else
s.setExpression('height','this.parentNode.offsetHeight + "px"');
if (full)
s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
else
s.setExpression('width','this.parentNode.offsetWidth + "px"');
if (fixL) s.setExpression('left', fixL);
if (fixT) s.setExpression('top', fixT);
}
else if (opts.centerY) {
if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
s.marginTop = 0;
}
else if (!opts.centerY && full) {
var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
s.setExpression('top',expression);
}
});
}
// show the message
if (msg) {
if (opts.theme)
lyr3.find('.ui-widget-content').append(msg);
else
lyr3.append(msg);
if (msg.jquery || msg.nodeType)
$(msg).show();
}
if ((msie || opts.forceIframe) && opts.showOverlay)
lyr1.show(); // opacity is zero
if (opts.fadeIn) {
var cb = opts.onBlock ? opts.onBlock : noOp;
var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
var cb2 = msg ? cb : noOp;
if (opts.showOverlay)
lyr2._fadeIn(opts.fadeIn, cb1);
if (msg)
lyr3._fadeIn(opts.fadeIn, cb2);
}
else {
if (opts.showOverlay)
lyr2.show();
if (msg)
lyr3.show();
if (opts.onBlock)
opts.onBlock();
}
// bind key and mouse events
bind(1, el, opts);
if (full) {
pageBlock = lyr3[0];
pageBlockEls = $(':input:enabled:visible',pageBlock);
if (opts.focusInput)
setTimeout(focus, 20);
}
else
center(lyr3[0], opts.centerX, opts.centerY);
if (opts.timeout) {
// auto-unblock
var to = setTimeout(function() {
if (full)
$.unblockUI(opts);
else
$(el).unblock(opts);
}, opts.timeout);
$(el).data('blockUI.timeout', to);
}
}
// remove the block
function remove(el, opts) {
var full = (el == window);
var $el = $(el);
var data = $el.data('blockUI.history');
var to = $el.data('blockUI.timeout');
if (to) {
clearTimeout(to);
$el.removeData('blockUI.timeout');
}
opts = $.extend({}, $.blockUI.defaults, opts || {});
bind(0, el, opts); // unbind events
if (opts.onUnblock === null) {
opts.onUnblock = $el.data('blockUI.onUnblock');
$el.removeData('blockUI.onUnblock');
}
var els;
if (full) // crazy selector to handle odd field errors in ie6/7
els = $('body').children().filter('.blockUI').add('body > .blockUI');
else
els = $el.find('>.blockUI');
// fix cursor issue
if ( opts.cursorReset ) {
if ( els.length > 1 )
els[1].style.cursor = opts.cursorReset;
if ( els.length > 2 )
els[2].style.cursor = opts.cursorReset;
}
if (full)
pageBlock = pageBlockEls = null;
if (opts.fadeOut) {
els.fadeOut(opts.fadeOut);
setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
}
else
reset(els, data, opts, el);
}
// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
var $el = $(el);
els.each(function(i,o) {
// remove via DOM calls so we don't lose event handlers
if (this.parentNode)
this.parentNode.removeChild(this);
});
if (data && data.el) {
data.el.style.display = data.display;
data.el.style.position = data.position;
if (data.parent)
data.parent.appendChild(data.el);
$el.removeData('blockUI.history');
}
if ($el.data('blockUI.static')) {
$el.css('position', 'static'); // #22
}
if (typeof opts.onUnblock == 'function')
opts.onUnblock(el,opts);
// fix issue in Safari 6 where block artifacts remain until reflow
var body = $(document.body), w = body.width(), cssW = body[0].style.width;
body.width(w-1).width(w);
body[0].style.width = cssW;
}
// bind/unbind the handler
function bind(b, el, opts) {
var full = el == window, $el = $(el);
// don't bother unbinding if there is nothing to unbind
if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
return;
$el.data('blockUI.isBlocked', b);
// don't bind events when overlay is not in use or if bindEvents is false
if (!opts.bindEvents || (b && !opts.showOverlay))
return;
// bind anchors and inputs for mouse and key events
var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
if (b)
$(document).bind(events, opts, handler);
else
$(document).unbind(events, handler);
// former impl...
// var $e = $('a,:input');
// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
}
// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
// allow tab navigation (conditionally)
if (e.keyCode && e.keyCode == 9) {
if (pageBlock && e.data.constrainTabKey) {
var els = pageBlockEls;
var fwd = !e.shiftKey && e.target === els[els.length-1];
var back = e.shiftKey && e.target === els[0];
if (fwd || back) {
setTimeout(function(){focus(back);},10);
return false;
}
}
}
var opts = e.data;
var target = $(e.target);
if (target.hasClass('blockOverlay') && opts.onOverlayClick)
opts.onOverlayClick();
// allow events within the message content
if (target.parents('div.' + opts.blockMsgClass).length > 0)
return true;
// allow events for content that is not being blocked
return target.parents().children().filter('div.blockUI').length === 0;
}
function focus(back) {
if (!pageBlockEls)
return;
var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
if (e)
e.focus();
}
function center(el, x, y) {
var p = el.parentNode, s = el.style;
var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
if (x) s.left = l > 0 ? (l+'px') : '0';
if (y) s.top = t > 0 ? (t+'px') : '0';
}
function sz(el, p) {
return parseInt($.css(el,p),10)||0;
}
}
/*global define:true */
if (typeof define === 'function' && define.amd && define.amd.jQuery) {
define(['jquery'], setup);
} else {
setup(jQuery);
}
})();

View File

@@ -0,0 +1,124 @@
;(function() {
var
dropdownToggleHash = {};
jQuery.extend({
dropdownToggle: function(options) {
// default options
options = jQuery.extend({
//switcherSelector: "#id" or ".class", - button
//dropdownID: "id", - drop panel
//anchorSelector: "#id" or ".class", - near field
//noActiveSwitcherSelector: "#id" or ".class", - dont hide
addTop: 0,
addLeft: 0,
position: "absolute",
fixWinSize: true,
enableAutoHide: true,
showFunction: null,
afterShowFunction: null,
hideFunction: null,
alwaysUp: false,
simpleToggle: false,
rightPos: false
}, options);
var _toggle = function(switcherObj, dropdownID, addTop, addLeft, fixWinSize, position, anchorSelector, showFunction, alwaysUp, simpleToggle, afterShowFunction) {
var dropdownItem = jq("#" + dropdownID);
if (typeof (simpleToggle) == "undefined" || simpleToggle === false) {
fixWinSize = fixWinSize === true;
addTop = addTop || 0;
addLeft = addLeft || 0;
position = position || "absolute";
var targetPos = jq(anchorSelector || switcherObj).offset();
if (!targetPos) return;
var elemPosLeft = targetPos.left;
var elemPosTop = targetPos.top + jq(anchorSelector || switcherObj).outerHeight();
if (options.rightPos) {
elemPosLeft = Math.max(0,targetPos.left - dropdownItem.outerWidth() + jq(anchorSelector || switcherObj).outerWidth());
}
var w = jq(window);
var topPadding = w.scrollTop();
var leftPadding = w.scrollLeft();
if (position == "fixed") {
addTop -= topPadding;
addLeft -= leftPadding;
}
var scrWidth = w.width();
var scrHeight = w.height();
if (fixWinSize && (!options.rightPos)
&& (targetPos.left + addLeft + dropdownItem.outerWidth()) > (leftPadding + scrWidth)) {
elemPosLeft = Math.max(0, leftPadding + scrWidth - dropdownItem.outerWidth()) - addLeft;
}
if (fixWinSize
&& (elemPosTop + dropdownItem.outerHeight()) > (topPadding + scrHeight)
&& (targetPos.top - dropdownItem.outerHeight()) > topPadding
|| alwaysUp) {
elemPosTop = targetPos.top - dropdownItem.outerHeight();
}
dropdownItem.css(
{
"position": position,
"top": elemPosTop + addTop,
"left": elemPosLeft + addLeft
});
}
if (typeof showFunction === "function") {
showFunction(switcherObj, dropdownItem);
}
dropdownItem.toggle();
if (typeof afterShowFunction === "function") {
afterShowFunction(switcherObj, dropdownItem);
}
};
var _registerAutoHide = function(event, switcherSelector, dropdownSelector, hideFunction) {
if (jq(dropdownSelector).is(":visible")) {
var $targetElement = jq((event.target) ? event.target : event.srcElement);
if (!$targetElement.parents().andSelf().is(switcherSelector + ", " + dropdownSelector)) {
if (typeof hideFunction === "function")
hideFunction($targetElement);
jq(dropdownSelector).hide();
}
}
};
if (options.switcherSelector && options.dropdownID) {
var toggleFunc = function(e) {
_toggle(jq(this), options.dropdownID, options.addTop, options.addLeft, options.fixWinSize, options.position, options.anchorSelector, options.showFunction, options.alwaysUp, options.simpleToggle, options.afterShowFunction);
};
if (!dropdownToggleHash.hasOwnProperty(options.switcherSelector + options.dropdownID)) {
jq(document).on("click", options.switcherSelector, toggleFunc);
dropdownToggleHash[options.switcherSelector + options.dropdownID] = true;
}
}
if (options.enableAutoHide && options.dropdownID) {
var hideFunc = function(e) {
var allSwitcherSelectors = options.noActiveSwitcherSelector ?
options.switcherSelector + ", " + options.noActiveSwitcherSelector : options.switcherSelector;
_registerAutoHide(e, allSwitcherSelectors, "#" + options.dropdownID, options.hideFunction);
};
jq(document).unbind("click", hideFunc);
jq(document).bind("click", hideFunc);
}
return {
toggle: _toggle,
registerAutoHide: _registerAutoHide
};
}
});
})();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,142 @@
/*
* jQuery Iframe Transport Plugin 1.2
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://creativecommons.org/licenses/MIT/
*/
/*jslint unparam: true */
/*global jQuery */
(function ($) {
'use strict';
// Helper variable to create unique names for the transport iframes:
var counter = 0;
// The iframe transport accepts three additional options:
// options.fileInput: a jQuery collection of file input fields
// options.paramName: the parameter name for the file form data,
// overrides the name property of the file input field(s)
// options.formData: an array of objects with name and value properties,
// equivalent to the return data of .serializeArray(), e.g.:
// [{name: a, value: 1}, {name: b, value: 2}]
$.ajaxTransport('iframe', function (options, originalOptions, jqXHR) {
if (options.type === 'POST' || options.type === 'GET') {
var form,
iframe;
return {
send: function (headers, completeCallback) {
form = $('<form style="display:none;"></form>');
// javascript:false as initial iframe src
// prevents warning popups on HTTPS in IE6.
// IE versions below IE8 cannot set the name property of
// elements that have already been added to the DOM,
// so we set the name along with the iframe HTML markup:
iframe = $(
'<iframe src="javascript:false;" name="iframe-transport-' +
(counter += 1) + '"></iframe>'
).bind('load', function () {
var fileInputClones;
iframe
.unbind('load')
.bind('load', function () {
// The complete callback returns the
// iframe content document as response object:
completeCallback(
200,
'success',
{'iframe': iframe.contents()}
);
// Fix for IE endless progress bar activity bug
// (happens on form submits to iframe targets):
$('<iframe src="javascript:false;"></iframe>')
.appendTo(form);
form.remove();
});
form
.prop('target', iframe.prop('name'))
.prop('action', options.url)
.prop('method', options.type);
if (options.formData) {
$.each(options.formData, function (index, field) {
$('<input type="hidden"/>')
.prop('name', field.name)
.val(field.value)
.appendTo(form);
});
}
if (options.fileInput && options.fileInput.length &&
options.type === 'POST') {
fileInputClones = options.fileInput.clone();
// Insert a clone for each file input field:
options.fileInput.after(function (index) {
return fileInputClones[index];
});
if (options.paramName) {
options.fileInput.each(function () {
$(this).prop('name', options.paramName);
});
}
// Appending the file input fields to the hidden form
// removes them from their original location:
form
.append(options.fileInput)
.prop('enctype', 'multipart/form-data')
// enctype must be set as encoding for IE:
.prop('encoding', 'multipart/form-data');
}
form.submit();
// Insert the file input fields at their original location
// by replacing the clones with the originals:
if (fileInputClones && fileInputClones.length) {
options.fileInput.each(function (index, input) {
var clone = $(fileInputClones[index]);
$(input).prop('name', clone.prop('name'));
clone.replaceWith(input);
});
}
});
form.append(iframe).appendTo('body');
},
abort: function () {
if (iframe) {
// javascript:false as iframe src aborts the request
// and prevents warning popups on HTTPS in IE6.
// concat is used to avoid the "Script URL" JSLint error:
iframe
.unbind('load')
.prop('src', 'javascript'.concat(':false;'));
}
if (form) {
form.remove();
}
}
};
}
});
// The iframe transport returns the iframe content document as response.
// The following adds converters from iframe to text, json, html, and script:
$.ajaxSetup({
converters: {
'iframe text': function (iframe) {
return iframe.text();
},
'iframe json': function (iframe) {
return $.parseJSON(iframe.text());
},
'iframe html': function (iframe) {
return iframe.find('body').html();
},
'iframe script': function (iframe) {
return $.globalEval(iframe.text());
}
}
});
}(jQuery));

View File

@@ -0,0 +1,179 @@
/*
Copyright (c) Ascensio System SIA 2014. All rights reserved.
http://www.onlyoffice.com
*/
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
add: function (e, data) {
jq(".error").removeClass("error");
jq(".done").removeClass("done");
jq(".current").removeClass("current");
jq("#step1").addClass("current");
jq("#mainProgress .error-message").hide().find("span").text("");
jq("#mainProgress").removeClass("embedded");
jq.blockUI({
theme: true,
title: "Getting ready to load the file" + "<div class=\"dialog-close\"></div>",
message: jq("#mainProgress"),
overlayCSS: { "background-color": "#aaa" },
themedCSS: { width: "656px", top: "20%", left: "50%", marginLeft: "-328px" }
});
jq("#beginEdit, #beginView, #beginEmbedded").addClass("disable");
data.submit();
},
always: function (e, data) {
if (!jq("#mainProgress").is(":visible")) {
return;
}
var response = data.result;
if (response.error) {
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
jq('#hiddenFileName').val("");
return;
}
jq("#hiddenFileName").val(response.filename);
jq("#step1").addClass("done").removeClass("current");
jq("#step2").addClass("current");
checkConvert();
}
});
});
var timer = null;
var checkConvert = function () {
if (timer != null) {
clearTimeout(timer);
}
if (!jq("#mainProgress").is(":visible")) {
return;
}
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (ConvertExtList.indexOf(posExt) == -1) {
loadScripts();
return;
}
if (jq("#checkOriginalFormat").is(":checked")) {
loadScripts();
return;
}
timer = setTimeout(function () {
var requestAddress = UrlConverter
+ "?filename=" + encodeURIComponent(jq("#hiddenFileName").val());
jq.ajax({
async: true,
contentType: "text/xml",
type: "get",
url: requestAddress,
complete: function (data) {
var responseText = data.responseText;
var response = jq.parseJSON(responseText);
if (response.error) {
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
jq('#hiddenFileName').val("");
return;
}
jq("#hiddenFileName").val(response.filename);
if (response.step && response.step < 100) {
checkConvert();
} else {
loadScripts();
}
}
});
}, 1000);
};
var loadScripts = function () {
if (!jq("#mainProgress").is(":visible")) {
return;
}
jq("#step2").addClass("done").removeClass("current");
jq("#step3").addClass("current");
if (jq("#loadScripts").is(":empty")) {
var urlScripts = jq("#loadScripts").attr("data-docs");
var frame = '<iframe id="iframeScripts" width=1 height=1 style="position: absolute; visibility: hidden;" ></iframe>';
jq("#loadScripts").html(frame);
document.getElementById("iframeScripts").onload = onloadScripts;
jq("#loadScripts iframe").attr("src", urlScripts);
} else {
onloadScripts();
}
};
var onloadScripts = function () {
if (!jq("#mainProgress").is(":visible")) {
return;
}
jq("#step3").addClass("done").removeClass("current");
jq("#beginView, #beginEmbedded").removeClass("disable");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (EditedExtList.indexOf(posExt) != -1) {
jq("#beginEdit").removeClass("disable");
}
};
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?fileName=" + fileId;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
});
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?mode=view&fileName=" + fileId;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
});
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?mode=embedded&fileName=" + fileId;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
jq("#embeddedView").attr("src", url);
});
jq(document).on("click", "#cancelEdit, .dialog-close", function () {
jq('#hiddenFileName').val("");
jq("#embeddedView").attr("src", "");
jq.unblockUI();
});
jq.dropdownToggle({
switcherSelector: ".question",
dropdownID: "hint"
});
}

View File

@@ -0,0 +1,15 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any styles
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
* file per style scope.
*
*= require_tree .
*= require_self
*/

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) Ascensio System SIA 2014. All rights reserved.
http://www.onlyoffice.com
*/
html {
height: 100%;
width: 100%;
}
body {
background: #fff;
color: #333;
font-family: Arial, Tahoma,sans-serif;
font-size: 12px;
font-weight: normal;
height: 100%;
margin: 0;
overflow-y: hidden;
padding: 0;
text-decoration: none;
}
.form {
height: 100%;
}
div {
margin: 0;
padding: 0;
}

View File

@@ -0,0 +1,464 @@
/*! jQuery UI - v1.9.2 - 2012-11-23
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css
* Copyright 2012 jQuery Foundation and other contributors; Licensed MIT */
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
.ui-autocomplete {
position: absolute;
top: 0;
left: 0;
cursor: default;
}
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}
.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 650px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
.ui-menu .ui-menu-item a.ui-state-focus,
.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
.ui-menu .ui-state-disabled a { cursor: default; }
/* icon support */
.ui-menu-icons { position: relative; }
.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
/* left-aligned */
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
/* right-aligned */
.ui-menu .ui-menu-icon { position: static; float: right; }
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }
.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
.ui-spinner-up { top: 0; }
.ui-spinner-down { bottom: 0; }
/* TR overrides */
.ui-spinner .ui-icon-triangle-1-s {
/* need to fix icons sprite */
background-position:-65px -16px;
}
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tooltip {
padding: 8px;
position: absolute;
z-index: 9999;
max-width: 300px;
-webkit-box-shadow: 0 0 5px #aaa;
box-shadow: 0 0 5px #aaa;
}
/* Fades and background-images don't work well together in IE6, drop the image */
* html .ui-tooltip {
background-image: none;
}
body .ui-tooltip { border-width: 2px; }
/* Component containers
----------------------------------*/
.ui-widget { font-family: 'Open Sans',sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: 'Open Sans',sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff 50% 50% repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
/* Icons
----------------------------------*/
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }

View File

@@ -0,0 +1,311 @@
/*
Copyright (c) Ascensio System SIA 2014. All rights reserved.
http://www.onlyoffice.com
*/
html {
height: 100%;
width: 100%;
}
body {
background: #fff;
color: #333;
font-family: 'Open Sans', Tahoma,sans-serif;
font-size: 12px;
font-weight: normal;
height: 100%;
margin: 0;
padding: 0;
text-decoration: none;
}
form {
height: 100%;
}
div {
margin: 0;
padding: 0;
}
a, a:hover, a:visited {
color: #333;
}
.top-panel {
background: url("logo.png") no-repeat 30px center #3D4A6B;
height: 80px;
width: 100%;
}
.main-panel {
margin: 80px auto;
width: 600px;
}
.portal-name {
font-size: 20px;
}
.portal-descr {
display: inline-block;
line-height: 20px;
margin-bottom: 24px;
width: 600px;
}
.save-original {
color: #929597;
line-height: 20px;
margin-left: 16px;
white-space: nowrap;
width: 272px;
}
.question {
background: url("question_small.png") no-repeat center center transparent;
cursor: pointer;
display: inline-block;
height: 16px;
width: 16px;
}
#hint {
background-color: #FFFFFF;
border: 1px solid #8E908F;
display: none;
margin: 4px 0 0 -32px;
max-width: 415px;
padding: 10px 15px 15px;
word-wrap: break-word;
z-index: 255;
}
.corner {
background: url("corner.png") no-repeat scroll 0 0 transparent;
height: 6px;
left: 35px;
margin-top: -15px;
position: absolute;
width: 9px;
z-index: 261;
}
.try-descr {
font-size: 16px;
white-space : nowrap;
}
.try-editor-list {
list-style: none;
margin: 0;
padding: 0;
}
.try-editor-list li {
float: left;
margin: 25px;
}
.try-editor {
background-color: transparent;
background-position: center 0;
background-repeat: no-repeat;
display: block;
font-size: 14px;
font-weight: bold;
height: 30px;
padding-top: 100px;
text-decoration: none;
}
.try-editor.document {
background-image: url("file_doct.png");
}
.try-editor.spreadsheet {
background-image: url("file_xlst.png");
}
.try-editor.presentation {
background-image: url("file_pptt.png");
}
.button, .button:visited, .button:hover, .button:active {
display: inline-block;
font-weight: normal;
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor:pointer;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
touch-callout: none;
-o-touch-callout: none;
-moz-touch-callout: none;
-webkit-touch-callout: none;
user-select: none;
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
font-size: 12px;
line-height: 16px;
margin-right: 3px;
padding: 2px 12px;
color: #fff;
background: #3D96C6;
background: linear-gradient(top, #59B1E2, #3D96C6 50%, #3D96C6 51%, #1A76a6);
background: -o-linear-gradient(top, #59B1E2, #3D96C6 50%, #3D96C6 51%, #1A76a6);
background: -moz-linear-gradient(top, #59B1E2, #3D96C6 50%, #3D96C6 51%, #1A76a6);
background: -webkit-linear-gradient(top, #59B1E2, #3D96C6 50%, #3D96C6 51%, #1A76a6);
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#59B1E2', EndColorStr='#1A76a6')";
border-width: 1px;
border-style: solid;
border-color: #4da9dc #4098c9 #2d7399 #4098c9;
}
.button.disable {
cursor: default;
background: #BADDEF;
background: linear-gradient(top, #CEE9F6, #BADDEF 50%, #BADDEF 51%, #ABD4EA);
background: -o-linear-gradient(top, #CEE9F6, #BADDEF 50%, #BADDEF 51%, #ABD4EA);
background: -moz-linear-gradient(top, #CEE9F6, #BADDEF 50%, #BADDEF 51%, #ABD4EA);
background: -webkit-linear-gradient(top, #CEE9F6, #BADDEF 50%, #BADDEF 51%, #ABD4EA);
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#CEE9F6', EndColorStr='#ABD4EA')";
border: 1px solid #BCDCED;
}
.button.gray {
color: #666;
background: #E9EAEA;
background: linear-gradient(top, #F3F3F3, #E9EAEA 50%, #E8E9E9 51%, #DEDEDE);
background: -o-linear-gradient(top, #F3F3F3, #E9EAEA 50%, #E8E9E9 51%, #DEDEDE);
background: -moz-linear-gradient(top, #F3F3F3, #E9EAEA 50%, #E8E9E9 51%, #DEDEDE);
background: -webkit-linear-gradient(top, #F3F3F3, #E9EAEA 50%, #E8E9E9 51%, #DEDEDE);
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#F3F3F3', EndColorStr='#DEDEDE')";
border: 1px solid #BFBFBF;
}
.file-upload {
cursor: pointer;
margin-bottom: 8px;
padding: 0 !important;
overflow: hidden;
position: relative;
}
.file-upload span {
line-height: 21px;
margin: 2px 12px;
}
.file-upload input {
cursor: pointer;
font-size: 23px;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transform: translate(-300px, 0) scale(4);
}
#mainProgress {
color: #979b9f;
display: none;
margin: 15px;
}
#mainProgress #embeddedView {
display: none;
}
#mainProgress.embedded #embeddedView {
display: block;
}
#mainProgress.embedded #uploadSteps {
display: none;
}
.error-message {
background: url("alert.png") no-repeat scroll 4px 10px #FFECE3;
color: #666668 !important;
display: none;
font-size: 13px;
font-weight: normal;
margin: 5px 0;
padding: 10px 10px 10px 30px;
vertical-align: middle;
}
#mainProgress .error-message a {
color: #666668;
}
.step {
background-repeat: no-repeat;
background-position: left center;
background-color: transparent;
color: #979B9F;
font-size: 14px;
line-height: 30px;
padding-left: 25px;
}
.current {
background-image: url("loader16.gif");
color: #333;
}
.done {
background-image: url("done.png");
color: #333;
}
.error {
background-image: url("alert.png");
}
.step-descr {
display: block;
margin-left: 45px;
}
#mainProgress .step-descr a {
color: #979B9F;
}
.progress-descr {
color: #333;
}
#loadScripts {
display: none;
}
#iframeScripts {
position: absolute;
visibility: hidden;
}
.bottom-panel {
bottom: 0;
position: fixed;
text-align: right;
width: 100%;
}
.help-block span {
font-size: 16px;
line-height: 26px;
}
.button.sample {
color: #333;
font-weight: bold;
}
.blockTitle {
background-color: #E2E2E2 !important;
border: none !important;
border-radius: 0 !important;
-moz-border-radius: 0 !important;
-webkit-border-radius: 0 !important;
color: #333 !important;
font-size: 16px !important;
font-weight: normal !important;
padding: 15px 25px !important;
}
.dialog-close {
background: url("close.png") no-repeat scroll left top #E2E2E2;
cursor: pointer;
float: right;
font-size: 1px;
height: 12px;
line-height: 1px;
margin-top: 4px;
width: 12px;
}
.blockPage {
border: none !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
-moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.5);
padding: 0 !important;
}

View File

@@ -0,0 +1,2 @@
class ApplicationController < ActionController::Base
end

View File

@@ -0,0 +1,219 @@
class HomeController < ApplicationController
def index
end
def editor
DocumentHelper.init(request.remote_ip, request.base_url)
@file = FileModel.new(:file_name => params[:fileName], :mode => params[:mode], :user_ip => request.remote_ip)
end
def sample
DocumentHelper.init(request.remote_ip, request.base_url)
file_name = DocumentHelper.create_demo(params[:fileExt])
redirect_to :controller => 'home', :action => 'editor', :fileName => file_name
end
def upload
DocumentHelper.init(request.remote_ip, request.base_url)
begin
http_posted_file = params[:file]
file_name = http_posted_file.original_filename
cur_size = http_posted_file.size
if DocumentHelper.file_size_max < cur_size || cur_size <= 0
raise 'File size is incorrect'
end
cur_ext = File.extname(file_name).downcase
unless DocumentHelper.file_exts.include? cur_ext
raise 'File type is not supported'
end
file_name = DocumentHelper.get_correct_name(file_name)
File.open(DocumentHelper.storage_path(file_name, nil), 'wb') do |file|
file.write(http_posted_file.read)
end
render :text => '{ "filename": "' + file_name + '"}'
rescue => ex
render :text => '{ "error": "' + ex.message + '"}'
end
end
def convert
begin
file_name = params[:filename]
file_uri = DocumentHelper.get_file_uri(file_name)
extension = File.extname(file_name)
internal_extension = DocumentHelper.get_internal_extension(FileUtility.get_file_type(file_name))
if DocumentHelper.convert_exts.include? (extension)
key = ServiceConverter.generate_revision_id(file_uri)
percent, new_file_uri = ServiceConverter.get_converted_uri(file_uri, extension.delete('.'), internal_extension.delete('.'), key, true)
if percent != 100
render :text => '{ "step" : "' + percent.to_s + '", "filename" : "' + file_name + '"}'
return
end
correct_name = DocumentHelper.get_correct_name(File.basename(file_name, extension) + internal_extension)
uri = URI.parse(new_file_uri)
http = Net::HTTP.new(uri.host, uri.port)
if new_file_uri.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
data = res.body
if data == nil
raise 'stream is null'
end
File.open(DocumentHelper.storage_path(correct_name, nil), 'wb') do |file|
file.write(data)
end
file_name = correct_name
end
render :text => '{ "filename" : "' + file_name + '"}'
rescue => ex
render :text => '{ "error": "' + ex.message + '"}'
end
end
def save
download_uri = params[:fileuri]
file_name = params[:filename]
if download_uri == nil || file_name == nil || download_uri.empty? || file_name.empty?
render :text => 'error'
return
end
new_type = File.extname(download_uri).delete('.')
current_type = (params[:filetype] == nil ? File.extname(file_name) : params[:filetype]).delete('.')
if new_type.downcase != current_type.downcase
key = ServiceConverter.generate_revision_id(download_uri)
begin
result, new_file_uri = ServiceConverter.get_converted_uri(download_uri, new_type, current_type, key, false)
if result != 100
raise 'error'
end
rescue
render :text => 'error'
return
end
download_uri = new_file_uri
new_type = current_type
end
file_name = File.basename(file_name, current_type) + new_type
begin
uri = URI.parse(download_uri)
http = Net::HTTP.new(uri.host, uri.port)
if download_uri.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
data = res.body
if data == nil
raise 'stream is null'
end
File.open(DocumentHelper.storage_path(file_name, nil), 'wb') do |file|
file.write(data)
end
rescue
render :text => 'error'
return
end
render :text => 'success'
end
def track
user_address = params[:userAddress]
file_name = params[:fileName]
storage_path = DocumentHelper.storage_path(file_name, user_address)
body = request.body.read
if body == nil || body.empty?
return
end
file_data = JSON.parse(body)
status = file_data['status'].to_i
if status == 2 || status == 3 #MustSave, Corrupted
saved = 1
begin
download_uri = file_data['url']
uri = URI.parse(download_uri)
http = Net::HTTP.new(uri.host, uri.port)
if download_uri.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
data = res.body
if data == nil
raise 'stream is null'
end
File.open(storage_path, 'wb') do |file|
file.write(data)
end
rescue
saved = 0
end
render :text => '{"c":"saved","status":' + saved.to_s + '}'
end
end
end

View File

@@ -0,0 +1,2 @@
module ApplicationHelper
end

View File

@@ -0,0 +1,2 @@
module HomeHelper
end

View File

@@ -0,0 +1,150 @@
class DocumentHelper
@@runtime_cache = {}
@@remote_ip = nil
@@base_url = nil
class << self
def init (ip, url)
@@remote_ip = ip
@@base_url = url
end
def file_size_max
if Rails.configuration.fileSizeMax == nil
5 * 1024 * 1024
else
Rails.configuration.fileSizeMax
end
end
def file_exts
[].concat(viewed_exts).concat(edited_exts).concat(convert_exts)
end
def viewed_exts
if Rails.configuration.viewedDocs.empty?
[]
else
Rails.configuration.viewedDocs.split("|")
end
end
def edited_exts
if Rails.configuration.editedDocs.empty?
[]
else
Rails.configuration.editedDocs.split("|")
end
end
def convert_exts
if Rails.configuration.convertDocs.empty?
[]
else
Rails.configuration.convertDocs.split("|")
end
end
def cur_user_host_address(user_address)
(user_address == nil ? @@remote_ip : user_address).gsub(/[^0-9-.a-zA-Z_=]/, '_');
end
def storage_path(file_name, user_address)
directory = Rails.root.join('public', Rails.configuration.storagePath, cur_user_host_address(user_address))
unless File.directory?(directory)
FileUtils.mkdir_p(directory)
end
directory.join(file_name).to_s
end
def get_correct_name(file_name)
ext = File.extname(file_name)
base_name = File.basename(file_name, ext)
name = base_name + ext
index = 1
while File.exist?(storage_path(name, nil))
name = base_name + ' (' + index.to_s + ')' + ext
index = index + 1
end
name
end
def create_demo(file_ext)
demo_name = 'sample.' + file_ext
file_name = get_correct_name demo_name
src = Rails.root.join('public', 'samples', demo_name)
dest = storage_path file_name, nil
FileUtils.cp src, dest
file_name
end
def get_file_uri(file_name)
uri = @@base_url + '/' + Rails.configuration.storagePath + '/' + cur_user_host_address(nil) + '/' + URI::encode(file_name)
if Rails.configuration.haveExternalIp
return uri
end
get_external_uri(uri)
end
def get_callback(file_name)
@@base_url + '/track?type=track&userAddress=' + cur_user_host_address(nil) + '&fileName=' + URI::encode(file_name)
end
def get_external_uri(local_uri)
begin
uri = @@runtime_cache[local_uri]
if uri == nil
file_name = URI::decode(File.basename(local_uri))
file_storage_path = DocumentHelper.storage_path(file_name, nil)
data = File.open(file_storage_path, 'rb') {|io| io.read}
key = ServiceConverter.generate_revision_id(local_uri)
uri = ServiceConverter.get_external_uri(data, data.length, nil, key)
@@runtime_cache[local_uri] = uri
end
return uri
rescue => ex
raise ex.message
end
local_uri
end
def get_internal_extension(file_type)
case file_type
when 'text'
ext = '.docx'
when 'spreadsheet'
ext = '.xlsx'
when 'presentation'
ext = '.pptx'
else
ext = '.docx'
end
ext
end
end
end

View File

@@ -0,0 +1,40 @@
class FileModel
attr_accessor :file_name, :mode, :user_ip
def initialize(attributes = {})
@file_name = attributes[:file_name]
@mode = attributes[:mode]
@user_ip = attributes[:user_ip]
end
def desktop_type
@mode != 'embedded'
end
def file_ext
File.extname(@file_name)
end
def file_uri
DocumentHelper.get_file_uri(@file_name)
end
def document_type
FileUtility.get_file_type(@file_name)
end
def key
uri = DocumentHelper.cur_user_host_address(nil) + '/' + @file_name
ServiceConverter.generate_revision_id(uri)
end
def validate_key
ServiceConverter.generate_validate_key(key, @user_ip)
end
def callback_url
DocumentHelper.get_callback(@file_name)
end
end

View File

@@ -0,0 +1,31 @@
class FileUtility
@@exts_document = %w(.docx .doc .odt .rtf .txt .html .htm .mht .pdf .djvu .fb2 .epub .xps)
@@exts_spreadsheet = %w(.xls .xlsx .ods .csv)
@@exts_presentation = %w(.ppt .pptx .odp)
class << self
def get_file_type(file_name)
ext = File.extname(file_name)
if @@exts_document.include? ext
return 'text'
end
if @@exts_spreadsheet.include? ext
return 'spreadsheet'
end
if @@exts_presentation.include? ext
return 'presentation'
end
'text'
end
end
end

View File

@@ -0,0 +1,248 @@
class ServiceConverter
@@convert_timeout = Rails.configuration.timeout
@@document_converter_url = Rails.configuration.urlConverter
@@document_storage_url = Rails.configuration.urlStorage
@@convert_params = '?url=%s&outputtype=%s&filetype=%s&title=%s&key=%s&vkey=%s'
@@max_try = 3
class << self
def get_converted_uri(document_uri, from_ext, to_ext, document_revision_id, is_async)
converted_document_uri = nil
responce_from_convert_service = send_request_to_convert_service(document_uri, from_ext, to_ext, document_revision_id, is_async)
file_result = responce_from_convert_service['FileResult']
error_element = file_result['Error']
if error_element != nil
process_convert_service_responce_error(error_element.to_i)
end
is_end_convert = file_result['EndConvert'].downcase == 'true'
percent = file_result['Percent'].to_i
if is_end_convert
converted_document_uri = file_result['FileUrl']
percent = 100
else
percent = percent >= 100 ? 99 : percent;
end
return percent, converted_document_uri
end
def get_external_uri(content, content_length, content_type, document_revision_id)
validate_key = generate_validate_key(document_revision_id, nil)
url_to_storage = @@document_storage_url + (@@convert_params % ['', '', '', '', document_revision_id, validate_key])
if content_type == nil
content_type = 'application/octet-stream'
end
uri = URI.parse(url_to_storage)
http = Net::HTTP.new(uri.host, uri.port)
if url_to_storage.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Post.new(uri.request_uri, {'Content-Type' => content_type , 'Content-Length' => content_length.to_s })
req.body = content
res = http.request(req)
data = res.body
if data == nil
raise 'Could not get an answer'
end
document_response = Hash.from_xml(data.gsub('\n', ''))
percent, external_uri = get_response_uri(document_response)
external_uri
end
def generate_revision_id(expected_key)
require 'zlib'
if expected_key.length > 20
expected_key = (Zlib.crc32 expected_key).to_s
end
key = expected_key.gsub(/[^0-9a-zA-Z.=]/, '_')
key[(key.length - [key.length, 20].min)..key.length]
end
def generate_validate_key(document_revision_id, user_ip)
if document_revision_id == nil
return ''
end
expire = Time.now.to_i * 1000
key = generate_revision_id(document_revision_id)
key_id = get_key
user_count = '0'
ip = user_ip != nil ? '' : user_ip
key = '{"expire": "\/Date(%s)\/", "key" : "%s", "key_id" : "%s", "user_count" : %s, "ip" : "%s"}' %
[expire.to_s, key.to_s, key_id.to_s, user_count, ip]
Signature.create(key, get_skey)
end
def get_key
Rails.configuration.tenantId
end
def get_skey
Rails.configuration.key
end
def send_request_to_convert_service(document_uri, from_ext, to_ext, document_revision_id, is_async)
from_ext = from_ext == nil ? File.extname(document_uri) : from_ext
title = File.basename(URI.parse(document_uri).path)
title = title == nil ? UUID.generate.to_s : title
document_revision_id = document_revision_id.empty? ? document_uri : document_revision_id
document_revision_id = generate_revision_id(document_revision_id)
validate_key = generate_validate_key(document_revision_id, nil)
url_to_converter = @@document_converter_url +
(@@convert_params % [URI::encode(document_uri), to_ext.delete('.'), from_ext.delete('.'), title, document_revision_id, validate_key])
if is_async
url_to_converter += '&async=true'
end
data = nil
count_try = 0
while count_try < @@max_try
begin
count_try += 1
uri = URI.parse(url_to_converter)
http = Net::HTTP.new(uri.host, uri.port)
if url_to_converter.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http.read_timeout = @@convert_timeout
req = Net::HTTP::Get.new(uri.request_uri)
res = http.request(req)
data = res.body
break
rescue TimeoutError
#try again
rescue => ex
raise ex.message
end
end
if count_try == @@max_try && data == nil
raise 'timeout'
end
Hash.from_xml(data.gsub('\n', ''))
end
def process_convert_service_responce_error(error_code)
error_message = 'unknown error'
case error_code
when -8
error_message = 'Error occurred in the ConvertService.ashx: Error document VKey'
when -7
error_message = 'Error occurred in the ConvertService.ashx: Error document request'
when -6
error_message = 'Error occurred in the ConvertService.ashx: Error database'
when -5
error_message = 'Error occurred in the ConvertService.ashx: Error unexpected guid'
when -4
error_message = 'Error occurred in the ConvertService.ashx: Error download error'
when -3
error_message = 'Error occurred in the ConvertService.ashx: Error convertation error'
when -2
error_message = 'Error occurred in the ConvertService.ashx: Error convertation timeout'
when -1
error_message = 'Error occurred in the ConvertService.ashx: Error convertation unknown'
when 0
#public const int c_nErrorNo = 0
else
error_message = 'ErrorCode = ' + error_code.to_s
end
raise error_message
end
def get_response_uri(document_response)
file_result = document_response['FileResult']
if file_result == nil
raise 'Invalid answer format'
end
error_element = file_result['Error']
if error_element != nil
process_convert_service_responce_error(error_element.to_i)
end
end_convert_element = file_result['EndConvert']
if end_convert_element == nil
raise 'Invalid answer format'
end
is_end_convert = end_convert_element.downcase == 'true'
result_percent = 0
response_uri = ''
if is_end_convert
file_url_element = file_result['FileUrl']
if file_url_element == nil
raise 'Invalid answer format'
end
response_uri = file_url_element
result_percent = 100
else
percent_element = file_result['Percent']
if percent_element != nil
result_percent = percent_element.to_i
end
result_percent = result_percent >= 100 ? 99 : result_percent
end
return result_percent, response_uri
end
end
end

View File

@@ -0,0 +1,43 @@
class Signature
class << self
def create(key, secret)
#secret = '_ContactUs_'
#key = '{"expire":"\/Date(1422449303583)\/","key":"mo.docx1422449303571","key_id":"_ContactUs_","user_count":0}'
payload = get_hash_base64(key + secret) + '?' + key
encode = url_token_encode(payload)
end
def get_hash_base64(str)
utf8 = str.encode('utf-8')
sha256 = Digest::SHA256.digest(utf8)
base64 = Base64.strict_encode64(sha256)
end
def url_token_encode(str)
utf8 = str.encode('utf-8')
base64 = Base64.strict_encode64(utf8)
cnt = 0
base64.each_char {|c|
if c == '='
cnt += 1
end
}
signature = base64.gsub('=', '') + cnt.to_s
signature = signature.gsub('+', '-').gsub('/', '_')
signature = URI.encode(signature)
end
end
end

View File

@@ -0,0 +1,147 @@
<div class="form">
<div id="iframeEditor">
</div>
</div>
<script src="<%= Rails.configuration.urlApi %>"></script>
<script type="text/javascript" language="javascript">
var docEditor;
var fileName = "<%= @file.file_name %>";
var fileType = "<%= @file.file_ext.delete('.') %>";
var innerAlert = function (message) {
if (console && console.log)
console.log(message);
};
var onReady = function () {
innerAlert("Document editor ready");
};
var onBack = function () {
location.href = "<%= root_path %>";
};
var onDocumentStateChange = function (event) {
var title = document.title.replace(/\*$/g, "");
document.title = title + (event.data ? "*" : "");
};
var onRequestEditRights = function () {
if (typeof DocsAPI.DocEditor.version == "function") {
var version = DocsAPI.DocEditor.version();
if ((parseFloat(version) || 0) >= 3) {
location.href = location.href.replace(RegExp("action=view?&", "i"), "");
return;
}
}
docEditor.applyEditRights(true);
};
var onDocumentSave = function (event) {
SaveFileRequest(fileName, fileType, event.data);
};
var onError = function (event) {
if (console && console.log && event)
console.log(event.data);
};
var сonnectEditor = function () {
docEditor = new DocsAPI.DocEditor("iframeEditor",
{
width: "100%",
height: "100%",
type: "<%= @file.desktop_type ? 'desktop' : 'embedded' %>",
documentType: "<%= @file.document_type %>",
document: {
title: fileName,
url: "<%= @file.file_uri %>",
fileType: fileType,
key: "<%= @file.key %>",
vkey: "<%= @file.validate_key %>",
info: {
author: "Me",
created: "<%= Time.now.to_s %>"
},
permissions: {
edit: "<%= (DocumentHelper.edited_exts.include? @file.file_ext).to_s %>" == "true",
download: true
}
},
editorConfig: {
mode: "<%= (DocumentHelper.edited_exts.include? @file.file_ext) && @file.mode != 'view' ? 'edit' : 'view' %>",
lang: "en",
callbackUrl: "<%= raw @file.callback_url %>",
embedded: {
saveUrl: "<%= @file.file_uri %>",
embedUrl: "<%= @file.file_uri %>",
shareUrl: "<%= @file.file_uri %>",
toolbarDocked: "top"
}
},
events: {
'onReady': onReady,
'onBack': "<%= @file.desktop_type.to_s %>" == "true" ? onBack : undefined,
'onDocumentStateChange': onDocumentStateChange,
'onSave': onDocumentSave,
'onError': onError
}
});
};
if (window.addEventListener) {
window.addEventListener("load", сonnectEditor);
} else if (window.attachEvent) {
window.attachEvent("load", сonnectEditor);
}
function getXmlHttp() {
var xmlhttp;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (ex) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
}
function SaveFileRequest(fileName, fileType, fileUri) {
var req = getXmlHttp();
if (console && console.log) {
req.onreadystatechange = function () {
if (req.readyState == 4) {
console.log(req.statusText);
if (req.status == 200) {
console.log(req.responseText);
}
}
};
}
var requestAddress = "<%= save_url %>"
+ "?filename=" + encodeURIComponent(fileName)
+ "&filetype=" + encodeURIComponent(fileType)
+ "&fileuri=" + encodeURIComponent(fileUri);
req.open('get', requestAddress, true);
req.send(fileUri);
}
</script>

View File

@@ -0,0 +1,98 @@
<div class="top-panel"></div>
<div class="main-panel">
<span class="portal-name">ONLYOFFICE™ Online Editors</span>
<br />
<br />
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE™ Online Editors, the first html5-based editors. You may upload your own documents for testing using the "Choose file" button and selecting the necessary files on your PC.</span>
<div class="file-upload button gray">
<span>Choose file</span>
<input type="file" id="fileupload" name="file" data-url="<%= upload_path %>" />
</div>
<label class="save-original">
<input type="checkbox" id="checkOriginalFormat" />Save document in original format
</label>
<span class="question"></span>
<br />
<br />
<br />
<span class="try-descr">You are also enabled to view and edit documents pre-uploaded to the portal.</span>
<ul class="try-editor-list">
<li>
<a href="<%= sample_path + '?fileExt=docx' %>" target="_blank" class="try-editor document">Sample Document</a>
</li>
<li>
<a href="<%= sample_path + '?fileExt=xlsx' %>" target="_blank" class="try-editor spreadsheet">Sample Spreadsheet</a>
</li>
<li>
<a href="<%= sample_path + '?fileExt=pptx' %>" target="_blank" class="try-editor presentation">Sample Presentation</a>
</li>
</ul>
<br />
<br />
<br />
<div class="help-block">
<span>Want to learn how it works?</span>
<br />
Read the editor <a href="http://api.onlyoffice.com/editors/howitworks">API Documentation</a>
</div>
<br />
<br />
<br />
<div class="help-block">
<span>Any questions?</span>
<br />
Please, <a href="mailto:sales@onlyoffice.com">submit your request</a> and we'll help you shortly.
</div>
</div>
<div id="hint">
<div class="corner"></div>
If you check this option the file will be saved both in the original and converted into Office Open XML format for faster viewing and editing. In other case the document will be overwritten by its copy in Office Open XML format.
</div>
<div id="mainProgress">
<div id="uploadSteps">
<span id="step1" class="step">1. Loading the file</span>
<span class="step-descr">The file loading process will take some time depending on the file size, presence or absence of additional elements in it (macros, etc.) and the connection speed.</span>
<br />
<span id="step2" class="step">2. File conversion</span>
<span class="step-descr">The file is being converted into Office Open XML format for the document faster viewing and editing.</span>
<br />
<span id="step3" class="step">3. Loading editor scripts</span>
<span class="step-descr">The scripts for the editor are loaded only once and are will be cached on your computer in future. It might take some time depending on the connection speed.</span>
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
<br />
<br />
<span class="progress-descr">Please note, that the speed of all operations greatly depends on the server and the client locations. In case they differ or are located in differernt countries/continents, there might be lack of speed and greater wait time. The best results are achieved when the server and client computers are located in one and the same place (city).</span>
<br />
<br />
<div class="error-message">
<span></span>
<br />
Please select another file and try again. If you have questions please <a href="mailto:sales@onlyoffice.com">contact us.</a>
</div>
</div>
<iframe id="embeddedView" src="" height="345px" width="600px" frameborder="0" scrolling="no" allowtransparency></iframe>
<br />
<div id="beginEmbedded" class="button disable">Embedded view</div>
<div id="beginView" class="button disable">View</div>
<div id="beginEdit" class="button disable">Edit</div>
<div id="cancelEdit" class="button gray">Cancel</div>
</div>
<span id="loadScripts" data-docs="<%= Rails.configuration.urlPreloader %>"></span>
<div class="bottom-panel">&copy; Ascensio System SIA <%= Time.now.year %>. All rights reserved.</div>
<%= javascript_include_tag "application" %>
<script language="javascript" type="text/javascript">
var ConvertExtList = '<%= DocumentHelper.convert_exts.join(",") %>';
var EditedExtList = '<%= DocumentHelper.edited_exts.join(",") %>';
var UrlConverter = '<%= convert_path %>';
var UrlEditor = '<%= editor_path %>';
</script>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<%= favicon_link_tag "favicon.ico" %>
<title>ONLYOFFICE™</title>
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:900,800,700,600,500,400,300&subset=latin,cyrillic-ext,cyrillic,latin-ext" />
<%= stylesheet_link_tag "application" %>
</head>
<body>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env ruby.exe
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
load Gem.bin_path('bundler', 'bundle')

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env ruby.exe
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env ruby.exe
require_relative '../config/boot'
require 'rake'
Rake.application.run

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env ruby.exe
require 'pathname'
# path to your application root.
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
Dir.chdir APP_ROOT do
# This script is a starting point to setup your application.
# Add necessary setup steps to this file:
puts "== Installing dependencies =="
system "gem install bundler --conservative"
system "bundle check || bundle install"
# puts "\n== Copying sample files =="
# unless File.exist?("config/database.yml")
# system "cp config/database.yml.sample config/database.yml"
# end
puts "\n== Preparing database =="
system "bin/rake db:setup"
puts "\n== Removing old logs and tempfiles =="
system "rm -f log/*"
system "rm -rf tmp/cache"
puts "\n== Restarting application server =="
system "touch tmp/restart.txt"
end

View File

@@ -0,0 +1,4 @@
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
run Rails.application

View File

@@ -0,0 +1,53 @@
require File.expand_path('../boot', __FILE__)
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module OnlineEditorsExampleRuby
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
Rails.configuration.fileSizeMax=5242880
Rails.configuration.storagePath="app_data"
Rails.configuration.timeout=120
Rails.configuration.tenantId="_ContactUs_"
Rails.configuration.key="_ContactUs_"
Rails.configuration.viewedDocs=".ppt|.pps|.odp|.pdf|.djvu|.fb2|.epub|.xps"
Rails.configuration.editedDocs=".docx|.doc|.odt|.xlsx|.xls|.ods|.csv|.pptx|.ppsx|.rtf|.txt|.mht|.html|.htm"
Rails.configuration.convertDocs=".doc|.odt|.xls|.ods|.ppt|.pps|.odp|.rtf|.mht|.html|.htm|.fb2|.epub"
Rails.configuration.urlStorage="https://doc.onlyoffice.com/FileUploader.ashx"
Rails.configuration.urlConverter="https://doc.onlyoffice.com/ConvertService.ashx"
Rails.configuration.urlApi="https://doc.onlyoffice.com/OfficeWeb/apps/api/documents/api.js"
Rails.configuration.urlPreloader="https://doc.onlyoffice.com/OfficeWeb/apps/api/documents/cache-scripts.html"
Rails.configuration.haveExternalIp=false #service can access the document on the url
end
end

View File

@@ -0,0 +1,3 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' # Set up gems listed in the Gemfile.

View File

@@ -0,0 +1,25 @@
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3

View File

@@ -0,0 +1,5 @@
# Load the Rails application.
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!

View File

@@ -0,0 +1,41 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end

View File

@@ -0,0 +1,79 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like
# NGINX, varnish or squid.
# config.action_dispatch.rack_cache = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
end

View File

@@ -0,0 +1,42 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Configure static file server for tests with Cache-Control for performance.
config.serve_static_files = true
config.static_cache_control = 'public, max-age=3600'
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Randomize the order test cases are executed.
config.active_support.test_order = :random
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end

View File

@@ -0,0 +1,11 @@
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# Rails.application.config.assets.precompile += %w( search.js )

View File

@@ -0,0 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View File

@@ -0,0 +1,3 @@
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json

View File

@@ -0,0 +1,4 @@
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

View File

@@ -0,0 +1,16 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end

View File

@@ -0,0 +1,4 @@
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf

View File

@@ -0,0 +1,3 @@
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_OnlineEditorsExampleRuby_session'

View File

@@ -0,0 +1,14 @@
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
end
# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
# self.include_root_in_json = true
# end

View File

@@ -0,0 +1,23 @@
# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
# <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# To learn more, please read the Rails Internationalization guide
# available at http://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"

View File

@@ -0,0 +1,66 @@
Rails.application.routes.draw do
root 'home#index'
match '/index', to: 'home#index', via: 'get'
match '/editor', to: 'home#editor', via: 'get'
match '/sample', to: 'home#sample', via: 'get'
match '/upload', to: 'home#upload', via: 'post'
match '/convert', to: 'home#convert', via: 'get'
match '/save', to: 'home#save', via: 'get'
match '/track', to: 'home#track', via: 'post'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end

View File

@@ -0,0 +1,22 @@
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
development:
secret_key_base: fadb8c51b54ebcb061791161d507fdaaa6df77e2ed6611101903bf48a20fffe0164a1fe9da16b5b400453de6b05dd46810de12ee468b3d695a4aa618801402a4
test:
secret_key_base: 96b983c551091cb89dae1538233bbdba38f8ca742b61b2320fa7f9aa6a3f146bfda53da2c8cdf2001f66626826f8519eab4327a521d5485ab434f4241fe4d74f
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

View File

@@ -0,0 +1,7 @@
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<div>
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<title>The change you wanted was rejected (422)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<div>
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
background-color: #EFEFEF;
color: #2E2F30;
text-align: center;
font-family: arial, sans-serif;
margin: 0;
}
div.dialog {
width: 95%;
max-width: 33em;
margin: 4em auto 0;
}
div.dialog > div {
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #BBB;
border-top: #B00100 solid 4px;
border-top-left-radius: 9px;
border-top-right-radius: 9px;
background-color: white;
padding: 7px 12% 0;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
h1 {
font-size: 100%;
color: #730E15;
line-height: 1.5em;
}
div.dialog > p {
margin: 0 0 1em;
padding: 1em;
background-color: #F7F7F7;
border: 1px solid #CCC;
border-right-color: #999;
border-left-color: #999;
border-bottom-color: #999;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-top-color: #DADADA;
color: #666;
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
}
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<div>
<h1>We're sorry, but something went wrong.</h1>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>