mirror of
https://github.com/internetee/registry.git
synced 2025-05-20 03:09:36 +02:00
Merge pull request #133 from internetee/story/115762063-show-historical-nested
Story/115762063 show historical nested
This commit is contained in:
commit
43df10ccaa
19 changed files with 845 additions and 126 deletions
|
@ -9,5 +9,6 @@
|
||||||
#= require shared/jquery.validate.bootstrap
|
#= require shared/jquery.validate.bootstrap
|
||||||
#= require jquery-ui/datepicker
|
#= require jquery-ui/datepicker
|
||||||
#= require select2
|
#= require select2
|
||||||
|
#= require jquery.doubleScroll
|
||||||
#= require shared/general
|
#= require shared/general
|
||||||
#= require admin/application
|
#= require admin/application
|
||||||
|
|
|
@ -16,3 +16,35 @@ $(document).on 'page:change', ->
|
||||||
$(this).validate()
|
$(this).validate()
|
||||||
|
|
||||||
$('[data-toggle="popover"]').popover()
|
$('[data-toggle="popover"]').popover()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# doublescroll
|
||||||
|
$('[data-doublescroll]').doubleScroll({
|
||||||
|
onlyIfScroll: false,
|
||||||
|
scrollCss:
|
||||||
|
'overflow-x': 'auto'
|
||||||
|
'overflow-y': 'hidden'
|
||||||
|
contentCss:
|
||||||
|
'overflow-x': 'auto'
|
||||||
|
'overflow-y': 'hidden'
|
||||||
|
resetOnWindowResize: true
|
||||||
|
})
|
||||||
|
|
||||||
|
positionSlider = ->
|
||||||
|
for scroll in document.querySelectorAll('[data-doublescroll]')
|
||||||
|
wrapper = scroll.previousSibling
|
||||||
|
if $(scroll).offset().top < $(window).scrollTop()
|
||||||
|
wrapper.style.position = 'fixed'
|
||||||
|
wrapper.style.top = '-5px'
|
||||||
|
else
|
||||||
|
wrapper.style.position = 'relative'
|
||||||
|
wrapper.style.top = '0'
|
||||||
|
return
|
||||||
|
|
||||||
|
positionSlider()
|
||||||
|
$(window).scroll(positionSlider).resize positionSlider
|
||||||
|
#due .report-table width: auto top scrollbar appears after resize so we do fake resize action
|
||||||
|
$(window).resize()
|
||||||
|
|
||||||
|
|
46
app/controllers/admin/contact_versions_controller.rb
Normal file
46
app/controllers/admin/contact_versions_controller.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
class Admin::ContactVersionsController < AdminController
|
||||||
|
load_and_authorize_resource
|
||||||
|
|
||||||
|
def index
|
||||||
|
params[:q] ||= {}
|
||||||
|
|
||||||
|
@q = ContactVersion.search(params[:q])
|
||||||
|
@versions = @q.result.page(params[:page])
|
||||||
|
search_params = params[:q].deep_dup
|
||||||
|
|
||||||
|
whereS = "1=1"
|
||||||
|
|
||||||
|
search_params.each do |key, value|
|
||||||
|
next if value.empty?
|
||||||
|
case key
|
||||||
|
when 'event'
|
||||||
|
whereS += " AND event = '#{value}'"
|
||||||
|
else
|
||||||
|
whereS += create_where_string(key, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
versions = ContactVersion.includes(:item).where(whereS)
|
||||||
|
@q = versions.search(params[:q])
|
||||||
|
@versions = @q.result.page(params[:page])
|
||||||
|
@versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
per_page = 7
|
||||||
|
@version = ContactVersion.find(params[:id])
|
||||||
|
@q = ContactVersion.where(item_id: @version.item_id).order(created_at: :asc).search
|
||||||
|
@versions = @q.result.page(params[:page])
|
||||||
|
@versions = @versions.per(per_page)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search
|
||||||
|
render json: ContactVersion.search_by_query(params[:q])
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_where_string(key, value)
|
||||||
|
" AND object->>'#{key}' ~ '#{value}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,18 +1,61 @@
|
||||||
class Admin::DomainVersionsController < AdminController
|
class Admin::DomainVersionsController < AdminController
|
||||||
load_and_authorize_resource
|
load_and_authorize_resource
|
||||||
|
|
||||||
# rubocop:disable Style/GuardClause
|
|
||||||
def index
|
def index
|
||||||
@domain = Domain.where(id: params[:domain_id]).includes({versions: :item}).first
|
params[:q] ||= {}
|
||||||
@versions = @domain.versions
|
|
||||||
|
|
||||||
# Depricated it had to load legal document. We may do it by parsing and adding link.
|
@q = DomainVersion.includes(:item).search(params[:q])
|
||||||
# if @domain.pending_json.present?
|
@versions = @q.result.page(params[:page])
|
||||||
# frame = Nokogiri::XML(@domain.pending_json['frame'])
|
search_params = params[:q].deep_dup
|
||||||
# @pending_user = User.find(@domain.pending_json['current_user_id'])
|
|
||||||
# @pending_domain = Epp::Domain.find(@domain.id)
|
if search_params[:registrant]
|
||||||
# @pending_domain.update(frame, @pending_user, false)
|
registrant = Contact.find_by(name: search_params[:registrant])
|
||||||
# end
|
search_params.delete(:registrant)
|
||||||
end
|
end
|
||||||
# rubocop:enable Style/GuardClause
|
|
||||||
|
if search_params[:registrar]
|
||||||
|
registrar = Registrar.find_by(name: search_params[:registrar])
|
||||||
|
search_params.delete(:registrar)
|
||||||
|
end
|
||||||
|
|
||||||
|
whereS = "1=1"
|
||||||
|
|
||||||
|
search_params.each do |key, value|
|
||||||
|
next if value.empty?
|
||||||
|
case key
|
||||||
|
when 'event'
|
||||||
|
whereS += " AND event = '#{value}'"
|
||||||
|
else
|
||||||
|
whereS += create_where_string(key, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
whereS += " AND object->>'registrant_id' = '#{registrant.id}'" if registrant
|
||||||
|
whereS += " AND object->>'registrar_id' = '#{registrar.id}'" if registrar
|
||||||
|
|
||||||
|
versions = DomainVersion.includes(:item).where(whereS)
|
||||||
|
@q = versions.search(params[:q])
|
||||||
|
@versions = @q.result.page(params[:page])
|
||||||
|
@versions = @versions.per(params[:results_per_page]) if params[:results_per_page].to_i > 0
|
||||||
|
render "admin/domain_versions/archive"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
per_page = 7
|
||||||
|
@version = DomainVersion.find(params[:id])
|
||||||
|
@q = DomainVersion.where(item_id: @version.item_id).order(created_at: :desc).search
|
||||||
|
@versions = @q.result.page(params[:page])
|
||||||
|
@versions = @versions.per(per_page)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search
|
||||||
|
render json: DomainVersion.search_by_query(params[:q])
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_where_string(key, value)
|
||||||
|
" AND object->>'#{key}' ~ '#{value}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -77,6 +77,11 @@ class Admin::DomainsController < AdminController
|
||||||
redirect_to [:admin, @domain]
|
redirect_to [:admin, @domain]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def versions
|
||||||
|
@domain = Domain.where(id: params[:domain_id]).includes({versions: :item}).first
|
||||||
|
@versions = @domain.versions
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_domain
|
def set_domain
|
||||||
|
|
|
@ -72,4 +72,15 @@ module ApplicationHelper
|
||||||
|
|
||||||
link_to(title, url_for(sort: {param_name => order}), class: "sort_link #{order}")
|
link_to(title, url_for(sort: {param_name => order}), class: "sort_link #{order}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def changing_css_class(version, *attrs)
|
||||||
|
return unless version
|
||||||
|
css_class = "text-warning"
|
||||||
|
|
||||||
|
if attrs.size == 1
|
||||||
|
version.object_changes.to_h[attrs.first] && css_class
|
||||||
|
else
|
||||||
|
version.object_changes.to_h.slice(*attrs).any? && css_class
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -95,6 +95,7 @@ class Ability
|
||||||
can :manage, ReservedDomain
|
can :manage, ReservedDomain
|
||||||
can :manage, ZonefileSetting
|
can :manage, ZonefileSetting
|
||||||
can :manage, DomainVersion
|
can :manage, DomainVersion
|
||||||
|
can :manage, ContactVersion
|
||||||
can :manage, Pricelist
|
can :manage, Pricelist
|
||||||
can :manage, User
|
can :manage, User
|
||||||
can :manage, ApiUser
|
can :manage, ApiUser
|
||||||
|
|
|
@ -3,6 +3,7 @@ module Versions
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
|
attr_accessor :version_loader
|
||||||
has_paper_trail class_name: "#{model_name}Version"
|
has_paper_trail class_name: "#{model_name}Version"
|
||||||
|
|
||||||
# add creator and updator
|
# add creator and updator
|
||||||
|
@ -55,4 +56,23 @@ module Versions
|
||||||
domains.each(&:touch_with_version)
|
domains.each(&:touch_with_version)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
def all_versions_for(ids, time)
|
||||||
|
ver_klass = paper_trail_version_class
|
||||||
|
from_history = ver_klass.where(item_id: ids.to_a).
|
||||||
|
order(:item_id).
|
||||||
|
preceding(time + 1, true).
|
||||||
|
select("distinct on (item_id) #{ver_klass.table_name}.*").
|
||||||
|
map do |ver|
|
||||||
|
o = new(ver.object)
|
||||||
|
o.version_loader = ver
|
||||||
|
ver.object_changes.to_h.each { |k, v| o[k]=v[-1] }
|
||||||
|
o
|
||||||
|
end
|
||||||
|
not_in_history = where(id: (ids.to_a - from_history.map(&:id)))
|
||||||
|
|
||||||
|
from_history + not_in_history
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
87
app/views/admin/contact_versions/index.haml
Normal file
87
app/views/admin/contact_versions/index.haml
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
= render 'shared/title', name: t(:contacts)
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
= search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f|
|
||||||
|
.row
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= f.label :name
|
||||||
|
= f.search_field :name, value: params[:q][:name], class: 'form-control', placeholder: t(:name)
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= f.label :id
|
||||||
|
= f.search_field :id, value: params[:q][:id], class: 'form-control', placeholder: t(:id)
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= f.label :ident
|
||||||
|
= f.search_field :ident, value: params[:q][:ident], class: 'form-control', placeholder: t(:ident)
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= f.label :phone
|
||||||
|
= f.search_field :phone, value: params[:q][:phone], class: 'form-control', placeholder: t(:phone)
|
||||||
|
.row
|
||||||
|
.col-md-3
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag :action
|
||||||
|
= select_tag '[q][event]', options_for_select([['Update', 'update'], ['Destroy', 'destroy']], params[:q][:event]), { include_blank:true, multiple: false, placeholder: t(:choose), class: 'form-control js-combobox' }
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag t(:results_per_page)
|
||||||
|
= text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page)
|
||||||
|
.col-md-3{style: 'padding-top: 25px;'}
|
||||||
|
%button.btn.btn-primary
|
||||||
|
|
||||||
|
%span.glyphicon.glyphicon-search
|
||||||
|
|
||||||
|
%button.btn.btn-default.js-reset-form
|
||||||
|
= t(:clear_fields)
|
||||||
|
%hr
|
||||||
|
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
.table-responsive
|
||||||
|
%table.table.table-hover.table-bordered.table-condensed
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:name)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:id)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:ident)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:phone)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:registrar)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:action_date)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:action)
|
||||||
|
%tbody
|
||||||
|
- @versions.each do |version|
|
||||||
|
- if version.reify
|
||||||
|
%tr
|
||||||
|
%td= link_to(version.reify.name, admin_contact_version_path(version.id))
|
||||||
|
%td= version.reify.code
|
||||||
|
%td= ident_for(version.reify)
|
||||||
|
%td= version.reify.phone
|
||||||
|
%td
|
||||||
|
- if version.reify.registrar
|
||||||
|
= link_to(version.reify.registrar, admin_registrar_path(version.reify.registrar))
|
||||||
|
%td= l(version.created_at, format: :short)
|
||||||
|
%td= version.event
|
||||||
|
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= paginate @versions
|
||||||
|
.col-md-6.text-right
|
||||||
|
|
||||||
|
|
||||||
|
:coffee
|
||||||
|
$(".js-reset-form").on "click", (e) ->
|
||||||
|
e.preventDefault();
|
||||||
|
window.location = "#{admin_contact_versions_path}"
|
107
app/views/admin/contact_versions/show.haml
Normal file
107
app/views/admin/contact_versions/show.haml
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
- contact = Contact.new(@version.object.to_h)
|
||||||
|
- @version.object_changes.to_h.each{|k,v| contact[k]=v.last}
|
||||||
|
= render 'shared/title', name: contact.name
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-8
|
||||||
|
.panel.panel-default{:style => "min-height:420px;"}
|
||||||
|
.panel-heading
|
||||||
|
%h3.panel-title
|
||||||
|
= l(@version.created_at, format: :short)
|
||||||
|
= @version.event
|
||||||
|
= plain_username(@version.terminator)
|
||||||
|
.panel-body
|
||||||
|
%dl.dl-horizontal
|
||||||
|
%dt= t(:id)
|
||||||
|
%dd{class: changing_css_class(@version,"code")}
|
||||||
|
= contact.code
|
||||||
|
|
||||||
|
%dt= t(:statuses)
|
||||||
|
%dd{class: changing_css_class(@version,"statuses")}
|
||||||
|
= contact.statuses.join(", ")
|
||||||
|
|
||||||
|
%dt= t(:ident)
|
||||||
|
%dd{class: changing_css_class(@version,"ident_country_code", "ident_type", "ident")}
|
||||||
|
= ident_for(contact)
|
||||||
|
|
||||||
|
%dt= t(:email)
|
||||||
|
%dd{class: changing_css_class(@version,"email")}
|
||||||
|
= contact.email
|
||||||
|
|
||||||
|
%dt= t(:phone)
|
||||||
|
%dd{class: changing_css_class(@version,"phone")}
|
||||||
|
= contact.phone
|
||||||
|
|
||||||
|
- if contact.fax
|
||||||
|
%dt= t(:fax)
|
||||||
|
%dd{class: changing_css_class(@version,"fax")}
|
||||||
|
= contact.fax
|
||||||
|
|
||||||
|
%br
|
||||||
|
|
||||||
|
%dt= t(:created)
|
||||||
|
%dd{class: changing_css_class(@version,"created_at")}
|
||||||
|
= l(contact.created_at, format: :short)
|
||||||
|
|
||||||
|
%dt= t(:updated)
|
||||||
|
%dd{class: changing_css_class(@version,"updated_at")}
|
||||||
|
= l(contact.updated_at, format: :short)
|
||||||
|
|
||||||
|
%dt= t(:registrar)
|
||||||
|
%dd{class: changing_css_class(@version,"registrar_id")}
|
||||||
|
- if contact.registrar.present?
|
||||||
|
= link_to(contact.registrar, admin_registrar_path(contact.registrar))
|
||||||
|
|
||||||
|
%dl.dl-horizontal
|
||||||
|
- if contact.org_name.present?
|
||||||
|
%dt= t(:org_name)
|
||||||
|
%dd{class: changing_css_class(@version,"org_name")}= contact.org_name
|
||||||
|
|
||||||
|
%dt= t(:street)
|
||||||
|
%dd{class: changing_css_class(@version,"street")}= contact.street.to_s.gsub("\n", '<br>').html_safe
|
||||||
|
|
||||||
|
%dt= t(:city)
|
||||||
|
%dd{class: changing_css_class(@version,"city")}= contact.city
|
||||||
|
|
||||||
|
%dt= t(:zip)
|
||||||
|
%dd{class: changing_css_class(@version,"zip")}= contact.zip
|
||||||
|
|
||||||
|
%dt= t(:state)
|
||||||
|
%dd{class: changing_css_class(@version,"state")}= contact.state
|
||||||
|
|
||||||
|
%dt= t(:country)
|
||||||
|
%dd{class: changing_css_class(@version,"country_code")}= contact.country
|
||||||
|
|
||||||
|
|
||||||
|
%span{:style => "padding-right:10px; float: right;"}
|
||||||
|
- if @version.previous
|
||||||
|
= link_to(t(:previous),
|
||||||
|
admin_contact_version_path(@version.previous.id),
|
||||||
|
class: 'btn btn-primary')
|
||||||
|
- else
|
||||||
|
%a.btn.btn-primary.disabled{:href => "#"}
|
||||||
|
%span= t(:previous)
|
||||||
|
- if @version.next
|
||||||
|
= link_to(t(:next),
|
||||||
|
admin_contact_version_path(@version.next.id),
|
||||||
|
class: 'btn btn-default')
|
||||||
|
- else
|
||||||
|
%a.btn.btn-default.disabled{:href => "#"}
|
||||||
|
%span= t(:next)
|
||||||
|
|
||||||
|
.col-md-4
|
||||||
|
.panel.panel-default{:style => "min-height:420px;"}
|
||||||
|
%ul.nav.nav-pills.nav-stacked
|
||||||
|
- @versions.each do |vs|
|
||||||
|
- if vs.id == @version.id
|
||||||
|
%li.active
|
||||||
|
= link_to admin_contact_version_path(vs.id) do
|
||||||
|
= l(vs.created_at, format: :short)
|
||||||
|
= vs.event
|
||||||
|
- else
|
||||||
|
%li
|
||||||
|
= link_to admin_contact_version_path(vs.id) do
|
||||||
|
= l(vs.created_at, format: :short)
|
||||||
|
= vs.event
|
||||||
|
%span{:style => "padding-left:10px; position: absolute; bottom: 10px;"}
|
||||||
|
= paginate @versions
|
|
@ -1,109 +0,0 @@
|
||||||
- statuses_link ||= false
|
|
||||||
- version ||= false
|
|
||||||
- domain ||= false
|
|
||||||
- pending_user ||= false
|
|
||||||
|
|
||||||
- if domain.present?
|
|
||||||
- if version # normal history
|
|
||||||
- children = HashWithIndifferentAccess.new(version.children)
|
|
||||||
- nameservers = Nameserver.where(id: children[:nameservers])
|
|
||||||
- tech_contacts = Contact.where(id: children[:tech_contacts])
|
|
||||||
- admin_contacts = Contact.where(id: children[:admin_contacts])
|
|
||||||
- registrant = Contact.where(id: children[:registrant])
|
|
||||||
- event = version.event
|
|
||||||
- creator = plain_username(version.terminator)
|
|
||||||
- else # pending history
|
|
||||||
- nameservers = domain.nameservers
|
|
||||||
- tech_contacts = domain.tech_contacts
|
|
||||||
- admin_contacts = domain.admin_contacts
|
|
||||||
- registrant = [domain.registrant]
|
|
||||||
- creator = pending_user.try(:username)
|
|
||||||
- event = 'pending'
|
|
||||||
|
|
||||||
%td
|
|
||||||
%p.nowrap
|
|
||||||
= l(domain.updated_at, format: :shorts)
|
|
||||||
- if statuses_link
|
|
||||||
%br= link_to t(:edit_statuses), edit_admin_domain_path(params[:domain_id])
|
|
||||||
|
|
||||||
%p.text-right
|
|
||||||
= event
|
|
||||||
%br
|
|
||||||
= creator
|
|
||||||
|
|
||||||
%td
|
|
||||||
%p
|
|
||||||
- if domain.statuses.present?
|
|
||||||
- domain.statuses.each do |s|
|
|
||||||
= s
|
|
||||||
- if domain.status_notes.present?
|
|
||||||
- notes = domain.status_notes[s]
|
|
||||||
- if notes
|
|
||||||
%br
|
|
||||||
%i= notes
|
|
||||||
%br
|
|
||||||
- if domain.pending_json.present?
|
|
||||||
%p
|
|
||||||
= link_to t(:pending_epp), '#', class: 'js-pending-toggle'
|
|
||||||
|
|
||||||
%td
|
|
||||||
%p
|
|
||||||
= "#{domain.period}#{domain.period_unit}"
|
|
||||||
%br
|
|
||||||
= "#{l(domain.valid_from, format: :date)}"
|
|
||||||
%br
|
|
||||||
= "#{l(domain.valid_to, format: :date)}"
|
|
||||||
|
|
||||||
%td
|
|
||||||
- if registrant
|
|
||||||
- registrant.each do |r|
|
|
||||||
%p
|
|
||||||
= r[:name]
|
|
||||||
= r[:phone]
|
|
||||||
= r[:email]
|
|
||||||
%p
|
|
||||||
= r[:code]
|
|
||||||
|
|
||||||
%td
|
|
||||||
- if admin_contacts
|
|
||||||
- admin_contacts.each do |ac|
|
|
||||||
%p
|
|
||||||
= ac[:name]
|
|
||||||
= ac[:phone]
|
|
||||||
= ac[:email]
|
|
||||||
%p
|
|
||||||
= ac[:code]
|
|
||||||
|
|
||||||
%td
|
|
||||||
- if tech_contacts
|
|
||||||
- tech_contacts.each do |tc|
|
|
||||||
%p
|
|
||||||
= tc[:name]
|
|
||||||
= tc[:phone]
|
|
||||||
= tc[:email]
|
|
||||||
%p
|
|
||||||
= tc[:code]
|
|
||||||
|
|
||||||
%td
|
|
||||||
%p
|
|
||||||
- if nameservers
|
|
||||||
- nameservers.each do |ns|
|
|
||||||
= ns[:hostname]
|
|
||||||
%br
|
|
||||||
= ns[:ipv4]
|
|
||||||
= ns[:ipv6]
|
|
||||||
|
|
||||||
%td
|
|
||||||
%p
|
|
||||||
= domain.registrar.name if domain.registrar
|
|
||||||
|
|
||||||
- if domain.pending_json.present?
|
|
||||||
%tr.js-pending{ style: 'display: none;' }
|
|
||||||
%td{colspan: 8}
|
|
||||||
= preserve do
|
|
||||||
%pre
|
|
||||||
- formatted_req = Nokogiri::XML(domain.pending_json['frame'])
|
|
||||||
- if formatted_req.errors.none?
|
|
||||||
= formatted_req
|
|
||||||
- else
|
|
||||||
= domain.pending_json['frame']
|
|
80
app/views/admin/domain_versions/archive.haml
Normal file
80
app/views/admin/domain_versions/archive.haml
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
= render 'shared/title', name: t(:domains)
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
= search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f|
|
||||||
|
.row
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag :name
|
||||||
|
= f.search_field :name, value: params[:q][:name], class: 'form-control', placeholder: t(:name)
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag :registrant
|
||||||
|
= f.search_field :registrant, value: params[:q][:registrant], class: 'form-control', placeholder: t(:registrant)
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag t(:registrar)
|
||||||
|
= f.search_field :registrar, value: params[:q][:registrar], class: 'form-control', placeholder: t(:registrant)
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag :action
|
||||||
|
= select_tag '[q][event]', options_for_select([['Update', 'update'], ['Destroy', 'destroy']], params[:q][:event]), { include_blank:true, multiple: false, placeholder: t(:choose), class: 'form-control js-combobox' }
|
||||||
|
.row
|
||||||
|
.col-md-3
|
||||||
|
.col-md-3
|
||||||
|
.col-md-3
|
||||||
|
.form-group
|
||||||
|
= label_tag t(:results_per_page)
|
||||||
|
= text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page)
|
||||||
|
.col-md-3{style: 'padding-top: 25px;'}
|
||||||
|
%button.btn.btn-primary
|
||||||
|
|
||||||
|
%span.glyphicon.glyphicon-search
|
||||||
|
|
||||||
|
%button.btn.btn-default.js-reset-form
|
||||||
|
= t(:clear_fields)
|
||||||
|
%hr
|
||||||
|
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-12
|
||||||
|
.table-responsive
|
||||||
|
%table.table.table-hover.table-bordered.table-condensed
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:name)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:registrant)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:registrar)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:action_date)
|
||||||
|
%th{class: 'col-xs-2'}
|
||||||
|
= t(:action)
|
||||||
|
%tbody
|
||||||
|
- @versions.each do |version|
|
||||||
|
- if version.reify
|
||||||
|
%tr
|
||||||
|
%td= link_to(version.reify.name, admin_domain_version_path(version.id))
|
||||||
|
%td
|
||||||
|
- if version.reify.registrant
|
||||||
|
= link_to(version.reify.registrant, admin_registrant_path(version.reify.registrant))
|
||||||
|
%td
|
||||||
|
- if version.reify.registrar
|
||||||
|
= link_to(version.reify.registrar, admin_registrar_path(version.reify.registrar))
|
||||||
|
%td= l(version.created_at, format: :short)
|
||||||
|
%td= version.event
|
||||||
|
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= paginate @versions
|
||||||
|
.col-md-6.text-right
|
||||||
|
|
||||||
|
|
||||||
|
:coffee
|
||||||
|
$(".js-reset-form").on "click", (e) ->
|
||||||
|
e.preventDefault();
|
||||||
|
window.location = "#{admin_domain_versions_path}"
|
123
app/views/admin/domain_versions/show.haml
Normal file
123
app/views/admin/domain_versions/show.haml
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
- domain = Domain.new(@version.object.to_h)
|
||||||
|
- @version.object_changes.to_h.each{|k,v| domain[k]=v.last}
|
||||||
|
|
||||||
|
= render 'shared/title', name: @version.reify.name
|
||||||
|
|
||||||
|
- if @version
|
||||||
|
- children = HashWithIndifferentAccess.new(@version.children)
|
||||||
|
- nameservers = Nameserver.all_versions_for(children[:nameservers], @version.created_at)
|
||||||
|
- dnskeys = Dnskey.all_versions_for(children[:dnskeys], @version.created_at)
|
||||||
|
- tech_contacts = Contact.all_versions_for(children[:tech_contacts], @version.created_at)
|
||||||
|
- admin_contacts = Contact.all_versions_for(children[:admin_contacts], @version.created_at)
|
||||||
|
- registrant = Contact.all_versions_for(children[:registrant], @version.created_at)
|
||||||
|
- event = @version.event
|
||||||
|
- creator = plain_username(@version.terminator)
|
||||||
|
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-md-8
|
||||||
|
.panel.panel-default{:style => "min-height:400px;"}
|
||||||
|
.panel-heading
|
||||||
|
%h3.panel-title
|
||||||
|
= l(@version.created_at, format: :short)
|
||||||
|
= event
|
||||||
|
= creator
|
||||||
|
.panel-body
|
||||||
|
%dl.dl-horizontal
|
||||||
|
%dt= t(:name)
|
||||||
|
%dd= link_to(domain.name, admin_domain_path(@version.item_id))
|
||||||
|
|
||||||
|
%dt= t(:statuses)
|
||||||
|
%dd{class: changing_css_class(@version,"statuses")}
|
||||||
|
- if domain.statuses.present?
|
||||||
|
- domain.statuses.each do |s|
|
||||||
|
= s
|
||||||
|
|
||||||
|
%dt= t(:registrant)
|
||||||
|
%dd{class: changing_css_class(@version,"registrant_id")}
|
||||||
|
- registrant.each do |r|
|
||||||
|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
|
||||||
|
= link_to link, target: "contact_#{r.id}" do
|
||||||
|
= r[:name]
|
||||||
|
= r[:phone]
|
||||||
|
= r[:email]
|
||||||
|
= r[:code]
|
||||||
|
%br
|
||||||
|
|
||||||
|
%dt= t(:admin_contacts)
|
||||||
|
%dd
|
||||||
|
- admin_contacts.each do |r|
|
||||||
|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
|
||||||
|
= link_to link, target: "contact_#{r.id}" do
|
||||||
|
= r[:name]
|
||||||
|
= r[:phone]
|
||||||
|
= r[:email]
|
||||||
|
= r[:code]
|
||||||
|
%br
|
||||||
|
|
||||||
|
%dt= t(:tech_contacts)
|
||||||
|
%dd
|
||||||
|
- tech_contacts.each do |r|
|
||||||
|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
|
||||||
|
= link_to link, target: "contact_#{r.id}" do
|
||||||
|
= r[:name]
|
||||||
|
= r[:phone]
|
||||||
|
= r[:email]
|
||||||
|
= r[:code]
|
||||||
|
%br
|
||||||
|
|
||||||
|
%dt= t(:nameservers)
|
||||||
|
%dd
|
||||||
|
- nameservers.each do |ns|
|
||||||
|
= ns[:hostname]
|
||||||
|
= ns[:ipv4]
|
||||||
|
= ns[:ipv6]
|
||||||
|
%br
|
||||||
|
|
||||||
|
%dt= t(:dnskeys)
|
||||||
|
%dd
|
||||||
|
- dnskeys.each do |ns|
|
||||||
|
= ns[:flags]
|
||||||
|
= ns[:protocol]
|
||||||
|
= ns[:alg]
|
||||||
|
- if ns[:public_key].present?
|
||||||
|
\...#{ns[:public_key].to_s[-20,20]}
|
||||||
|
%br
|
||||||
|
|
||||||
|
%dt= t(:registrar)
|
||||||
|
%dd{class: changing_css_class(@version,"registrar_id")}
|
||||||
|
= link_to admin_registrar_path(domain.registrar), target: "registrar_#{domain.registrar.id}" do
|
||||||
|
= domain.registrar.name
|
||||||
|
|
||||||
|
%span{:style => "padding-right:10px; padding-top:40px; float: right; bottom: 10px;"}
|
||||||
|
- if @version.previous
|
||||||
|
= link_to(t(:previous),
|
||||||
|
admin_domain_version_path(@version.previous.id),
|
||||||
|
class: 'btn btn-primary')
|
||||||
|
- else
|
||||||
|
%a.btn.btn-primary.disabled{:href => "#"}
|
||||||
|
%span= t(:previous)
|
||||||
|
- if @version.next
|
||||||
|
= link_to(t(:next),
|
||||||
|
admin_domain_version_path(@version.next.id),
|
||||||
|
class: 'btn btn-default')
|
||||||
|
- else
|
||||||
|
%a.btn.btn-default.disabled{:href => "#"}
|
||||||
|
%span= t(:next)
|
||||||
|
|
||||||
|
.col-md-4
|
||||||
|
.panel.panel-default{:style => "min-height:400px;"}
|
||||||
|
%ul.nav.nav-pills.nav-stacked
|
||||||
|
- @versions.each do |vs|
|
||||||
|
- if vs.id == @version.id and vs.reify
|
||||||
|
%li.active
|
||||||
|
= link_to admin_domain_version_path(vs.id) do
|
||||||
|
= l(vs.created_at, format: :short)
|
||||||
|
= vs.event
|
||||||
|
- else
|
||||||
|
%li
|
||||||
|
= link_to admin_domain_version_path(vs.id) do
|
||||||
|
= l(vs.created_at, format: :short)
|
||||||
|
= vs.event
|
||||||
|
%span{:style => "padding-left:10px; position: absolute; bottom: 10px;"}
|
||||||
|
= paginate @versions
|
127
app/views/admin/domains/partials/_version.haml
Normal file
127
app/views/admin/domains/partials/_version.haml
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
- statuses_link ||= false
|
||||||
|
- version ||= false
|
||||||
|
- domain ||= false
|
||||||
|
- pending_user ||= false
|
||||||
|
|
||||||
|
- if domain.present?
|
||||||
|
- if version # normal history
|
||||||
|
- children = HashWithIndifferentAccess.new(version.children)
|
||||||
|
- nameservers = Nameserver.all_versions_for(children[:nameservers], version.created_at)
|
||||||
|
- dnskeys = Dnskey.all_versions_for(children[:dnskeys], version.created_at)
|
||||||
|
- tech_contacts = Contact.all_versions_for(children[:tech_contacts], version.created_at)
|
||||||
|
- admin_contacts = Contact.all_versions_for(children[:admin_contacts], version.created_at)
|
||||||
|
- registrant = Contact.all_versions_for(children[:registrant], version.created_at)
|
||||||
|
- event = version.event
|
||||||
|
- creator = plain_username(version.terminator)
|
||||||
|
- else # pending history
|
||||||
|
- nameservers = domain.nameservers
|
||||||
|
- dnskeys = domain.dnskeys
|
||||||
|
- tech_contacts = domain.tech_contacts
|
||||||
|
- admin_contacts = domain.admin_contacts
|
||||||
|
- registrant = [domain.registrant]
|
||||||
|
- creator = pending_user.try(:username)
|
||||||
|
- event = 'pending'
|
||||||
|
|
||||||
|
%td
|
||||||
|
%p.nowrap
|
||||||
|
= l(domain.updated_at, format: :shorts)
|
||||||
|
- if statuses_link
|
||||||
|
%br= link_to t(:edit_statuses), edit_admin_domain_path(params[:domain_id])
|
||||||
|
|
||||||
|
%p.text-right
|
||||||
|
= event
|
||||||
|
%br
|
||||||
|
= creator
|
||||||
|
- if version
|
||||||
|
%p.text-right
|
||||||
|
= link_to "Pure history", admin_domain_version_path(version)
|
||||||
|
|
||||||
|
%td{class: changing_css_class(version,"statuses")}
|
||||||
|
%p
|
||||||
|
- if domain.statuses.present?
|
||||||
|
- domain.statuses.each do |s|
|
||||||
|
= s
|
||||||
|
- if domain.status_notes.present?
|
||||||
|
- notes = domain.status_notes[s]
|
||||||
|
- if notes
|
||||||
|
%br
|
||||||
|
%i= notes
|
||||||
|
%br
|
||||||
|
- if domain.pending_json.present?
|
||||||
|
%p
|
||||||
|
= link_to t(:pending_epp), '#', class: 'js-pending-toggle'
|
||||||
|
|
||||||
|
%td{class: changing_css_class(version, "period", "period_unit", "valid_from", "valid_to")}
|
||||||
|
%p
|
||||||
|
= "#{domain.period}#{domain.period_unit}"
|
||||||
|
%br
|
||||||
|
= "#{l(domain.valid_from, format: :date)}"
|
||||||
|
%br
|
||||||
|
= "#{l(domain.valid_to, format: :date)}"
|
||||||
|
|
||||||
|
%td
|
||||||
|
- Array(registrant).each do |r|
|
||||||
|
- link = r.version_loader ? admin_contact_version_path(r.version_loader.try(:id)) : admin_contact_path(r.id)
|
||||||
|
= link_to link, target: "contact_#{r.id}" do
|
||||||
|
%p
|
||||||
|
= r[:name]
|
||||||
|
= r[:phone]
|
||||||
|
= r[:email]
|
||||||
|
%p
|
||||||
|
= r[:code]
|
||||||
|
|
||||||
|
%td
|
||||||
|
- Array(admin_contacts).each do |ac|
|
||||||
|
- link = ac.version_loader ? admin_contact_version_path(ac.version_loader.try(:id)) : admin_contact_path(ac.id)
|
||||||
|
= link_to link, target: "contact_#{ac.id}" do
|
||||||
|
%p
|
||||||
|
= ac[:name]
|
||||||
|
= ac[:phone]
|
||||||
|
= ac[:email]
|
||||||
|
%p
|
||||||
|
= ac[:code]
|
||||||
|
|
||||||
|
%td
|
||||||
|
- Array(tech_contacts).each do |tc|
|
||||||
|
- link = tc.version_loader ? admin_contact_version_path(tc.version_loader.try(:id)) : admin_contact_path(tc.id)
|
||||||
|
= link_to link, target: "contact_#{tc.id}" do
|
||||||
|
%p
|
||||||
|
= tc[:name]
|
||||||
|
= tc[:phone]
|
||||||
|
= tc[:email]
|
||||||
|
%p
|
||||||
|
= tc[:code]
|
||||||
|
|
||||||
|
%td
|
||||||
|
%p
|
||||||
|
- Array(nameservers).each do |ns|
|
||||||
|
= ns[:hostname]
|
||||||
|
%br
|
||||||
|
= ns[:ipv4].presence
|
||||||
|
= ns[:ipv6].presence
|
||||||
|
%br
|
||||||
|
%td
|
||||||
|
- Array(dnskeys).each do |ns|
|
||||||
|
%p
|
||||||
|
= ns.flags
|
||||||
|
= ns.protocol
|
||||||
|
= ns.alg
|
||||||
|
- if ns.public_key.present?
|
||||||
|
\...#{ns.public_key.to_s[-20,20]}
|
||||||
|
|
||||||
|
%td{class: changing_css_class(version,"registrar_id")}
|
||||||
|
- if domain.registrar
|
||||||
|
%p
|
||||||
|
= link_to admin_registrar_path(domain.registrar), target: "registrar_#{domain.registrar.id}" do
|
||||||
|
= domain.registrar.name
|
||||||
|
|
||||||
|
- if domain.pending_json.present?
|
||||||
|
%tr.js-pending{ style: 'display: none;' }
|
||||||
|
%td{colspan: 8}
|
||||||
|
= preserve do
|
||||||
|
%pre
|
||||||
|
- formatted_req = Nokogiri::XML(domain.pending_json['frame'])
|
||||||
|
- if formatted_req.errors.none?
|
||||||
|
= formatted_req
|
||||||
|
- else
|
||||||
|
= domain.pending_json['frame']
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
.table-responsive
|
.table-responsive{data: {doublescroll: true}}
|
||||||
%table.table-hover.table-bordered.table-condensed
|
%table.table.table-bordered.table-condensed
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th{class: 'col-xs-1'}= t(:timestap)
|
%th{class: 'col-xs-1'}= t(:timestap)
|
||||||
|
@ -15,24 +15,25 @@
|
||||||
%th{class: 'col-xs-2'}= t(:admin)
|
%th{class: 'col-xs-2'}= t(:admin)
|
||||||
%th{class: 'col-xs-2'}= t(:tech)
|
%th{class: 'col-xs-2'}= t(:tech)
|
||||||
%th{class: 'col-xs-2'}= t(:nameservers)
|
%th{class: 'col-xs-2'}= t(:nameservers)
|
||||||
|
%th{class: 'col-xs-2'}= t(:dnskeys)
|
||||||
%th{class: 'col-xs-2'}= t(:registrar)
|
%th{class: 'col-xs-2'}= t(:registrar)
|
||||||
|
|
||||||
%tbody
|
%tbody
|
||||||
- if @pending_domain.present?
|
- if @pending_domain.present?
|
||||||
%tr.small
|
%tr.small
|
||||||
= render 'admin/domain_versions/version',
|
= render 'admin/domains/partials/version',
|
||||||
domain: @pending_domain, pending_user: @pending_user, statuses_link: true
|
domain: @pending_domain, pending_user: @pending_user, statuses_link: true
|
||||||
|
|
||||||
-# current version
|
-# current version
|
||||||
- if @domain.versions.present?
|
- if @domain.versions.present?
|
||||||
%tr.small
|
%tr.small
|
||||||
= render 'admin/domain_versions/version',
|
= render 'admin/domains/partials/version',
|
||||||
domain: @domain, version: @domain.versions.last
|
domain: @domain, version: @domain.versions.last
|
||||||
|
|
||||||
-# all other older versions
|
-# all other older versions
|
||||||
- @domain.versions.not_creates.reverse.each do |version|
|
- @domain.versions.not_creates.reverse.each do |version|
|
||||||
%tr.small
|
%tr.small
|
||||||
= render 'admin/domain_versions/version',
|
= render 'admin/domains/partials/version',
|
||||||
domain: version.reify, version: version.previous
|
domain: version.reify, version: version.previous
|
||||||
|
|
||||||
:coffee
|
:coffee
|
|
@ -57,6 +57,10 @@
|
||||||
%li= link_to t(:invoices), admin_invoices_path
|
%li= link_to t(:invoices), admin_invoices_path
|
||||||
%li= link_to t(:account_activities), admin_account_activities_path(created_after: 'today')
|
%li= link_to t(:account_activities), admin_account_activities_path(created_after: 'today')
|
||||||
%li.divider
|
%li.divider
|
||||||
|
%li.dropdown-header= t(:archive)
|
||||||
|
%li= link_to t(:domains_history), admin_domain_versions_path
|
||||||
|
%li= link_to t(:contacts_history), admin_contact_versions_path
|
||||||
|
%li.divider
|
||||||
%li.dropdown-header= t(:system)
|
%li.dropdown-header= t(:system)
|
||||||
%li= link_to t(:settings), admin_settings_path
|
%li= link_to t(:settings), admin_settings_path
|
||||||
%li= link_to t(:zonefile), admin_zonefile_settings_path
|
%li= link_to t(:zonefile), admin_zonefile_settings_path
|
||||||
|
|
|
@ -942,6 +942,8 @@ en:
|
||||||
if_auth_info_is_left_empty_it_will_be_auto_generated: 'If auth info is left empty, it will be auto generated.'
|
if_auth_info_is_left_empty_it_will_be_auto_generated: 'If auth info is left empty, it will be auto generated.'
|
||||||
each_domain_name_must_end_with_colon_sign: 'Each domain name must end with colon (:) sign.'
|
each_domain_name_must_end_with_colon_sign: 'Each domain name must end with colon (:) sign.'
|
||||||
expiration_remind_subject: 'The %{name} domain has expired'
|
expiration_remind_subject: 'The %{name} domain has expired'
|
||||||
|
next: 'Next'
|
||||||
|
previous: 'Previous'
|
||||||
personal_domain_verification_url: 'Personal domain verification url'
|
personal_domain_verification_url: 'Personal domain verification url'
|
||||||
available_verification_url_not_found: 'Available verification url not found, for domain.'
|
available_verification_url_not_found: 'Available verification url not found, for domain.'
|
||||||
contact_already_associated_with_the_domain: 'Object association prohibits operation, contact already associated with the domain'
|
contact_already_associated_with_the_domain: 'Object association prohibits operation, contact already associated with the domain'
|
||||||
|
|
|
@ -198,7 +198,7 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :domains do
|
resources :domains do
|
||||||
resources :domain_versions
|
resources :domain_versions, controller: 'domains', action: 'versions'
|
||||||
resources :pending_updates
|
resources :pending_updates
|
||||||
resources :pending_deletes
|
resources :pending_deletes
|
||||||
member do
|
member do
|
||||||
|
@ -207,6 +207,18 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :domain_versions do
|
||||||
|
collection do
|
||||||
|
get 'search'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
resources :contact_versions do
|
||||||
|
collection do
|
||||||
|
get 'search'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
resources :settings
|
resources :settings
|
||||||
|
|
||||||
resources :blocked_domains do
|
resources :blocked_domains do
|
||||||
|
|
126
vendor/assets/javascripts/jquery.doubleScroll.js
vendored
Normal file
126
vendor/assets/javascripts/jquery.doubleScroll.js
vendored
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* @name DoubleScroll
|
||||||
|
* @desc displays scroll bar on top and on the bottom of the div
|
||||||
|
* @requires jQuery
|
||||||
|
*
|
||||||
|
* @author Pawel Suwala - http://suwala.eu/
|
||||||
|
* @author Antoine Vianey - http://www.astek.fr/
|
||||||
|
* @version 0.5 (11-11-2015)
|
||||||
|
*
|
||||||
|
* Dual licensed under the MIT and GPL licenses:
|
||||||
|
* http://www.opensource.org/licenses/mit-license.php
|
||||||
|
* http://www.gnu.org/licenses/gpl.html
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* https://github.com/avianey/jqDoubleScroll
|
||||||
|
*/
|
||||||
|
(function( $ ) {
|
||||||
|
|
||||||
|
jQuery.fn.doubleScroll = function(userOptions) {
|
||||||
|
|
||||||
|
// Default options
|
||||||
|
var options = {
|
||||||
|
contentElement: undefined, // Widest element, if not specified first child element will be used
|
||||||
|
scrollCss: {
|
||||||
|
'overflow-x': 'auto',
|
||||||
|
'overflow-y': 'hidden'
|
||||||
|
},
|
||||||
|
contentCss: {
|
||||||
|
'overflow-x': 'auto',
|
||||||
|
'overflow-y': 'hidden'
|
||||||
|
},
|
||||||
|
onlyIfScroll: true, // top scrollbar is not shown if the bottom one is not present
|
||||||
|
resetOnWindowResize: false, // recompute the top ScrollBar requirements when the window is resized
|
||||||
|
timeToWaitForResize: 30 // wait for the last update event (usefull when browser fire resize event constantly during ressing)
|
||||||
|
};
|
||||||
|
|
||||||
|
$.extend(true, options, userOptions);
|
||||||
|
|
||||||
|
// do not modify
|
||||||
|
// internal stuff
|
||||||
|
$.extend(options, {
|
||||||
|
topScrollBarMarkup: '<div class="doubleScroll-scroll-wrapper" style="height: 20px;"><div class="doubleScroll-scroll" style="height: 20px;"></div></div>',
|
||||||
|
topScrollBarWrapperSelector: '.doubleScroll-scroll-wrapper',
|
||||||
|
topScrollBarInnerSelector: '.doubleScroll-scroll'
|
||||||
|
});
|
||||||
|
|
||||||
|
var _showScrollBar = function($self, options) {
|
||||||
|
|
||||||
|
if (options.onlyIfScroll && $self.get(0).scrollWidth <= $self.width()) {
|
||||||
|
// content doesn't scroll
|
||||||
|
// remove any existing occurrence...
|
||||||
|
$self.prev(options.topScrollBarWrapperSelector).remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add div that will act as an upper scroll only if not already added to the DOM
|
||||||
|
var $topScrollBar = $self.prev(options.topScrollBarWrapperSelector);
|
||||||
|
|
||||||
|
if ($topScrollBar.length == 0) {
|
||||||
|
|
||||||
|
// creating the scrollbar
|
||||||
|
// added before in the DOM
|
||||||
|
$topScrollBar = $(options.topScrollBarMarkup);
|
||||||
|
$self.before($topScrollBar);
|
||||||
|
|
||||||
|
// apply the css
|
||||||
|
$topScrollBar.css(options.scrollCss);
|
||||||
|
$self.css(options.contentCss);
|
||||||
|
|
||||||
|
// bind upper scroll to bottom scroll
|
||||||
|
$topScrollBar.bind('scroll.doubleScroll', function() {
|
||||||
|
$self.scrollLeft($topScrollBar.scrollLeft());
|
||||||
|
});
|
||||||
|
|
||||||
|
// bind bottom scroll to upper scroll
|
||||||
|
var selfScrollHandler = function() {
|
||||||
|
$topScrollBar.scrollLeft($self.scrollLeft());
|
||||||
|
};
|
||||||
|
$self.bind('scroll.doubleScroll', selfScrollHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the content element (should be the widest one)
|
||||||
|
var $contentElement;
|
||||||
|
|
||||||
|
if (options.contentElement !== undefined && $self.find(options.contentElement).length !== 0) {
|
||||||
|
$contentElement = $self.find(options.contentElement);
|
||||||
|
} else {
|
||||||
|
$contentElement = $self.find('>:first-child');
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the width of the wrappers
|
||||||
|
$(options.topScrollBarInnerSelector, $topScrollBar).width($contentElement.outerWidth());
|
||||||
|
$topScrollBar.width($self.width());
|
||||||
|
$topScrollBar.scrollLeft($self.scrollLeft());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.each(function() {
|
||||||
|
|
||||||
|
var $self = $(this);
|
||||||
|
|
||||||
|
_showScrollBar($self, options);
|
||||||
|
|
||||||
|
// bind the resize handler
|
||||||
|
// do it once
|
||||||
|
if (options.resetOnWindowResize) {
|
||||||
|
|
||||||
|
var id;
|
||||||
|
var handler = function(e) {
|
||||||
|
_showScrollBar($self, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
$(window).bind('resize.doubleScroll', function() {
|
||||||
|
// adding/removing/replacing the scrollbar might resize the window
|
||||||
|
// so the resizing flag will avoid the infinite loop here...
|
||||||
|
clearTimeout(id);
|
||||||
|
id = setTimeout(handler, options.timeToWaitForResize);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}( jQuery ));
|
Loading…
Add table
Add a link
Reference in a new issue