Commit b8391435 authored by nazarf's avatar nazarf

nazar copy

git-svn-id: https://svn.sp-service.com.ua/svnroot/svn/node-stats/branches/nazar_trunk@6 320591d9-fe85-4a77-9bad-1a723db14d60
parents
# 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
<?xml version="1.0" encoding="UTF-8"?>
<Settings><!--This file was automatically generated by Ruby plugin.
You are allowed to:
1. Reorder generators
2. Remove generators
3. Add installed generators
To add new installed generators automatically delete this file and reload the project.
--><GeneratorsGroup><Generator name="active_record:devise" /><Generator name="assets" /><Generator name="bootstrap:install" /><Generator name="bootstrap:layout" /><Generator name="bootstrap:partial" /><Generator name="bootstrap:themed" /><Generator name="ckeditor:install" /><Generator name="ckeditor:pundit_policy" /><Generator name="coffee:assets" /><Generator name="controller" /><Generator name="devise" /><Generator name="devise:controllers" /><Generator name="devise:i18n:locale" /><Generator name="devise:i18n:views" /><Generator name="devise:install" /><Generator name="devise:views" /><Generator name="erb:controller" /><Generator name="erb:mailer" /><Generator name="erb:scaffold" /><Generator name="generator" /><Generator name="haml:application_layout" /><Generator name="helper" /><Generator name="integration_test" /><Generator name="jbuilder" /><Generator name="job" /><Generator name="js:assets" /><Generator name="less:assets" /><Generator name="mailer" /><Generator name="migration" /><Generator name="model" /><Generator name="mongoid:devise" /><Generator name="nested_form:install" /><Generator name="resource" /><Generator name="responders:install" /><Generator name="responders_controller" /><Generator name="scaffold" /><Generator name="scaffold_controller" /><Generator name="simple_form:install" /><Generator name="task" /><Generator name="test_unit:generator" /><Generator name="test_unit:job" /><Generator name="test_unit:plugin" /><Generator name="uploader" /></GeneratorsGroup></Settings>
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<codeStyleSettings language="ruby">
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
</codeStyleSettings>
</value>
</option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</component>
</project>
\ No newline at end of file
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<codeStyleSettings language="ruby">
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
</codeStyleSettings>
</code_scheme>
</component>
\ No newline at end of file
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
\ No newline at end of file
<component name="CopyrightManager">
<settings default="" />
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="RailsParamDefResolve" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="Rubocop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RubyInstanceMethodNamingConvention" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_maxLength" value="40" />
</inspection_tool>
<inspection_tool class="RubyResolve" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="warnImplicitResults" value="false" />
</inspection_tool>
<inspection_tool class="RubyStringKeysInHashInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_PROFILE" value="true" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="false" project-jdk-name="RVM: ruby-2.3.3 [global]" project-jdk-type="RUBY_SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SvnBranchConfigurationManager">
<option name="myConfigurationMap">
<map>
<entry key="$PROJECT_DIR$">
<value>
<SvnBranchConfiguration>
<option name="branchUrls">
<list>
<option value="https://svn.sp-service.com.ua/svnroot/svn/base_site/branches" />
<option value="https://svn.sp-service.com.ua/svnroot/svn/base_site/tags" />
</list>
</option>
<option name="trunkUrl" value="https://svn.sp-service.com.ua/svnroot/svn/base_site/trunk" />
</SvnBranchConfiguration>
</value>
</entry>
</map>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/base_site.iml" filepath="$PROJECT_DIR$/base_site.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="svn" />
</component>
</project>
\ No newline at end of file
ruby-2.3.3
\ No newline at end of file
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
# https://github.com/capistrano/rvm
require 'capistrano/rvm'
# https://github.com/capistrano/bundler
require 'capistrano/bundler'
# require 'capistrano/rails'
require 'capistrano/rails'
require 'capistrano/faster_assets'
require 'capistrano/scm/svn'
install_plugin Capistrano::SCM::Svn
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
# Invoke staging as default
# Rake::Task[:staging].invoke
\ No newline at end of file
source 'https://rubygems.org'
gem 'rails', '4.2.8'
gem 'mysql2'
gem 'uglifier', '>= 1.3.0'
gem 'sass-rails', '~> 5.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'twitter-bootstrap-rails'
gem 'bootstrap-sass', '~> 3.3.4'
gem 'haml-rails'
gem 'devise'
gem 'devise-i18n'
gem 'ckeditor'
gem 'carrierwave'
gem 'mini_magick'
gem 'simple_form'
gem 'nested_form'
gem 'font-awesome-rails'
gem 'jquery-ui-rails'
gem 'acts_as_list'
gem 'will_paginate'
gem 'bootstrap-will_paginate'
gem 'momentjs-rails', '>= 2.9.0'
gem 'bootstrap3-datetimepicker-rails', '~> 4.15.35'
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'json'
gem "google_drive"
group :development do
gem 'capistrano-faster-assets'
gem 'capistrano-rails'
gem 'capistrano-rvm'
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
gem 'web-console', '>= 3.3.0'
end
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.2.8)
actionpack (= 4.2.8)
actionview (= 4.2.8)
activejob (= 4.2.8)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.8)
actionview (= 4.2.8)
activesupport (= 4.2.8)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.8)
activesupport (= 4.2.8)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (4.2.8)
activesupport (= 4.2.8)
globalid (>= 0.3.0)
activemodel (4.2.8)
activesupport (= 4.2.8)
builder (~> 3.1)
activerecord (4.2.8)
activemodel (= 4.2.8)
activesupport (= 4.2.8)
arel (~> 6.0)
activesupport (4.2.8)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
acts_as_list (0.9.4)
activerecord (>= 3.0)
airbrussh (1.1.2)
sshkit (>= 1.6.1, != 1.7.0)
arel (6.0.4)
autoprefixer-rails (6.7.7.1)
execjs
bcrypt (3.1.11)
bcrypt (3.1.11-x64-mingw32)
bcrypt (3.1.11-x86-mingw32)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootstrap-sass (3.3.7)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
bootstrap-will_paginate (0.0.11)
will_paginate
bootstrap3-datetimepicker-rails (4.15.35)
momentjs-rails (>= 2.8.1)
builder (3.2.3)
capistrano (3.7.2)
airbrussh (>= 1.0.0)
capistrano-harrow
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
capistrano-bundler (1.2.0)
capistrano (~> 3.1)
sshkit (~> 1.2)
capistrano-faster-assets (1.0.2)
capistrano (>= 3.1)
capistrano-harrow (0.5.3)
capistrano-rails (1.2.3)
capistrano (~> 3.1)
capistrano-bundler (~> 1.1)
capistrano-rvm (0.1.2)
capistrano (~> 3.0)
sshkit (~> 1.2)
carrierwave (1.0.0)
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
ckeditor (4.2.4)
cocaine
orm_adapter (~> 0.5.0)
climate_control (0.2.0)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
coffee-rails (4.1.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.1.x)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
commonjs (0.2.7)
concurrent-ruby (1.0.5)
debug_inspector (0.0.2)
devise (4.2.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
devise-i18n (1.1.2)
erubis (2.7.0)
execjs (2.7.0)
font-awesome-rails (4.7.0.1)
railties (>= 3.2, < 5.1)
globalid (0.3.7)
activesupport (>= 4.1.0)
haml (4.0.7)
tilt
haml-rails (0.9.0)
actionpack (>= 4.0.1)
activesupport (>= 4.0.1)
haml (>= 4.0.6, < 5.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1)
html2haml (2.1.0)
erubis (~> 2.7.0)
haml (~> 4.0)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
i18n (0.8.1)
jbuilder (2.6.3)
activesupport (>= 3.0.0, < 5.2)
multi_json (~> 1.2)
jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1)
railties (>= 3.2.16)
json (2.1.0)
less (2.6.0)
commonjs (~> 0.2.7)
less-rails (2.8.0)
actionpack (>= 4.0)
less (~> 2.6.0)
sprockets (> 2, < 4)
tilt
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
mime-types (>= 1.16, < 4)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_magick (4.6.1)
mini_portile2 (2.1.0)
minitest (5.10.1)
momentjs-rails (2.17.1)
railties (>= 3.1)
multi_json (1.12.1)
mysql2 (0.4.5)
mysql2 (0.4.5-x64-mingw32)
mysql2 (0.4.5-x86-mingw32)
nested_form (0.3.2)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (4.1.0)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
nokogiri (1.7.1-x64-mingw32)
mini_portile2 (~> 2.1.0)
nokogiri (1.7.1-x86-mingw32)
mini_portile2 (~> 2.1.0)
orm_adapter (0.5.0)
rack (1.6.5)
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.8)
actionmailer (= 4.2.8)
actionpack (= 4.2.8)
actionview (= 4.2.8)
activejob (= 4.2.8)
activemodel (= 4.2.8)
activerecord (= 4.2.8)
activesupport (= 4.2.8)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.8)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.8)
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
railties (4.2.8)
actionpack (= 4.2.8)
activesupport (= 4.2.8)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (12.0.0)
rdoc (4.3.0)
responders (2.3.0)
railties (>= 4.2.0, < 5.1)
ruby_parser (3.8.4)
sexp_processor (~> 4.1)
sass (3.4.23)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sdoc (0.4.2)
rdoc (~> 4.0)
sexp_processor (4.8.0)
simple_form (3.4.0)
actionpack (> 4, < 5.1)
activemodel (> 4, < 5.1)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sshkit (1.12.0)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.7)
turbolinks (5.0.1)
turbolinks-source (~> 5)
turbolinks-source (5.0.0)
twitter-bootstrap-rails (3.2.2)
actionpack (>= 3.1)
execjs (>= 2.2.2, >= 2.2)
less-rails (>= 2.5.0)
railties (>= 3.1)
tzinfo (1.2.2)
thread_safe (~> 0.1)
tzinfo-data (1.2017.1)
tzinfo (>= 1.0.0)
uglifier (3.1.9)
execjs (>= 0.3.0, < 3)
warden (1.2.7)
rack (>= 1.0)
web-console (2.3.0)
activemodel (>= 4.0)
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
sprockets-rails (>= 2.0, < 4.0)
will_paginate (3.1.5)
PLATFORMS
ruby
x64-mingw32
x86-mingw32
DEPENDENCIES
acts_as_list
bootstrap-sass (~> 3.3.4)
bootstrap-will_paginate
bootstrap3-datetimepicker-rails (~> 4.15.35)
capistrano (~> 3.7.2)
capistrano-bundler
capistrano-faster-assets (~> 1.0)
capistrano-rails
capistrano-rvm
carrierwave
ckeditor
coffee-rails (~> 4.1.0)
devise
devise-i18n
font-awesome-rails
haml-rails
jbuilder (~> 2.0)
jquery-rails
jquery-ui-rails
json
mini_magick
momentjs-rails (>= 2.9.0)
mysql2
nested_form
rails (= 4.2.8)
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
simple_form
turbolinks
twitter-bootstrap-rails
tzinfo-data
uglifier (>= 1.3.0)
web-console (~> 2.0)
will_paginate
BUNDLED WITH
1.16.2
== 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>.
# 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
z_sendmany znkHBbvPzgbB3zNmqDFZK3eWCSM7j7VfUpm '[{ "address":"znff3kJV4jemXdX2upsczkNvNQ3Q6drM96B", "amount": "42.0001" }, { "address":"znm6BH74X8ebVdAW6BoXV9nU85ykmmUC6pb", "amount": "42.0001" }, { "address":"znnXhfitPet8p56ryw963Uog2dvAWZJhDgH", "amount": "42.0001" }, { "address":"znX6M6FA44YiD9sQFtzpj7mQaj1uckJUK3X", "amount": "42.0001" }, { "address":"znTyDUCDiwcGxpLkJZ346gMtna9haMWSJFp", "amount": "42.0001" }, { "address":"znjDc99Dks5ktfSiTkyF9tFUkegKFquzLoR", "amount": "42.0001" }, { "address":"znkz37NgMbatwBQwBc6yggBLcDsZsPZFeCM", "amount": "42.0001" }, { "address":"znUuHHvYyjCdvr5gaPYsMvR27eP2F9qgQXy", "amount": "42.0001" }, { "address":"znVsbvBx8aaYDeESERGabfbhPQdor4ubMU1", "amount": "42.0001" }, { "address":"znSpk4gDZsmjReQ1pv5Bd8cWWyA3mpGzhn6", "amount": "42.0001" }, { "address":"znbwmb4MFEPQZF26SUBzK9jQwGyZrPAWnMF", "amount": "42.0001" }, { "address":"znSyrrasfj1ZGrw6zvQEPwSbnqFEV821Zcu", "amount": "42.0001" }, { "address":"znZAn3czymPbDfaawDJQu3JJMxtcDHEYmSV", "amount": "42.0001" }, { "address":"znRBozfwgQW3sQbXzcUXVrsqg1Tw6b5rgdF", "amount": "42.0001" }, { "address":"znhDyryWjLbbeKpfcoMeXhk2QdNw3pF2hP1", "amount": "42.0001" }, { "address":"zndncpfPmsdks2sxrjTHoiEJpixmPVrcQRg", "amount": "42.0001" }, { "address":"znXFzPWzCuXR9JFvFCLcDJJpr9SbEaomxzW", "amount": "42.0001" }, { "address":"znVZbwkiJUxCyqdVtCVp14RoS95jEgACLwN", "amount": "42.0001" }, { "address":"zndyDqVZuvrLNfXcyRnQ2gfR4pNmmHCHdAz", "amount": "42.0001" }, { "address":"znTMax99wueha5jCczHiYGLQmnmyiRJ4LMS", "amount": "42.0001" }, { "address":"zna7UHMw1TkQ6d5CDXhfsf6F2CjuGMUw2eH", "amount": "42.0001" }, { "address":"zng7CVyh4jJJLdvPD9wWV32PNmz745kH4hY", "amount": "42.0001" }, { "address":"zneySs5Kj61nbGFiifdsyY1iD1R3t2dRaCq", "amount": "42.0001" }]'
\ No newline at end of file
//= require jquery-ui/widgets/sortable
//= require turbolinks
//= require jquery_nested_form
//= require moment
//= require bootstrap-datetimepicker
//= require_tree ./admin
window.linksPanelShowed = false
$(document).on 'ready page:load turbolinks:load', ->
if window.linksPanelShowed
$('#container:not(.pinned) #links_panel').css left: 0
$(document).on 'mouseover click', '#container:not(.pinned) #links_panel', ->
unless window.linksPanelShowed
$linksPanel = $(this)
$linksPanel.animate {left: 0}, 100, ->
$linksPanel.find('.handle i').removeClass('fa-chevron-circle-right').addClass('fa-chevron-circle-left')
window.linksPanelShowed = true
$(document).on 'mouseleave', '#container:not(.pinned) #links_panel', ->
$linksPanel = $(this)
$linksPanel.animate {left: 10 - $linksPanel.width()}, 250, ->
$linksPanel.find('.handle i').removeClass('fa-chevron-circle-left').addClass('fa-chevron-circle-right')
window.linksPanelShowed = false
$(document).on 'click', '#container:not(.pinned) #links_panel .handle', ->
$linksPanel = $('#links_panel')
$linksPanel.animate {left: 10 - $linksPanel.width()}, 250, ->
$linksPanel.find('.handle i').removeClass('fa-chevron-circle-left').addClass('fa-chevron-circle-right')
window.linksPanelShowed = false
$(document).on 'click', '#container:not(.pinned) #links_panel .pin', ->
$('#container').addClass('pinned')
$.ajax '/admin/links_pinned', method: 'patch', dataType: 'json', data: {pinned: 1}
$(document).on 'click', '#container.pinned #links_panel .pin', ->
$('#container').removeClass('pinned')
$.ajax '/admin/links_pinned', method: 'patch', dataType: 'json', data: {pinned: 0}
$(document).on 'ready page:load turbolinks:load', ->
init_datetime_picker($('.datetime_picker'))
init_date_picker($('.date_picker'))
@init_datetime_picker = (element) ->
element.datetimepicker locale: $('html').attr('lang'), format: 'YYYY-MM-DD HH:mm', useCurrent: false
@init_date_picker = (element) ->
element.datetimepicker locale: $('html').attr('lang'), format: 'YYYY-MM-DD', useCurrent: false
\ No newline at end of file
class @CurrentPath
constructor: () ->
@path = $(location).attr('href').replace(/https?:\/\/[^\/]+/i, "")
replace_param: (param, value) ->
regex = new RegExp('(' + param + '[^&?]*).', 'g')
@path = @path.replace(regex, param + '=' + value)
this
remove_param: (param) ->
regex = new RegExp('(' + param + '[^&?]*).', 'g')
@path = @path.replace(regex, '').replace(/[?&]+$/, '')
this
get_path: () ->
@path
$(document).on 'ready page:load turbolinks:load', ->
$('table.editable_rows').each ->
initEditableRows(this)
initCreation(this)
initEditableRows = (table) ->
$table = $(table)
$table.find('a.edit').click (event) ->
event.preventDefault()
initRowEditing($(this))
$table.find('a.destroy').click (event) ->
event.preventDefault()
event.stopPropagation()
$button = $(this)
confirmation = $button.data('confirm')
if !confirmation or confirm(confirmation)
$row = $button.closest('tr')
$.ajax
type: $button.data('method')
url: $button.attr('href') + '.json'
success: () ->
$row.remove()
dispatchChangeEvent($table, 'delete')
error: (data) -> setErrors($row, data)
initRowEditing = ($editButton) ->
$controlsCell = $editButton.parent('td')
$row = $controlsCell.parent('tr')
orygControlHtml = $controlsCell.find('a').detach()
initControls($controlsCell)
initInputs($row)
$row.find('td[data] input, td[data-name] input, td[data-name] select').keypress (event) ->
if event.which == 13
event.preventDefault()
save()
$controlsCell.find('.save').click (event) ->
event.preventDefault()
save()
save = () ->
clearErrors($row)
data = {id: $row.data('id')}
$row.find('td[data], td[data-name]').each ->
$cell = $(this)
name = if $cell.attr('data') then 'data' else 'data-name'
if $cell.data('image')
$form = $cell.find('form')
$.ajax
type: $form.attr('method')
url: $form.attr('action')
data: new FormData($form[0])
processData: false
contentType: false
success: (data, textStatus, jqXHR) ->
$cell.html(data)
else
data[$cell.attr(name)] = $cell.find('input, select').val()
ajaxData = {}
ajaxData[$table.data('resource')] = data
$.ajax
type: "PUT"
url: window.location.href + "/#{$row.data('id')}.json"
data: ajaxData
success: () ->
restoreRow(true)
dispatchChangeEvent($table, 'update')
error: (data) -> setErrors($row, data)
restoreRow = (updated) ->
$controlsCell.html(orygControlHtml)
$row.find('td[data], td[data-name]').each ->
$cell = $(this)
$input = $cell.find('input, select')
if updated
if $cell.find('form').length == 0
if $input.prop('tagName') == 'SELECT'
$cell.html($input.find("option[value=#{$input.val()}]").html())
else
$cell.html($input.val())
else
$cell.html($cell.data('undo'))
$controlsCell.find('.cancel').click (event) ->
event.preventDefault()
restoreRow(false)
initCreation = (table) ->
$table = $(table)
$createButton = $table.find('a.create')
$row = $createButton.closest('tr')
initInputs($row)
$row.find('td[data], td[data-name]').keypress (event) ->
if event.which == 13
event.preventDefault()
create()
$createButton.click (event) ->
event.preventDefault()
create()
create = () ->
clearErrors($row)
data = {}
$row.find('td[data]').each ->
$cell = $(this)
data[$cell.attr('data')] = $cell.find('input, select').val()
$row.find('td[data-name]').each ->
$cell = $(this)
data[$cell.attr('data-name')] = $cell.find('input, select').val()
ajaxData = {}
ajaxData[$table.data('resource')] = data
$.ajax
type: "POST"
url: window.location.href
data: ajaxData
success: (data) ->
newTableBody = $("<div>#{data}</div>").find('table.editable_rows tbody').html()
$table.find('tbody').html(newTableBody)
$row.find('input:text').val('')
initEditableRows(table)
dispatchChangeEvent($table, 'create')
error: (data) -> setErrors($row, data)
initInputs = ($row) ->
$row.find('td[data], td[data-name]').each ->
$cell = $(this)
$cell.data('undo', $cell.html())
if $cell.data('select')
value = $cell.html()
$cell.html("<select>#{$cell.data('select')}</select><span class='has-error'/>")
$select = $cell.find('select')
$select.val($select.find("option:contains(#{value})").val())
else if $cell.data('image')
$cell.html("#{$cell.data('image')}</input><span class='has-error'/>")
else
value = $cell.html()
$cell.html("<input value='#{value}'><span class='has-error'/>")
initControls = ($cell) ->
$cell.html("<a class='btn btn-primary btn-xs save' href='#'><i class='fa fa-check'/></a> <a class='btn btn-default btn-xs cancel' href='#'><i class='fa fa-remove'/></a>")
clearErrors = ($row) ->
$row.find("td[data] span, td[data-name] span").html('')
setErrors = ($row, data) ->
for k,v of data.responseJSON
$row.find("td[data='#{k}'] span, td[data-name='#{k}'] span").html(v.join())
dispatchChangeEvent = ($table, type) ->
window.dispatchEvent new CustomEvent('editable_table_changed', detail: {resource: $table.data('resource'), type: type})
selectFromData = (data, query) ->
jQuery("<div>#{data}</div>").find(query)
\ No newline at end of file
HISTORY_ID = 'tabular_filter'
$ ->
$(document).on 'change focusout', 'tr#filters .filter', filterChanged
$(document).on 'click', 'tr#filters .clear_tabular_filters', clearFilters
filterChanged = ->
refreshTable($(this).parents('table'))
clearFilters = (e) ->
e.preventDefault()
table = $(this).closest('table')
table.find('tr#filters .filter').val('')
refreshTable(table)
refreshTable = (table) ->
path = new CurrentPath(table.closest('.popup_window').attr('data-path')).remove_param('tf').remove_param('page').get_path()
$.ajax path,
data: filtersHash(table),
asynchronous: true
evalScripts: true
method: "get"
success: (data, textStatus, jqXHR) ->
tableBody = $(data).find('tbody').html()
paginate = $(data).find('.refresh_pagination').html()
refreshData(table, tableBody, paginate)
if table.closest('.popup_window').length
table.closest('.popup_window').attr('data-path', this.url)
else
history.pushState({id: HISTORY_ID, tbody: tableBody, paginate: paginate, filters: filtersHistory()}, null, this.url);
$(window).on 'popstate', () ->
if history.state && history.state.id == HISTORY_ID
refreshData(filteredTable(), history.state.tbody, history.state.paginate)
i = 0
$('table thead tr#filters .filter').each ->
$(this).val(history.state.filters[i++])
filteredTable = (data = 'body') ->
$(data).find('table thead tr#filters').closest('table')
filtersHash = (table) ->
filters = {}
filtersRow = table.find('tr#filters')
filtersRow.find('.filter').each () ->
value = $(this).val()
mode = ''
if value
if $(this).hasClass("date_picker")
mode = 'd'
else if $(this).hasClass("boolean")
mode = 'b'
filters["tf#{mode}_#{$(this).attr('id')}"] = value
filters
refreshData = (table, tbody, paginate) ->
table.find('tbody').html(tbody);
$('.refresh_pagination').html(paginate)
#$(window).resize(); #!!!special for med with its fixed tables!!!
filtersHistory = ->
filters = []
$('table thead tr#filters .filter').each ->
filters.push($(this).val())
filters
\ No newline at end of file
$ ->
newsletter_progress = $('#newsletter_progress')
if newsletter_progress.length > 0
send_emails()
send_emails = () ->
$.getJSON window.location.href, {}, (newsletter) ->
$('#newsletter_progress').css('width', 100*newsletter.processed_id/newsletter.last_id + '%');
if newsletter.processed_id < newsletter.last_id
send_emails()
else
$('.page-header h1').html('Sending of newsletter is complete.')
$('#sending_complete').show()
$(document).on 'ready page:load turbolinks:load', ->
$('#page_mode').each -> refresh_menu_item_fieldset($(this))
$('#page_mode').change -> refresh_menu_item_fieldset($(this))
refresh_menu_item_fieldset = (item) ->
if item.val() == 'link'
$('#path_fields').hide()
$('#page_fields').hide()
$('#link_fields').show()
else if item.val() == 'page' || item.val() == 'anchor'
$('#path_fields').hide()
$('#page_fields').show()
$('#link_fields').hide()
else
$('#path_fields').show()
$('#page_fields').hide()
$('#link_fields').hide()
$(document).on 'ready page:load turbolinks:load', ->
if $('.sort_icon').length
init_sortable('tbody', 'tr')
init_sortable = (container_selector, item_selector, axis = 'y', handle_selector = '.sort_icon') ->
$(container_selector).sortable(
items: item_selector
handle: handle_selector
axis: axis
stop: (event, ui) ->
position = $(ui.item).index() + 1
$.ajax({
type: "PUT"
url: window.location.href + "/#{$(ui.item).data('id')}"
data: {position: position}
});
)
//= require_tree ./admin_front
\ No newline at end of file
#= require jquery-ui/widgets/draggable
#= require jquery-ui/widgets/resizable
$ ->
$('#blocks_controls').draggable()
$(document).on "click", '.block', ->
createInput(this)
createInput = (block) ->
window.currentBlock = block
window.blocksControlsDisplay = $('#blocks_controls').css('display')
$('#blocks_controls').hide()
key = $(block).attr('class').match(/block_key_\w+/)[0].replace(/block_key_/, '')
$.get "/#{$('html').attr('lang')}/admin/blocks/#{key}/edit", (data) ->
$('#block_editor').remove()
$("<div id='block_editor'></div>").appendTo('body').draggable().resizable().css(blockRect())
.animate
top: $(window).height() * 0.2
left: $(window).width() * 0.2
height: $(window).height() * 0.6
width: $(window).width() * 0.6
, 250
, ->
$(data).appendTo('#block_editor')
resizeTextArea()
$('#block_editor textarea').each ->
$textArea = $(this)
$textArea.val($(block).html()) unless $textArea.val()
$textArea.val($textArea.val().replace(/\s+/gi, " ").replace(/<br\s*[\/]?>|<\/p\s*>\s*/gi, "\n").replace(/<p>\s*/gi, ""))
$(document).on "resize", "#block_editor", (e) ->
resizeTextArea()
resizeTextArea = ->
$('#block_editor textarea').height($('#block_editor').height() - 100)
blockRect = ->
top: $(window.currentBlock).offset().top - window.scrollY
left: $(window.currentBlock).offset().left - window.scrollX
height: $(window.currentBlock).height()
width: $(window.currentBlock).width()
$(document).on "mousemove", "#block_editor a", (e) ->
e.stopImmediatePropagation()
$(document).on "wheel", "#block_editor", (e) ->
e.stopImmediatePropagation()
e.target.type == 'textarea'
# e.target.scroll(e)
false
# e.preventDefault()
$(document).on "click", "#cancel_block_editing", (e) ->
$('#block_editor').animate
opacity: 0
top: $('#block_editor').position().top + 0.25 * $('#block_editor').height()
left: $('#block_editor').position().left + 0.25 * $('#block_editor').width()
height: 0.5 * $('#block_editor').height()
width: 0.5 * $('#block_editor').width()
, 250
, ->
$('#block_editor').remove()
$('#blocks_controls').css(display: window.blocksControlsDisplay)
e.preventDefault()
false
$(document).on "click", "#apply_block_editing", (e) ->
$('#block_editor').animate blockRect(), 250, ->
$('#block_editor form').submit()
$('#block_editor').remove()
e.preventDefault()
false
CKEDITOR.editorConfig = function (config) {
config.filebrowserBrowseUrl = "/admin/ckeditor/attachment_files";
config.filebrowserFlashBrowseUrl = "/admin/ckeditor/attachment_files";
config.filebrowserFlashUploadUrl = "/admin/ckeditor/attachment_files";
config.filebrowserImageBrowseLinkUrl = "/admin/ckeditor/pictures";
config.filebrowserImageBrowseUrl = "/admin/ckeditor/pictures";
config.filebrowserImageUploadUrl = "/admin/ckeditor/pictures";
config.filebrowserUploadUrl = "/admin/ckeditor/attachment_files";
//read more here: http://docs.ckeditor.com/#!/api/CKEDITOR.config
config.extraPlugins = 'toolbarswitch,apply';
config.removePlugins = 'about,a11yhelp,dialogadvtab,templates,newpage,pagebreak,wsc,forms';
config.toolbar_minToolbar =
[
{name: 'document', items: ['Apply', 'Cancel']},
{name: 'basicstyles', items: ['Bold', 'Italic']},
//{name: 'links', items: ['Link', 'Unlink']},
{name: 'paragraph', items: ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock']},
{name: 'tools', items: ['Toolbarswitch']}
];
config.toolbar_maxToolbar =
[
{name: 'document', items: ['Source', '-', 'Apply', 'Cancel']},
{
name: 'clipboard',
groups: ['clipboard', 'undo'],
items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo']
},
{
name: 'editing',
groups: ['find', 'selection', 'spellchecker'],
items: ['Find', 'Replace', '-', 'SelectAll', '-', 'Scayt']
},
{name: 'insert', items: ['Image', 'Flash', 'Table', 'HorizontalRule', 'SpecialChar', 'Smiley', 'Iframe']},
{name: 'links', items: ['Link', 'Unlink', 'Anchor']},
'/',
{name: 'styles', items: ['Styles', 'Format', 'Font', 'FontSize']},
{
name: 'basicstyles',
groups: ['basicstyles', 'cleanup'],
items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']
},
{name: 'colors', items: ['TextColor', 'BGColor']},
{
name: 'paragraph',
groups: ['list', 'indent', 'blocks', 'align', 'bidi'],
items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl']
},
{name: 'tools', items: ['ShowBlocks', 'Toolbarswitch']}
];
config.toolbar = 'minToolbar';
config.smallToolbar = 'minToolbar';
config.maximizedToolbar = 'maxToolbar';
config.allowedContent = true;
return true;
};
/*
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.plugins.setLang( 'apply', 'en', {
apply: 'Apply',
cancel: 'Cancel'
});
/*
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.plugins.setLang( 'apply', 'ru', {
apply: 'Применить',
cancel: 'Отменить'
});
/*
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.plugins.setLang( 'apply', 'uk', {
apply: 'Застосувати',
cancel: 'Скасувати'
});
CKEDITOR.plugins.add('apply', {
requires: ['button', 'toolbar', 'maximize'],
lang: 'en,ru,uk', // %REMOVE_LINE_CORE%
icons: 'apply,cancel', // %REMOVE_LINE_CORE%
hidpi: true, // %REMOVE_LINE_CORE%
init: function (editor) {
if (typeof(window.applyCKEditorChanges) != "function") return;
function close(discard_changes) {
if (editor.commands.maximize.state == 1) {
editor.commands.maximize.exec();
}
editor.destroy(discard_changes);
if (typeof(window.applyCloseCKEditor) == "function") {
window.applyCloseCKEditor(Object.keys(CKEDITOR.instances).length);
}
}
var lang = editor.lang;
var applyFunction = {
exec: function (editor) {
close(false);
window.applyCKEditorChanges(editor.getData());
}
};
var cancelFunction = {
exec: function (editor) {
close(true);
}
};
var applyCommand = editor.addCommand('apply', applyFunction);
applyCommand.modes = {wysiwyg: 1, source: 1};
applyCommand.canUndo = false;
applyCommand.readOnly = 1;
editor.ui.addButton && editor.ui.addButton('Apply', {
label: lang.apply.apply,
command: 'apply',
toolbar: 'document,0'
});
var cancelCommand = editor.addCommand('cancel', cancelFunction);
cancelCommand.modes = {wysiwyg: 1, source: 1};
cancelCommand.canUndo = false;
cancelCommand.readOnly = 1;
editor.ui.addButton && editor.ui.addButton('Cancel', {
label: lang.apply.cancel,
command: 'cancel',
toolbar: 'document,1'
});
}
});
/*
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.plugins.setLang( 'toolbarswitch', 'en', {
toolbarswitch: 'Maximize and switch toolbar'
});
/*
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.plugins.setLang( 'toolbarswitch', 'ru', {
toolbarswitch: 'Увеличить и переключить панель инструментов'
});
/*
Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
CKEDITOR.plugins.setLang( 'toolbarswitch', 'uk', {
toolbarswitch: 'Збільшити і переключити панель інструментів'
});
/**
* @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.html or http://ckeditor.com/license
*/
/**
* @fileOverview Plugin that changes the toolbar and maximizes the editor
* for the big toolbar.
*
* You need a custom config to define the small and big toolbars.
* Also the maximize plug-in is needed but not the maximize button.
* For this plugin you should use the 'Toolbarswitch' button instead.
*
* CKEDITOR.replace('sometextcomponentname', {
* customConfig: '/...custom_ckeditor_config.js'
* toolbar: 'yoursmalltoolbarname',
* smallToolbar: 'yoursmalltoolbarname',
* maximizedToolbar: 'yourbigtoolbarname' });
*
* Requires:
* - Maximize plugin. But not the button that goes with it.
* - All toolbars used in the ckeditor instance have to use the 'Toolbarswitch' button instead.
* - A custom config to define the small and big toolbars.
* - jQuery
*/
function switchMe(editor, callback) {
var origCustomConfig = editor.config.customConfig;
var origContentCss = editor.config.contentsCss;
var origExtraPlugins = editor.config.extraPlugins;
var origToolbar = editor.config.toolbar;
var origSmallToolbar = editor.config.smallToolbar;
var origMaximizedToolbar = editor.config.maximizedToolbar;
var newToolbar;
//if (editor.commands.maximize.state == 2) {
if (origToolbar == origSmallToolbar) {
newToolbar = origMaximizedToolbar;
} else {
newToolbar = origSmallToolbar;
}
// Remember editing data before getting rid of the old editor
var oldEditorData = editor.getData();
var domElement = editor.element.$;
// Remove old editor and the DOM elements, else you get two editors
//var id = domElement.id;
editor.destroy(true);
CKEDITOR.replace(domElement, {
customConfig: origCustomConfig,
contentsCss: origContentCss,
toolbar: newToolbar,
smallToolbar: origSmallToolbar,
maximizedToolbar: origMaximizedToolbar,
extraPlugins: origExtraPlugins,
on: {
instanceReady: function (e) {
// Restore old editing data
if (typeof(oldEditorData) != "undefined") {
e.editor.setData(oldEditorData);
}
if (callback) {
callback.call(null, e);
}
}
}
});
}
CKEDITOR.plugins.add('toolbarswitch', {
requires: ['button', 'toolbar', 'maximize'],
lang: 'en,ru,uk', // %REMOVE_LINE_CORE%
icons: 'toolbarswitch', // %REMOVE_LINE_CORE%
hidpi: true, // %REMOVE_LINE_CORE%
init: function (editor) {
var lang = editor.lang;
var commandFunction = {
exec: function (editor) {
if (editor.config.toolbar == editor.config.maximizedToolbar) {
// For switching to the small toolbar first minimize
editor.commands.maximize.exec();
switchMe(editor, function (e) {
var newEditor = e.editor;
newEditor.fire('triggerResize');
});
} else {
switchMe(editor, function (e) {
var newEditor = e.editor;
newEditor.commands.maximize.exec();
newEditor.fire('triggerResize');
newEditor.commands.toolbarswitch.setState(CKEDITOR.TRISTATE_ON);
});
}
}
};
var command = editor.addCommand('toolbarswitch', commandFunction);
command.modes = {wysiwyg: 1, source: 1};
command.canUndo = false;
command.readOnly = 1;
editor.ui.addButton('Toolbarswitch', {
label: lang.toolbarswitch.toolbarswitch,
command: 'toolbarswitch',
toolbar: 'tools,10'
});
}
});
//= require_tree ./front
$(document).on 'ready page:load turbolinks:load', ->
initContactUsMessage()
refreshLandingHeader()
initContactUsMessage = () ->
$('.contact_us_form #contact_message').each ->
$this = $(this)
$this.keypress (event) ->
characters_left = $this.data('characters') - $this.val().length
if characters_left <= 0
event.preventDefault()
$this.keyup () -> updateCharactersLeft()
updateCharactersLeft = () ->
characters_left = $this.data('characters') - $this.val().length
$this.closest('form').find('.characters_left').html(Math.max(characters_left, 0))
updateCharactersLeft()
$(window).scroll -> refreshLandingHeader()
refreshLandingHeader = ->
$header = $('#landing_header')
containerHeight = $header.find('.container').height()
$header.css top: if window.pageYOffset > containerHeight then -containerHeight else -window.pageYOffset
$(document).on 'click', '.zoomed_image', (e) ->
$('#cloned_zoomed_image').remove();
originalLeft = $(this).offset().left - window.pageXOffset;
originalTop = $(this).offset().top - window.pageYOffset;
originalWidth = $(this).width();
clonedImg = $(this).clone()
$(clonedImg).attr(id: 'cloned_zoomed_image', class: '');
$(clonedImg).css(top: originalTop, left: originalLeft, position: 'fixed', 'z-index': 21);
$(clonedImg).width(originalWidth);
$('body').prepend(clonedImg)
$(clonedImg).click () ->
$(clonedImg).animate width: originalWidth, left: originalLeft, top: originalTop
, 300, () -> $(clonedImg).remove()
max = 0.95
coef = $(clonedImg).width() / $(clonedImg).height()
w = $(window).height()*max * coef
if $(clonedImg).width() > $(clonedImg).height() && $(window).width()*max*coef < $(window).height()
w = $(window).width()*max
$('#cloned_zoomed_image').animate
width: w
left: ($(window).width() - w) / 2
top: ($(window).height() - w * $(this).height() / $(this).width() ) / 2
opacity: 1
, 300
e.preventDefault()
false
$(document).on 'ready page:load turbolinks:load', ->
$(".box_sandwich").click ->
if $('.mobile_menu').hasClass('menu_open')
closeMobileMenu()
else
openMobileMenu()
$(document).on 'click', ".mobile_menu a", (e) ->
closeMobileMenu()
closeMobileMenu = () ->
console.log('close')
$('.sandwich').removeClass "close_sandwich"
$('.mobile_menu').removeClass "menu_open"
openMobileMenu = () ->
console.log('open')
$('.sandwich').addClass "close_sandwich"
$('.mobile_menu').addClass "menu_open"
$(document).on 'ready page:load turbolinks:load', ->
$('.box_search .search_action').click (e) ->
$('.box_search form').submit()
@google_search = (query) ->
google.search.cse.element.render({gname: 'google_search', div: 'search_results'});
console.log('rendered google search');
if query
google.search.cse.element.getElement("google_search").execute(query);
console.log("search for \"#{query}\"");
gcseCallback = ->
if $('#search_results').length
console.log("search box found")
query = $('#search_results').data('query')
if (document.readyState == 'complete')
google_search(query)
else
google.setOnLoadCallback ->
google_search(query)
, true
window.__gcse = {
parsetags: 'explicit',
callback: gcseCallback
};
$(document).on 'click', "a[href*='#']:not([href^='#'])", (e) ->
if location.hostname == this.hostname
target = $(this.hash)
target = if target.length then target else $('[name=' + this.hash.slice(1) + ']')
if target.length
$('html,body').animate {scrollTop: target.offset().top - $('#landing_header .nav_menu:not(.mobile_menu):visible').height()}, 500
e.preventDefault()
false
$(document).on 'click', "a[href='#{location.pathname}']", (e) ->
$('html,body').animate {scrollTop: 0}, 500
e.preventDefault()
false
//= require jquery
//= require jquery_ujs
//= require twitter/bootstrap
//= require_tree ./shared
$(document).on 'ready page:load turbolinks:load', ->
$("a[rel~=popover], .has-popover").popover()
$("a[rel~=tooltip], .has-tooltip").tooltip()
/*
*= require bootstrap-datetimepicker
*= require_tree ./admin
*= require_self
*/
html
height: 100%
body.admin-body
padding-top: 70px
height: 100%
.yield-container
overflow-y: auto
height: 100%
.yield-column
padding: 0 10px 20px 90px
&.pinned
.yield-column
padding: 0 10px 20px 300px
#links_panel
left: 0
.handle
display: none
.pin
color: #347bb7
footer
position: fixed
bottom: 0
right: 25px
color: #b2b2b8
p
margin: 0
.navbar-right
margin-right: 0
#links_panel
position: fixed
width: 300px
padding: 0 20px
left: -250px
height: calc(100% - 85px)
z-index: 2
div
height: 100%
overflow-y: auto
ul li
a
padding: 2px 15px
&.selected
margin-left: 0
margin-right: -5px
border-left: #808080 outset 5px
.handle
position: absolute
top: calc(50% - 12px)
left: 265px
color: darkgrey
&:hover
color: #347bb7
cursor: pointer
.pin
position: absolute
top: 5px
left: 258px
color: darkgrey
font-size: 18px
height: 26px
&:hover
color: #347bb7
cursor: pointer
.page-header
margin: 0 0 5px
h1
margin-top: 0
margin-bottom: 0
font-size: 24px
.form-horizontal .form-group
margin-left: 0
margin-right: 0
.sort_icon
width: 15px
cursor: pointer
\ No newline at end of file
table.editable_rows {
td {
input {
width: 100%;
margin: -2px 0;
}
select {
width: 100%;
padding: 2px 0;
margin: -2px 0;
}
img {
margin-top: -5px;
margin-bottom: -5px;
max-height: 32px;
max-width: 100%
}
}
td span.has-error {
color: #a94442;
}
}
@import "bootstrap-sprockets"
@import "bootstrap"
#filters
input
width: 100%
padding: 2px
select
width: 100%
padding: 3px
.clear_btn
text-align: center
display: inline-block
cursor: pointer
margin: 0 5px
color: black
font-weight: normal
font-size: 16px
font-family: FontAwesome
padding: 1px 8px
&:before
content: '\f00d'
&:hover, &:focus, &:active
color: red
background: rgba(0, 0, 0, 0.16)
border-radius: 3px
text-decoration: none
div {
&.field, &.actions {
margin-bottom: 10px;
}
}
//body {
//
// color: #333;
// font-family: verdana, arial, helvetica, sans-serif;
// font-size: 13px;
// line-height: 18px;
//}
//
//p, ol, ul, td {
// font-family: verdana, arial, helvetica, sans-serif;
// font-size: 13px;
// line-height: 18px;
//}
//
//pre {
//// background-color: #eee;
// padding: 10px;
// font-size: 11px;
//}
//
//a {
// color: #000;
//
// &:visited {
// color: #666;
// }
//
// &:hover {
// color: #fff;
//// background-color: #000;
// }
//}
//
//
//#notice {
// color: green;
//}
//
//.field_with_errors {
// padding: 2px;
// background-color: red;
// display: table;
//}
////
//#error_explanation {
// width: 450px;
// border: 2px solid red;
// padding: 7px;
// padding-bottom: 0;
// margin-bottom: 20px;
// background-color: #f0f0f0;
//
// h2 {
// text-align: left;
// font-weight: bold;
// padding: 5px 5px 5px 15px;
// font-size: 12px;
// margin: -7px;
// margin-bottom: 0px;
// background-color: #c00;
// color: #fff;
// }
//
// ul li {
// font-size: 12px;
// list-style: square;
// }
//}
//
//.pagination {
// margin: 0;
//}
table.editable_rows
td input
width: 100%
margin: -2px 0
td span.has-error
color: #a94442
/*
*= require_tree ./admin_front
*/
\ No newline at end of file
//= require jquery-ui/resizable
//= require jquery-ui/draggable
@import "shared/mixin";
.block {
&:hover {
outline: 1px dashed;
outline-offset: -1px;
cursor: pointer;
opacity: 0.7;
}
}
#blocks_controls {
position: fixed;
margin: 10px;
padding: 5px;
width: 260px;
background: rgba(255, 255, 255, 0.8);
@include box-shadow(1px 1px 3px 3px rgba(44, 44, 44, 0.63));
@include border-radius(5px);
z-index: 20;
.caption {
font-size: 18px;
padding: 5px;
cursor: move;
}
a {
padding: 3px;
&.apply {
color: green;
&:hover {
color: lime;
}
}
&.cancel {
color: #d90000;
&:hover {
color: #ff4600;
}
}
}
}
#block_editor {
z-index: 20;
position: fixed;
width: 60%;
height: 60%;
left: 20%;
top: 20%;
padding: 10px;
background: white;
@include box-shadow(1px 1px 3px 3px rgba(44, 44, 44, 0.63));
@include border-radius(4px);
div {
margin: 0;
padding: 0;
}
textarea {
margin-bottom: 10px;
height: 228px;
resize: none;
overflow-y: auto;
border-top: none;
}
label {
display: none;
}
}
\ No newline at end of file
/*
*= require_directory ./front
*= require_self
*/
input
outline: none
&:hover, &:focus, &:active
outline: none
a
text-decoration: none
&:hover, &:focus, &:active, &:visited
text-decoration: none
ul
padding: 0
margin: 0
li
list-style: none
@import "shared/color"
@import "shared/mixin"
body
@media (min-width: 768px)
padding-top: 120px
header
position: fixed
top: 0
left: 0
width: 100%
height: 150px
z-index: 17
@media (max-width: 767px)
padding: 10px
position: relative
height: 40px
nav
position: relative
text-align: center
background: $main
background: -moz-linear-gradient(0deg, $main 30%, $second 93%)
background: -webkit-linear-gradient(0deg, $main 30%, $second 93%)
background: linear-gradient(0deg, $main 30%, $second 93%)
background-image: -ms-linear-gradient(0deg, $main 30%, $second 93%)
background-image: linear-gradient(0deg, $main 30%, $second 93%)
+box-shadow_2(2px 2px 5px -1px rgba(0,0,0,1), inset 0px 0px 15px 12px rgba(154, 154, 154, 0.19))
padding: 2px 0
.nav_menu
display: flex
justify-content: center
a
margin: 0 10px
line-height: 1.5
color: $white
font-weight: bold
font-size: 16px
padding: 5px 10px
border: 2px solid transparent
+border-radius(5px)
+transition(all .2s ease)
&:hover
border: 2px solid
color: $orange !important
+box-shadow(1px 1px 5px -1px black)
&:active
+box-shadow(none)
background: $main
background: -moz-linear-gradient(-180deg, $second 0%, $main 100%)
background: -webkit-linear-gradient(-180deg, $second 0%, $main 100%)
background: linear-gradient(-180deg, $second 0%, $main 100%)
background-image: -ms-linear-gradient(-180deg, $second 0%, $main 100%)
background-image: linear-gradient(-180deg, $second 0%, $main 100%)
&:visited
color: white
.contact_box
margin-top: 10%
.info_box
h1, h4
margin: 10px 0
h4
display: inline-block
border-bottom: 2px solid $main
color: $black
padding: 5px 20px
@media (max-width: 990px)
font-size: 14px
margin-top: 20px
h1
color: $main
font-weight: bold
@media (max-width: 990px )
font-size: 24px
margin: 0
.info-block
height: 59px
display: table
div
display: table-cell
vertical-align: middle
p
margin: 0
.language_box
position: absolute
top: 6px
right: 30px
.navbar-btn
margin: 0
.style_lang
background: none
color: $white
font-weight: bold !important
border: 2px solid white
padding: 5px 10px
margin: 0
&:hover
background: $white
color: $main
.dropdown-menu
right: 0
left: auto
text-align: center
min-width: 100px
padding: 5px 0
.dropdown-menu>.active>a
background: $main
\ No newline at end of file
@import "shared/color"
.border
border: 1px solid black
.c_green
color: $main
.s_10
font-size: 10px
.line_1
line-height: 1
.without_padding
padding-left: 0 !important
padding-right: 0 !important
.mob_back
@media (max-width: 767px)
background-color: rgba(white, .4)
@import "shared/color"
@import "shared/mixin"
.mobile_menu
position: relative
top: 0
z-index: 100
display: none
border-top: 2px solid rgba($main, .21)
border-bottom: 2px solid rgba($main, .11)
+box-shadow(inset 0 0 8px -5px black)
text-align: center
background: white
.nav_menu
a
color: $main
border: 2px solid $main
+border-radius(5px)
padding: 2px 10px
.menu_open
display: block !important
.box_sandwich
.sandwich
position: absolute
top: 20px
right: 10px
cursor: pointer
+width_height(30px, 5px)
+border-radius(2px)
background: $main
z-index: 101
&:before, &:after
position: absolute
content: ''
+width_height(30px, 5px )
+border-radius(2px)
&:before
top: -8px
left: 0
background: $main
&:after
top: 8px
left: 0
background: $main
.close_sandwich
&:after, &:before
background: $main
background: white
&:after
top: 0
+transform(rotate(-45deg))
&:before
+transform(rotate(45deg))
top: 0
\ No newline at end of file
@import "shared/color"
.h_style
padding: 0 15px
border-bottom: 4px solid white
color: $main
font-weight: bold
margin-top: 60px
font-size: 60px
.h_style_no_border
padding: 0 15px
color: $main
font-weight: bold
margin-top: 60px
font-size: 60px
\ No newline at end of file
body {
background-color: #fff;
color: #333;
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
line-height: 18px;
}
p, ol, ul, td {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
line-height: 18px;
}
pre {
background-color: #eee;
padding: 10px;
font-size: 11px;
}
a {
color: #000;
&:visited {
color: #666;
}
&:hover {
color: #fff;
background-color: #000;
}
}
div {
&.field, &.actions {
margin-bottom: 10px;
}
}
#notice {
color: green;
}
.field_with_errors {
padding: 2px;
background-color: red;
display: table;
}
#error_explanation {
width: 450px;
border: 2px solid red;
padding: 7px;
padding-bottom: 0;
margin-bottom: 20px;
background-color: #f0f0f0;
h2 {
text-align: left;
font-weight: bold;
padding: 5px 5px 5px 15px;
font-size: 12px;
margin: -7px;
margin-bottom: 0px;
background-color: #c00;
color: #fff;
}
ul li {
font-size: 12px;
list-style: square;
}
}
/*
*= require_directory ./shared
*= require_self
*= require font-awesome
*/
//$green: #479724
$white: white
$black: #2A2A2A
$main: #67912f
$second: #c8f241
//$orange: #F6AE2D
$orange: #F7E565
\ No newline at end of file
////standart_veritables
$default_transition: all .2s ease
=transition($transition)
transition: $transition
-webkit-transition: $transition
-moz-transition: $transition
-o-transition: $transition
=box-shadow($box-shadow)
box-shadow: $box-shadow
-webkit-box-shadow: $box-shadow
-moz-box-shadow: $box-shadow
-o-box-shadow: $box-shadow
-ms-box-shadow: $box-shadow
= box-shadow_2($sha_1, $sha_2)
box-shadow: $sha_1, $sha_2
-webkit-box-shadow: $sha_1, $sha_2
-moz-box-shadow: $sha_1, $sha_2
-o-box-shadow: $sha_1, $sha_2
-ms-box-shadow: $sha_1, $sha_2
=border-radius($border-radius)
border-radius: $border-radius
-webkit-border-radius: $border-radius
-moz-border-radius: $border-radius
//border_box, content_box
=box-sizing($box_sizing)
-webkit-box-sizing: $box_sizing
-moz-box-sizing: $box_sizing
box-sizing: $box_sizing
=user_select($user_select)
-webkit-user-select: $user_select
-moz-user-select: $user_select
-ms-user-select: $user_select
user-select: $user_select
=transform($transform)
transform: $transform
-webkit-transform: $transform
-moz-transform: $transform
-o-transform: $transform
-ms-transform: $transform
=transform_2($transform_double_1, $transform_double_2)
transform: $transform_double_1 $transform_double_2
-webkit-transform: $transform_double_1 $transform_double_2
-moz-transform: $transform_double_1 $transform_double_2
-o-transform: $transform_double_1 $transform_double_2
-ms-transform: $transform_double_1 $transform_double_2
=transform_3( $transform_triple_1, $transform_triple_2, $transform_triple_3)
transform: $transform_triple_1 $transform_triple_2 $transform_triple_3
-webkit-transform: $transform_triple_1 $transform_triple_2 $transform_triple_3
-moz-transform: $transform_triple_1 $transform_triple_2 $transform_triple_3
-o-transform: $transform_triple_1 $transform_triple_2 $transform_triple_3
-ms-transform: $transform_triple_1 $transform_triple_2 $transform_triple_3
=ul_li($display, $vertical)
display: $display
vertical-align: $vertical
///////////////////////////////////////////////
=double_shadow($color)
+box-shadow((0 1px 0 lighten($color, 10%) inset, 0 -1px 0 darken($color, 10%) inset))
=hover-style($color)
&:hover
background: lighten($color, 3%)
= width_height($width, $height)
width: $width
height: $height
=appearance($appearance)
-webkit-appearance: $appearance
-moz-appearance: $appearance
appearance: $appearance
=transition_delay($transition_sub_1, $transition_sub_2 )
transition-delay: $transition_sub_1, $transition_sub_2
-o-transition-delay: $transition_sub_1, $transition_sub_2
-moz-transition-delay: $transition_sub_1, $transition_sub_2
-webkit-transition-delay: $transition_sub_1, $transition_sub_2
=transition_delay_single($transition_sub_1 )
transition-delay: $transition_sub_1
-o-transition-delay: $transition_sub_1
-moz-transition-delay: $transition_sub_1
-webkit-transition-delay: $transition_sub_1
=transition_2($tra_1, $tra_2)
transition: $tra_1, $tra_2
-webkit-transition: $tra_1, $tra_2
-moz-transition: $tra_1, $tra_2
-ms-transition: $tra_1, $tra_2
-o-transition: $tra_1, $tra_2
= animation_delay($animation_delay)
-webkit-animation-delay: $animation_delay
-moz-animation-delay: $animation_delay
-ms-animation-delay: $animation_delay
animation-delay: $animation_delay
=animation($content)
animation: $content
-webkit-animation: $content
-moz-animation: $content
-o-animation: $content
=keyframe($name)
@keyframes #{$name}
@content
@-moz-keyframes #{$name}
@content
@-webkit-keyframes #{$name}
@content
@-o-keyframes #{$name}
@content
=text-shadow($text_shadow)
text-shadow: $text_shadow
=transform_origin($origin-x, $origin-y)
-webkit-transform-origin: $origin-x, $origin-y
-moz-transform-origin: $origin-x, $origin-y
-o-transform-origin: $origin-x, $origin-y
-ms-transform-origin: $origin-x, $origin-y
transform-origin: $origin-x, $origin-y
=border($top, $bottom, $left, $right)
border-top-color: $top !important
border-bottom-color: $bottom !important
border-left-color: $left !important
border-right-color: $right !important
=position_center($position, $top, $left)
position: $position
top: $top
left: $left
+transform(translate(-50%, -50%))
=vertical_align($height)
&:before
content: ''
display: inline-block
vertical-align: middle
height: $height
width: .1px
=vertical_align_without_veritable()
&:before
content: ''
display: inline-block
vertical-align: middle
width: .1px
= clearfix()
&:before,&:after
content: ''
display: table
&:after
clear: both
= opacity($opacity)
opacity: $opacity
$opacity-ie: $opacity * 100
filter: alpha(opacity = $opacity-ie)
= link_settings($link, $visited, $hover, $active)
&:link
color: $link
&:visited
color: $visited
&:hover
color: $hover
&:active
color: $active
= normal_box($s)
width: $s
height: $s
line-height: $s
= perspective($size)
perspective: $size
-webkit-perspective: $size
-moz-perspective: $size
= letter-spacing($letter-spacing)
-webkit-letter-spacing: $letter-spacing
-moz-letter-spacing: $letter-spacing
-ms-letter-spacing: $letter-spacing
-o-letter-spacing: $letter-spacing
letter-spacing: $letter-spacing
/*
=require twitter-bootstrap-static/bootstrap
Use Font Awesome icons (default)
To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
=require twitter-bootstrap-static/fontawesome
*/
body.devise {
padding: 20px;
text-align: center;
.remember {
display: inline-block;
vertical-align: middle;
}
.form-group {
width: 220px;
margin: 0 auto 10px;
}
input[type=email], input[type=password], div:not(.remember) > label:first-child {
margin: 0 2px 0;
width: 220px;
text-align: left;
}
a {
line-height: 1.5;
}
input[type=submit] {
max-width: 200px;
white-space: normal;
margin-top: 10px;
margin-bottom: 20px;
}
.logo img {
max-width: 80%;
max-height: 100px;
}
}
\ No newline at end of file
class AccountsController < AdminController
before_action :set_account, only: [:show, :edit, :update, :destroy]
def index
@accounts = paginated tabular_filter.add_keys_replacements({email: 'accounts.email', on_hold: 'accounts.on_hold',
admin: 'if(administrators.id is not null, 1, 0)'}).apply(Account.with_admins.order :email)
end
def new
@account = Account.new
end
def show
end
def edit
end
def create
@account = Account.new(account_params)
respond_to do |format|
if @account.save
format.html { redirect_to @account, notice: 'Account was successfully created.' }
format.json { render :show, status: :created, location: @account }
else
format.html { render :new }
format.json { render json: @account.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @account.update(account_params)
format.html { redirect_to @account, notice: 'Account was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @account.errors, status: :unprocessable_entity }
end
end
end
def destroy
respond_to do |format|
if @account.administrator.nil? || @account.on_hold? || Administrator.active.count > 1
@account.destroy
format.html { redirect_to accounts_url, notice: 'Account was successfully destroyed.' }
format.json { head :no_content }
else
format.html { redirect_to accounts_url, alert: 'You cannot destroy last active admin.' }
format.json { head :no_content }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_account
@account = Account.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def account_params
if params[:account][:password].blank?
params[:account][:password] = nil
params[:account][:password_confirmation] = nil
end
params.require(:account).permit(:email, :investment, :percentage_attendant, :on_hold, :subscribed, :admin, :password, :password_confirmation)
end
end
class AdminController < ApplicationController
def index
# console
end
def links_pinned
current_account.administrator.update links_pinned: params[:pinned]
render nothing: true
end
def paginated(scope)
scope.paginate(page: params[:page], per_page: 20)
end
helper_method :tabular_filter
def tabular_filter
@tabular_filter ||= TabularFilter.new(params)
end
end
class AmountSendsController < ApplicationController
before_action :set_amount_send, only: [:show, :edit, :update, :destroy]
# GET /amount_sends
# GET /amount_sends.json
def index
@amount_sends = AmountSend.all
end
# GET /amount_sends/1
# GET /amount_sends/1.json
def show
end
# GET /amount_sends/new
def new
@amount_send = AmountSend.new
end
# GET /amount_sends/1/edit
def edit
end
# POST /amount_sends
# POST /amount_sends.json
def create
@amount_send = AmountSend.new(amount_send_params)
respond_to do |format|
if @amount_send.save
format.html {redirect_to @amount_send, notice: 'Amount send was successfully created.'}
format.json {render :show, status: :created, location: @amount_send}
else
format.html {render :new}
format.json {render json: @amount_send.errors, status: :unprocessable_entity}
end
end
end
# PATCH/PUT /amount_sends/1
# PATCH/PUT /amount_sends/1.json
def update
respond_to do |format|
if @amount_send.update(amount_send_params)
format.html {redirect_to @amount_send, notice: 'Amount send was successfully updated.'}
format.json {render :show, status: :ok, location: @amount_send}
else
format.html {render :edit}
format.json {render json: @amount_send.errors, status: :unprocessable_entity}
end
end
end
# DELETE /amount_sends/1
# DELETE /amount_sends/1.json
def destroy
@amount_send.destroy
respond_to do |format|
format.html {redirect_to amount_sends_url, notice: 'Amount send was successfully destroyed.'}
format.json {head :no_content}
end
end
def set_transaction
Node.all.each do |a|
listunspent = listunspent(a)
listunspent.keys.each do |b|
if listunspent["#{b}"] > a.start_balance_t + 0.001
AmountSend.create(from: a.taddress, to: Setting.stk_node_address, amount: listunspent["#{b}"].to_f - 0.0001, node_id: a.id)
end
end
end
redirect_to nodes_path, notice: 'Transaction is create.'
end
def correction_amount(num)
return (num.to_s.split('.')[0] + "." + num.to_s.split('.')[1][0..3])
end
def pick_up_amount
AmountSend.need_to_send.each do |a|
node_id = Node.find_by(id: a.node_id)
h = BitcoinRPC.new("http://#{node_id.node_username}:#{node_id.node_password}@#{node_id.ipv4}:8231")
check = h.z_sendmany "#{a.from}", [{'address': "#{a.to}", 'amount': a.amount}]
if check.nil?
a.update(status: 'fail')
else
a.update(status: 'success')
end
end
redirect_to nodes_path, notice: 'Pick up amount.'
end
def preparation_return
Node.all.each do |a|
balance = (a.start_balance_t - a.balance_t).to_f
if balance > 0
AmountSend.create(from: Setting.stk_node_address, to: a.taddress, amount: a.start_balance_t + 0.0001, status: 'return')
end
end
redirect_to nodes_path, notice: 'Preparation return.'
end
# def return_amount
# AmountSend.need_to_return.each do |a|
# h = BitcoinRPC.new('http://nazspsnaz:3QipttwhoStEXqhLZBF56iiahPjAHADFkbm@45.77.137.182:8231')
# check = h.sendtoaddress a.to, "#{a.amount}"
# if check.nil?
# a.update(status: 'fail')
# else
# a.update(status: 'success')
# end
# end
# redirect_to nodes_path, notice: 'Return amount.'
# end
private
def listunspent(node)
h = BitcoinRPC.new("http://#{node.node_username}:#{node.node_password}@#{node.ipv4}:8231")
listunspent = h.listunspent
address = Hash.new()
if listunspent.nil?
return nil
else
listunspent.each do |a|
if address.keys.include?("a[\"address\"]")
address[a["address"]] = a["amount"]
else
address[a["address"]] = address[a["address"]].to_f + a["amount"]
end
end
return address
end
end
# Use callbacks to share common setup or constraints between actions.
def set_amount_send
@amount_send = AmountSend.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def amount_send_params
params.require(:amount_send).permit(:from, :to, :amount, :amount, :status)
end
end
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :check_administrator, unless: :devise_controller?
before_filter :set_locale
helper_method :current_url_for_locale
def current_url_for_locale(locale)
request.get? ? url_for(params.merge(locale: locale)) : url_for(locale: locale)
end
protected
def check_administrator
if current_account.nil?
authenticate_account!
elsif current_account.administrator.nil?
redirect_to root_url, alert: 'You have not enough rights to do it!'
end
end
def extract_best_locale
if request.env['HTTP_ACCEPT_LANGUAGE']
return request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first || I18n.default_locale
end
I18n.default_locale
end
def set_locale
ActionMailer::Base.default_url_options = {:host => request.host_with_port}
params[:locale] = extract_best_locale if params[:locale].nil?
if I18n.available_locales.include?(params[:locale].to_sym)
current_account.update(locale: params[:locale]) if current_account && current_account.locale != params[:locale]
I18n.locale = params[:locale]
else
flash.now[:notice] = "#{params[:locale]} translation not available"
logger.error flash.now[:notice]
end
end
def self.default_url_options(options={})
options.merge({locale: I18n.available_locales.length > 1 ? I18n.locale: nil})
end
end
class BlocksController < AdminController
before_action :set_block, only: [:edit, :update]
layout false
def edit
end
def update
replace_line_breaks
update_block_by_version
respond_to do |format|
format.js
end
end
def apply
BlockVersion.by_admin(current_account).last.activate
respond_to do |format|
format.js { render nothing: true, status: 200 }
format.html { redirect_to :back }
end
end
def cancel
last_block_version = BlockVersion.by_admin(current_account).last
if last_block_version.present? and !last_block_version.active
last_block_version.blocks.destroy_all
end
respond_to do |format|
format.js { render nothing: true, status: 200 }
format.html { redirect_to :back }
end
end
private
def set_block
@block = Block.last_for_admin(params[:id], current_account)
end
def block_params
params.require(:block).permit(:key, localed_attr(:text))
end
def replace_line_breaks
locales.each do |locale|
split_text = params[:block]["text_#{locale}"].split(/\r\n|\n\r|\r|\n/)
params[:block]["text_#{locale}"] = split_text.map {|p| p.blank? ? '<br>' : "<p>#{p}</p>"}.join
end
end
def update_block_by_version
full_params = block_params
full_params[:key] = params[:id]
if @block.block_version.active?
block_version = BlockVersion.find_or_create_by(account: current_account, active: false)
@block = Block.new(key: params[:id], block_version: block_version)
@prev_block = Block.active.by_key(params[:id]).last
if @prev_block
@prev_block.text_phrase.translations.each do |translation|
full_params["text_#{translation.locale}"] = translation.text if translation.locale != I18n.locale.to_s
end
end
end
@block.update(full_params)
end
end
module Sortable
extend ActiveSupport::Concern
included do
before_action :update_position, only: :update
end
def update_position
if params.has_key?(:position)
item = controller_name.classify.constantize.find(params[:id])
item.insert_at(params[:position].to_i)
render nothing: true, status: :ok
false
end
end
end
\ No newline at end of file
class TabularFilter
include ActionView::Helpers
def initialize(params)
filters_params = params.select{|key| key.to_s.match(/tf.?_.+/)}
@filters = Hash[filters_params.map{|k,v| [k.to_s.match(/tf.?_(.+)/)[1],{value: v, mode: k.to_s.match(/tf(.?)_.+/)[1]}]}]
@keys_replacements = {}
@joins = {}
end
def translations(*translated_columns)
relations Hash[translated_columns.map { |c| [c, '.:t'] }]
end
def relations(args)
# EXAMPLE: {manager: 'accounts.name', client: 'accounts.name', ware: 'wares.name:t', name: '.:t'}
args.keys.each do |key|
value = args[key].split('.')
table_name = value[0]
join_table_name = key.to_s.pluralize
column_params = value[1].split(':')
column_name = column_params[0]
translatable = false
if column_params.length > 1 && column_params[1]=='t'
translatable = true
join_table_name += "_#{column_name}_translations"
end
@joins[key] = {table_name: table_name, join_table_name: join_table_name, column: key, join_column: column_name,
translatable: translatable}
add_keys_replacements(key => "#{join_table_name}.#{translatable ? 'text' : column_name}")
end
self
end
def add_keys_replacements(keys)
@keys_replacements.merge! keys
self
end
def apply(scope, args = {})
decode_apply_args(args)
@table_name = scope.table.name
active? ? add_joins(scope).where(condition).uniq : scope
end
def decode_apply_args(args)
@skip = []
if args.has_key? :skip
if args[:skip].is_a? Array
args[:skip].each { |value| @skip << value }
else
@skip << args[:skip].to_sym
end
end
end
def add_joins(scope)
@joins.each do |key, join_data|
next if @skip.include? key.to_sym
jt_column = join_data[:join_column]
jt_name = join_data[:join_table_name]
if jt_column.empty?
jt_column = join_data[:column]
jt = @table_name
column = 'id'
else
jt = join_data[:table_name]
column = join_data[:column].to_s + '_id'
end
if join_data[:translatable]
scope = scope.
joins "LEFT JOIN phrase_containers `#{jt}_containers` ON `#{jt}_containers`.`translatable_id` = `#{@table_name}`.`#{column}` AND `#{jt}_containers`.`translatable_type`='#{jt.classify}' AND `#{jt}_containers`.`attribute_name`='#{jt_column}'",
"LEFT JOIN `phrases` `#{jt}_phrases` ON `#{jt}_phrases`.`id` = `#{jt}_containers`.`phrase_id`",
"LEFT JOIN `translations` `#{jt_name}` ON `#{jt_name}`.`phrase_id` = `#{jt}_phrases`.`id` AND `#{jt_name}`.`locale` = '#{I18n.locale}'"
else
scope = scope.
joins "LEFT JOIN `#{jt}` `#{jt_name}` ON `#{jt_name}`.`id` = `#{@table_name}`.`#{column}`"
end
end
scope
end
def condition
condition = ''
@filters.keys.each do |key|
return 'false' if @skip.include? key.to_sym
condition << ' and ' unless condition.blank?
condition << key_condition(key)
end
condition
end
def key_condition(key)
@key = key
condition = ''
sub_keys = key.split(':').map(&:to_sym).map { |k| @keys_replacements.include?(k) ? @keys_replacements[k] : k }
(0..sub_keys.length - 1).each do
condition << ' or ' unless condition.blank?
condition << current_keys_condition(sub_keys)
sub_keys << sub_keys.shift
end
"(#{condition})"
end
def current_keys_condition(keys)
condition = ''
values = @filters[@key][:value].split(' ')
(0..values.length - 1).each do
condition << ' or ' unless condition.blank?
condition << current_values_condition(keys, values)
values << values.shift
end
condition
end
def current_values_condition(keys, values)
condition = ''
(0..[values.length, keys.length].min - 1).each do |i|
condition << ' and ' unless condition.blank?
condition << value_condition(keys[i], values[i])
end
"(#{condition})"
end
#noinspection RubyAssignmentExpressionInConditionalInspection
def value_condition(key, value)
col_name = key.to_s
col_name = "#{@table_name}.#{col_name}" if col_name.gsub(/\./).count == 0
case @filters[@key][:mode]
when 'd'
date = value.to_datetime
"(#{col_name} BETWEEN '#{date.beginning_of_day.to_s(:db)}' AND '#{date.end_of_day.to_s(:db)}')"
when 'b'
value == '1' ? "(#{col_name} = 1)" : "(#{col_name} = 0 OR #{col_name} IS NULL)"
else
if value == '!*'
return "(#{col_name} is null or #{col_name}='')"
elsif value == '*'
return "(#{col_name} is not null and #{col_name}<>'')"
elsif match = /^(==)(\d*.\d*)$/.match(value)
return "(#{col_name}=#{match[2]})"
elsif match = /^(<>)(\d*.\d*)$/.match(value)
return "(#{col_name}!=#{match[2]})"
elsif match = /^(!=|[><=])(\d*.\d*)$/.match(value)
return "(#{col_name}#{match[1]}#{match[2]})"
end
"#{col_name} like '%#{value}%'"
end
end
def active?
!@filters.empty?
end
def empty?
@filters.empty?
end
def row_helper(*args)
out = "<tr id='filters'>"
put = true
args = args[0] if args[0].is_a? Array
args.each_with_index do |param, i|
param = 1 if param == '-' || param == ''
if param.is_a? Integer
if i == args.size - 1
if block_given?
out << "<th class='actions' colspan='#{param}'>#{yield}</th>"
else
out << "<th class='actions' colspan='#{param}'>#{link_to '', '?', class: 'clear_btn clear_tabular_filters',
title: t('helpers.links.clear', default: 'Clear')}</th>"
end
else
out << "<th colspan='#{param}'></th>" if put
end
put = true
elsif !!param == param
put = param
elsif param.is_a? Hash
param.keys.each do |key|
out << generate_control(param[key], key) if put
end
else
param_parts = param.to_s.split(':')
type = param_parts.length > 1 ? param_parts[1].to_sym : :text
out << generate_control(type, param_parts[0]) if put
put = true
end
end
out << '</tr>'
out.html_safe
end
private
def generate_control(type, param)
case type
when :text, :string, :as_text, :as_string
"<th>#{field_helper param}</th>"
when :bool, :boolean, :as_bool, :as_boolean
"<th>#{yes_no_helper param}</th>"
when :date, :as_date
"<th>#{date_helper param}</th>"
else
'<th></th>'
end
end
def field_helper(attr)
text_field_tag attr, value_for(attr), class: 'filter'
end
def yes_no_helper(attr)
select_tag attr, options_for_select([[t('humanizers.bool.true'), 1], [t('humanizers.bool.false'), 0]], value_for(attr)),
include_blank: true, class: 'filter boolean'
end
def date_helper(attr)
text_field_tag attr, value_for(attr), class: 'filter date_picker'
end
def value_for(attr)
@filters.has_key?(attr) ? @filters[attr][:value] : ''
end
end
class FrontController < ApplicationController
skip_before_action :check_administrator
def index
@pages = Page.active.anchors
end
def page
@page = Page.find_by(url_id: params[:id]) || Page.find(params[:id])
end
end
class ImagesController < ApplicationController
before_action :set_image
layout false
def show
render_image
end
def edit
end
def update
if @image.update image_params
render_image
else
render nothing: true, status: :internal_server_error
end
end
private
def render_image
render html: "<img src='#{@image.data_url}'/>".html_safe, status: :ok
end
# Use callbacks to share common setup or constraints between actions.
def set_image
@image = Image.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def image_params
params[:image] = {remove_data: true} if params[:image].nil?
params.require(:image).permit(:data, :remove_data)
end
end
class NewslettersController < AdminController
before_action :set_newsletter, only: [:show, :edit, :update, :destroy, :sending, :resend]
# GET /newsletters
# GET /newsletters.json
def index
@newsletters = Newsletter.all
end
# GET /newsletters/1
# GET /newsletters/1.json
def show
end
# GET /newsletters/new
def new
@newsletter = params.has_key?(:newsletter) ? Newsletter.new(newsletter_params) : Newsletter.new
end
# GET /newsletters/1/edit
def edit
end
# POST /newsletters
# POST /newsletters.json
def create
@newsletter = Newsletter.new(newsletter_params)
respond_to do |format|
if @newsletter.save
format.html { redirect_to @newsletter, notice: 'Newsletter was successfully created.' }
format.json { render :show, status: :created, location: @newsletter }
else
format.html { render :new }
format.json { render json: @newsletter.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /newsletters/1
# PATCH/PUT /newsletters/1.json
def update
respond_to do |format|
if @newsletter.update(newsletter_params)
format.html { redirect_to @newsletter, notice: 'Newsletter was successfully updated.' }
format.json { render :show, status: :ok, location: @newsletter }
else
format.html { render :edit }
format.json { render json: @newsletter.errors, status: :unprocessable_entity }
end
end
end
# DELETE /newsletters/1
# DELETE /newsletters/1.json
def destroy
@newsletter.destroy
respond_to do |format|
format.html { redirect_to newsletters_url, notice: 'Newsletter was successfully destroyed.' }
format.json { head :no_content }
end
end
def resend
@newsletter.update(last_id: nil)
redirect_to send_newsletter_url
end
def sending
if @newsletter.last_id.nil?
init_newsletter
elsif @newsletter.processed_id < @newsletter.last_id
sending_newsletter
end
end
private
def init_newsletter
@newsletter.update(last_id: filtered_accounts.last.id, processed_id: 0)
end
def filtered_accounts
Account.where(subscribed: true).for_filter.where(@newsletter.recipient_filter).order(:id)
end
def sending_newsletter
@accounts = filtered_accounts.where('accounts.id > ?', @newsletter.processed_id).first(100)
begin
FrontMailer.newsletter(@newsletter.text_for_request(request), @accounts.map(&:email), @newsletter.subject).deliver_now
rescue Exception => error
Rails.logger.error("Error on send newsletter to #{error.message}")
end
params = {processed_id: @accounts.last.id}
if @accounts.last.id >= @newsletter.last_id
params[:processed_at] = DateTime.current
params[:last_id] = @accounts.last.id
end
@newsletter.update(params)
end
# Use callbacks to share common setup or constraints between actions.
def set_newsletter
@newsletter = Newsletter.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def newsletter_params
params.require(:newsletter).permit(:subject, :text, :date, :recipient_filter)
end
end
class NodesController < AdminController
before_action :set_node, only: [:show, :edit, :update, :destroy]
# GET /nodes
# GET /nodes.json
def index
@nodes = Node.all
@nodelist = AmountSend.need_to_return.map do |u|
{ :address => u.to, :amount => u.amount}
end
@command = "z_sendmany " + "#{Setting.stk_node_address} " + "'#{@nodelist.to_json}'"
end
# GET /nodes/1
# GET /nodes/1.json
def show
listunspent(@node)
end
# GET /nodes/new
def new
@node = Node.new
end
# GET /nodes/1/edit
def edit
end
# POST /nodes
# POST /nodes.json
def create
@node = Node.new(node_params)
respond_to do |format|
if @node.save
format.html {redirect_to @node, notice: 'Node was successfully created.'}
format.json {render :show, status: :created, location: @node}
else
format.html {render :new}
format.json {render json: @node.errors, status: :unprocessable_entity}
end
end
end
# PATCH/PUT /nodes/1
# PATCH/PUT /nodes/1.json
def update
respond_to do |format|
if @node.update(node_params)
format.html {redirect_to @node, notice: 'Node was successfully updated.'}
format.json {render :show, status: :ok, location: @node}
else
format.html {render :edit}
format.json {render json: @node.errors, status: :unprocessable_entity}
end
end
end
# DELETE /nodes/1
# DELETE /nodes/1.json
def destroy
@node.destroy
respond_to do |format|
format.html {redirect_to nodes_url, notice: 'Node was successfully destroyed.'}
format.json {head :no_content}
end
end
def set_t_address
Node.all.each do |a|
if listunspent(a) != nil
listunspent = listunspent(a)
p listunspent
listunspent.keys.each do |b|
if listunspent["#{b}"] > a.start_balance_t
a.update(taddress: b)
end
end
end
end
redirect_to nodes_url
end
def z_gettotalbalance
Node.all.each do |a|
h = BitcoinRPC.new("http://#{a.node_username}:#{a.node_password}@#{a.ipv4}:8231")
getinfo = h.z_gettotalbalance
if getinfo.nil?
Node.find_by_id(a.id).update({:balance_t => 101, :balance_z => 101})
else
Node.find_by_id(a.id).update({:balance_t => getinfo["transparent"], :balance_z => getinfo["private"]})
end
end
redirect_to nodes_path
end
def return_amount
@nodelist = AmountSend.need_to_return.map do |u|
{ :address => u.to, :amount => u.amount}
u.update(status: 'success')
end
@command = "z_sendmany " + "#{Setting.stk_node_address} " + "'#{@nodelist.to_json}'"
redirect_to nodes_path
end
# def update_node_status(id)
# id.update(status: 'success')
# end
def listunspent(node)
h = BitcoinRPC.new("http://#{node.node_username}:#{node.node_password}@#{node.ipv4}:8231")
listunspent = h.listunspent
address = Hash.new()
if listunspent.nil?
@address = nil
else
listunspent.each do |a|
if address.keys.include?("a[\"address\"]")
address[a["address"]] = a["amount"]
else
address[a["address"]] = address[a["address"]].to_f + a["amount"]
end
end
@address = address
end
end
def sync_node
Node.sync_node
redirect_to nodes_path
end
private
# Use callbacks to share common setup or constraints between actions.
def set_node
@node = Node.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def node_params
params.require(:node).permit(:name, :domain, :ipv4, :ipv6, :node_username, :node_password, :taddress, :zaddress, :start_balance_t, :start_balance_z, :balance_t, :balance_z, :server_provider)
end
end
class PagesController < AdminController
before_action :set_page, only: [:show, :edit, :update, :destroy]
include Sortable
# GET /pages
def index
@pages = Page.all
end
# GET /pages/1
def show
end
# GET /pages/new
def new
@page = Page.new
end
# GET /pages/1/edit
def edit
end
# POST /pages
# POST /pages.json
def create
@page = Page.new(page_params)
respond_to do |format|
if @page.save
format.html { redirect_to @page, notice: 'Page was successfully created.' }
else
format.html { render :new }
end
end
end
# PATCH/PUT /pages/1
# PATCH/PUT /pages/1.json
def update
respond_to do |format|
if @page.update(page_params)
format.html { redirect_to @page, notice: 'Page was successfully updated.' }
else
format.html { render :edit }
end
end
end
# DELETE /pages/1
# DELETE /pages/1.json
def destroy
@page.destroy
respond_to do |format|
format.html { redirect_to pages_url, notice: 'Page was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_page
@page = Page.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def page_params
params.require(:page).permit(localed_attr(:title), :position, :mode, (:path if params[:page][:mode] == 'path'),
(:link if params[:page][:mode] == 'link'), localed_attr(:body), :url_id, :enabled, :keywords, localed_attr(:description))
end
end
class SettingsController < AdminController
before_action :set_setting, only: [:update, :destroy, :image_form]
# GET /settings
# GET /settings.json
def index
@settings = Setting.init.all
end
# PATCH/PUT /settings/1
# PATCH/PUT /settings/1.json
def update
respond_to do |format|
if @setting.update(setting_params)
format.html { redirect_to settings_url, notice: 'Setting was successfully updated.' }
format.json { render json: {}, status: :ok }
else
format.json { render json: @setting.errors, status: :unprocessable_entity }
end
end
end
# DELETE /settings/1
# DELETE /settings/1.json
def destroy
@setting.destroy
respond_to do |format|
format.html { redirect_to settings_url, notice: 'Setting was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_setting
@setting = Setting.find_by(name: params[:id]) || Setting.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def setting_params
params.require(:setting).permit(:value)
end
end
module AdminHelper
def current_admin_path
return @current_admin_path if @current_admin_path
if params['controller'] == 'admin' && params['action'] == 'index'
@current_admin_caption = t('activerecord.attributes.page.links.admin_area')
@current_admin_path = link_to @current_admin_caption, admin_index_path, class: 'navbar-brand'
else
model = controller_name.singularize.classify.constantize
@current_admin_caption = model ? model.model_name.human(count: 2).mb_chars.titleize : controller_name.humanize
@current_admin_path = link_to @current_admin_caption, controller_path, class: 'navbar-brand'
end
end
def current_admin_caption
current_admin_path unless @current_admin_caption
@current_admin_caption
end
end
module AmountSendsHelper
end
module ApplicationHelper
def truncate_html(html, length, &block)
truncate html.nil? ? '' : sanitize(html, tags: {}).squish , length: length, separator: ' ', &block
end
def is_administrator?
current_account.present? && current_account.administrator.present?
end
def show_amount(amount)
"#{((amount || 0) * Bank::SATOSHI_COEFF).round} <strong>SATOSHI</strong>".html_safe
end
def to_d digits_after_dot, value
if value.present?
"%.#{digits_after_dot}f" % value
else
value
end
end
def localize_datetime(date)
"#{l date.to_date} #{date.strftime('%H:%M:%S')}" if date.present?
end
def timer_timeslot(seconds)
[60, 60, 1000].map { |count| seconds, n = seconds.divmod(count); n.to_s.rjust(2, '0') }.reverse.join(':')
end
def humanize_timeslot(seconds)
[[60, 'second'], [60, 'minute'], [24, 'hour'], [1000, 'day']].map { |count, name|
if seconds > 0
seconds, n = seconds.divmod(count)
n > 0 ? pluralize(n.to_i, name) : nil
end
}.compact.reverse.join(', ')
end
end
module BlocksHelper
def block_tag(key, options=nil, &block)
text = block_given? ? capture(&block) : nil
if account_signed_in?
b = Block.last_for_admin(key, current_account, text)
else
b = Block.last(key, text)
end
b.apply_options(options).html
end
def blocks_changing_allowed?
account_signed_in? && current_account.administrator.present?
end
def blocks_changed?
last_version = BlockVersion.by_admin(current_account).last
blocks_changing_allowed? and last_version.present? and !last_version.active and last_version.blocks.present?
end
end
module CertificatesHelper
end
module FrontHelper
def title(title)
content_for :title do
[title, Setting.title].compact.join(' | ')
end
end
def description(description)
content_for :description do
description.present? ? description : Setting.description
end
end
def keywords(keywords)
content_for :keywords do
keywords.present? ? keywords : Setting.keywords
end
end
def og_image(value)
content_for(:og_image) { full_path value }
end
def og_type(value)
content_for(:og_type) { value }
end
def og_url(value)
content_for(:og_url) { value }
end
def full_path(path)
"#{request.protocol + request.host_with_port + path.to_s}"
end
def recently_rated?(rate_data)
rate_data && Time.now.to_i - rate_data['rated_at'] < 86400 #- 24 hours
end
def balance
"#{(current_account ? current_account.reload.balance * Bank::SATOSHI_COEFF : 0).to_i} s"
end
def today_played_games
current_account.operating_date == Date.today ? current_account.played_games : 0
end
def expected_revenue
left_days > 0 ? Setting.all_days_bonus : Setting.one_day_bonus
end
def left_days
account = current_account
continuous_days = account.operating_date && account.operating_date >= Date.yesterday ? account.continuous_days : 0
left_days = Setting.days_for_bonus - continuous_days
[left_days, 0].max
end
end
module NodesHelper
def sum_investment
investment_balance = 0
Account.all.each do |a|
investment_balance += a.investment
end
return investment_balance
end
def sum_full_balance
full_balance = 0
Node.all.each do |a|
full_balance += a.balance_t + a.balance_z
end
return full_balance
end
def sum_not_involved_funds
return sum_start_balance - sum_full_balance
end
def sum_start_balance
start_balance = 0
Node.all.each do |a|
start_balance += a.start_balance_t + a.start_balance_z
end
return start_balance
end
def calc_percentage_attendant
sum_full_balance - sum_investment
end
def sum_attendant_profit
sum_attendant_profit = 0
Account.all.each do |a|
sum_attendant_profit += (sum_full_balance - sum_investment) * a.percentage_attendant / 100
end
return sum_attendant_profit
end
def user_profits
user_profits = Hash.new()
Account.all.each do |a|
user_profits[a.id] = (sprintf("%8.2f", (a.investment / (sum_investment) * (sum_full_balance - sum_attendant_profit)) - a.investment))
end
return user_profits
end
def attendant_profit
attendant_profit = Hash.new()
Account.all.each do |a|
attendant_profit[a.id] = (sum_full_balance - sum_investment) * a.percentage_attendant / 100
end
return attendant_profit
end
end
module PagesHelper
def link_to_page(page)
link_to(page.title, page_url_for(page), target: (:_blank if page.mode == 'link')).html_safe
end
def page_url_for(page)
if page.mode == 'page'
front_page_path(page.url)
elsif page.mode == 'anchor'
root_path anchor: "page_#{page.url}"
elsif page.mode == 'path'
send Page.links[page.link.to_sym]
else
page.link
end
end
end
module ServicesHelper
end
module SettingsHelper
def generate_setting_data(setting)
data = {name: :value}
case setting.format
when :image
form = simple_form_for setting.real_value do |f|
f.file_field :data, accept: 'image/*'
end
data.merge!({image: form})
when :bool
select_data = options_for_select([[t('no'), 0], [t('yes'), 1]])
data.merge!({select: select_data})
else
nil
end
data
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment