diff --git a/app/assets/images/bootstrap/glyphicons-halflings.png b/app/assets/images/bootstrap/glyphicons-halflings.png
new file mode 100644
index 0000000..92d4445
Binary files /dev/null and b/app/assets/images/bootstrap/glyphicons-halflings.png differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index a406fb6..7b87799 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -10,4 +10,10 @@
//= require pjax
//= require active_scaffold
//= require slides
+//= require bootstrap-tooltip
+//= require bootstrap-popover
//= require_self
+
+$(function(){
+ $('[rel=popover]').popover();
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/bootstrap-popover.js b/app/assets/javascripts/bootstrap-popover.js
new file mode 100644
index 0000000..57864fc
--- /dev/null
+++ b/app/assets/javascripts/bootstrap-popover.js
@@ -0,0 +1,95 @@
+/* ===========================================================
+ * bootstrap-popover.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function( $ ) {
+
+ "use strict"
+
+ var Popover = function ( element, options ) {
+ this.init('popover', element, options)
+ }
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+ , content = this.getContent()
+
+ $tip.find('.title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
+ $tip.find('.content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+ }
+
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ , getContent: function () {
+ var content
+ , $e = this.$element
+ , o = this.options
+
+ content = $e.attr('data-content')
+ || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
+
+ content = content.toString().replace(/(^\s*|\s*$)/, "")
+
+ return content
+ }
+
+ , tip: function() {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ }
+ return this.$tip
+ }
+
+ })
+
+
+ /* POPOVER PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.popover = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('popover')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+ placement: 'right'
+ , content: ''
+ , template: '
'
+ })
+
+}( window.jQuery )
diff --git a/app/assets/javascripts/bootstrap-tooltip.js b/app/assets/javascripts/bootstrap-tooltip.js
new file mode 100644
index 0000000..67fca5e
--- /dev/null
+++ b/app/assets/javascripts/bootstrap-tooltip.js
@@ -0,0 +1,273 @@
+/* ===========================================================
+ * bootstrap-tooltip.js v2.0.0
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function( $ ) {
+
+ "use strict"
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Tooltip = function ( element, options ) {
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.prototype = {
+
+ constructor: Tooltip
+
+ , init: function ( type, element, options ) {
+ var eventIn
+ , eventOut
+
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.enabled = true
+
+ if (this.options.trigger != 'manual') {
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
+ eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
+ this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ , getOptions: function ( options ) {
+ options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ , enter: function ( e ) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.show) {
+ self.show()
+ } else {
+ self.hoverState = 'in'
+ setTimeout(function() {
+ if (self.hoverState == 'in') {
+ self.show()
+ }
+ }, self.options.delay.show)
+ }
+ }
+
+ , leave: function ( e ) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.hide) {
+ self.hide()
+ } else {
+ self.hoverState = 'out'
+ setTimeout(function() {
+ if (self.hoverState == 'out') {
+ self.hide()
+ }
+ }, self.options.delay.hide)
+ }
+ }
+
+ , show: function () {
+ var $tip
+ , inside
+ , pos
+ , actualWidth
+ , actualHeight
+ , placement
+ , tp
+
+ if (this.hasContent() && this.enabled) {
+ $tip = this.tip()
+ this.setContent()
+
+ if (this.options.animation) {
+ $tip.addClass('fade')
+ }
+
+ placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ inside = /in/.test(placement)
+
+ $tip
+ .remove()
+ .css({ top: 0, left: 0, display: 'block' })
+ .appendTo(inside ? this.$element : document.body)
+
+ pos = this.getPosition(inside)
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ switch (inside ? placement.split(' ')[1] : placement) {
+ case 'bottom':
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'top':
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'left':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+ break
+ case 'right':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+ break
+ }
+
+ if (this.options['z-index']) tp['z-index'] = this.options['z-index']
+
+ $tip
+ .css(tp)
+ .addClass(placement)
+ .addClass('in')
+ }
+ }
+
+ , setContent: function () {
+ var $tip = this.tip()
+ $tip.find('.tooltip-inner').html(this.getTitle())
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ , hide: function () {
+ var that = this
+ , $tip = this.tip()
+
+ $tip.removeClass('in')
+
+ function removeWithAnimation() {
+ var timeout = setTimeout(function () {
+ $tip.off($.support.transition.end).remove()
+ }, 500)
+
+ $tip.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ $tip.remove()
+ })
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ removeWithAnimation() :
+ $tip.remove()
+ }
+
+ , fixTitle: function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
+ }
+ }
+
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
+ , getPosition: function (inside) {
+ return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
+ width: this.$element[0].offsetWidth
+ , height: this.$element[0].offsetHeight
+ })
+ }
+
+ , getTitle: function () {
+ var title
+ , $e = this.$element
+ , o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ title = title.toString().replace(/(^\s*|\s*$)/, "")
+
+ return title
+ }
+
+ , tip: function () {
+ return this.$tip = this.$tip || $(this.options.template)
+ }
+
+ , validate: function () {
+ if (!this.$element[0].parentNode) {
+ this.hide()
+ this.$element = null
+ this.options = null
+ }
+ }
+
+ , enable: function () {
+ this.enabled = true
+ }
+
+ , disable: function () {
+ this.enabled = false
+ }
+
+ , toggleEnabled: function () {
+ this.enabled = !this.enabled
+ }
+
+ , toggle: function () {
+ this[this.tip().hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+ * ========================= */
+
+ $.fn.tooltip = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tooltip')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tooltip.Constructor = Tooltip
+
+ $.fn.tooltip.defaults = {
+ animation: true
+ , delay: 0
+ , selector: false
+ , placement: 'top'
+ , trigger: 'hover'
+ , title: ''
+ , template: ''
+ , 'z-index': false
+ }
+
+}( window.jQuery )
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 5e26b32..e0bdc8c 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -5,6 +5,8 @@
*= require normalize
+*= require bootstrap/bootstrap
+
*= require theme/base
*= require theme/theme
*= require theme/error_explanation
diff --git a/app/assets/stylesheets/bootstrap/bootstrap.scss b/app/assets/stylesheets/bootstrap/bootstrap.scss
new file mode 100644
index 0000000..c4f9256
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap/bootstrap.scss
@@ -0,0 +1,545 @@
+.icon {
+ background-image: url(image-path('bootstrap/glyphicons-halflings.png'));
+ background-position: 14px 14px;
+ background-repeat: no-repeat;
+ display: inline-block;
+ vertical-align: text-top;
+ width: 14px;
+ height: 14px;
+ *margin-right: .3em;
+}
+.icon:last-child {
+ *margin-left: 0;
+}
+.icon.white {
+ background-image: url(../img/glyphicons-halflings-white.png);
+}
+.icon.glass {
+ background-position: 0 0;
+}
+.icon.music {
+ background-position: -24px 0;
+}
+.icon.search {
+ background-position: -48px 0;
+}
+.icon.envelope {
+ background-position: -72px 0;
+}
+.icon.heart {
+ background-position: -96px 0;
+}
+.icon.star {
+ background-position: -120px 0;
+}
+.icon.star-empty {
+ background-position: -144px 0;
+}
+.icon.user {
+ background-position: -168px 0;
+}
+.icon.film {
+ background-position: -192px 0;
+}
+.icon.th-large {
+ background-position: -216px 0;
+}
+.icon.th {
+ background-position: -240px 0;
+}
+.icon.th-list {
+ background-position: -264px 0;
+}
+.icon.ok {
+ background-position: -288px 0;
+}
+.icon.remove {
+ background-position: -312px 0;
+}
+.icon.zoom-in {
+ background-position: -336px 0;
+}
+.icon.zoom-out {
+ background-position: -360px 0;
+}
+.icon.off {
+ background-position: -384px 0;
+}
+.icon.signal {
+ background-position: -408px 0;
+}
+.icon.cog {
+ background-position: -432px 0;
+}
+.icon.trash {
+ background-position: -456px 0;
+}
+.icon.home {
+ background-position: 0 -24px;
+}
+.icon.file {
+ background-position: -24px -24px;
+}
+.icon.time {
+ background-position: -48px -24px;
+}
+.icon.road {
+ background-position: -72px -24px;
+}
+.icon.download-alt {
+ background-position: -96px -24px;
+}
+.icon.download {
+ background-position: -120px -24px;
+}
+.icon.upload {
+ background-position: -144px -24px;
+}
+.icon.inbox {
+ background-position: -168px -24px;
+}
+.icon.play-circle {
+ background-position: -192px -24px;
+}
+.icon.repeat {
+ background-position: -216px -24px;
+}
+.icon.refresh {
+ background-position: -240px -24px;
+}
+.icon.list-alt {
+ background-position: -264px -24px;
+}
+.icon.lock {
+ background-position: -287px -24px;
+}
+.icon.flag {
+ background-position: -312px -24px;
+}
+.icon.headphones {
+ background-position: -336px -24px;
+}
+.icon.volume-off {
+ background-position: -360px -24px;
+}
+.icon.volume-down {
+ background-position: -384px -24px;
+}
+.icon.volume-up {
+ background-position: -408px -24px;
+}
+.icon.qrcode {
+ background-position: -432px -24px;
+}
+.icon.barcode {
+ background-position: -456px -24px;
+}
+.icon.tag {
+ background-position: 0 -48px;
+}
+.icon.tags {
+ background-position: -25px -48px;
+}
+.icon.book {
+ background-position: -48px -48px;
+}
+.icon.bookmark {
+ background-position: -72px -48px;
+}
+.icon.print {
+ background-position: -96px -48px;
+}
+.icon.camera {
+ background-position: -120px -48px;
+}
+.icon.font {
+ background-position: -144px -48px;
+}
+.icon.bold {
+ background-position: -167px -48px;
+}
+.icon.italic {
+ background-position: -192px -48px;
+}
+.icon.text-height {
+ background-position: -216px -48px;
+}
+.icon.text-width {
+ background-position: -240px -48px;
+}
+.icon.align-left {
+ background-position: -264px -48px;
+}
+.icon.align-center {
+ background-position: -288px -48px;
+}
+.icon.align-right {
+ background-position: -312px -48px;
+}
+.icon.align-justify {
+ background-position: -336px -48px;
+}
+.icon.list {
+ background-position: -360px -48px;
+}
+.icon.indent-left {
+ background-position: -384px -48px;
+}
+.icon.indent-right {
+ background-position: -408px -48px;
+}
+.icon.facetime-video {
+ background-position: -432px -48px;
+}
+.icon.picture {
+ background-position: -456px -48px;
+}
+.icon.pencil {
+ background-position: 0 -72px;
+}
+.icon.map-marker {
+ background-position: -24px -72px;
+}
+.icon.adjust {
+ background-position: -48px -72px;
+}
+.icon.tint {
+ background-position: -72px -72px;
+}
+.icon.edit {
+ background-position: -96px -72px;
+}
+.icon.share {
+ background-position: -120px -72px;
+}
+.icon.check {
+ background-position: -144px -72px;
+}
+.icon.move {
+ background-position: -168px -72px;
+}
+.icon.step-backward {
+ background-position: -192px -72px;
+}
+.icon.fast-backward {
+ background-position: -216px -72px;
+}
+.icon.backward {
+ background-position: -240px -72px;
+}
+.icon.play {
+ background-position: -264px -72px;
+}
+.icon.pause {
+ background-position: -288px -72px;
+}
+.icon.stop {
+ background-position: -312px -72px;
+}
+.icon.forward {
+ background-position: -336px -72px;
+}
+.icon.fast-forward {
+ background-position: -360px -72px;
+}
+.icon.step-forward {
+ background-position: -384px -72px;
+}
+.icon.eject {
+ background-position: -408px -72px;
+}
+.icon.chevron-left {
+ background-position: -432px -72px;
+}
+.icon.chevron-right {
+ background-position: -456px -72px;
+}
+.icon.plus-sign {
+ background-position: 0 -96px;
+}
+.icon.minus-sign {
+ background-position: -24px -96px;
+}
+.icon.remove-sign {
+ background-position: -48px -96px;
+}
+.icon.ok-sign {
+ background-position: -72px -96px;
+}
+.icon.question-sign {
+ background-position: -96px -96px;
+}
+.icon.info-sign {
+ background-position: -120px -96px;
+}
+.icon.screenshot {
+ background-position: -144px -96px;
+}
+.icon.remove-circle {
+ background-position: -168px -96px;
+}
+.icon.ok-circle {
+ background-position: -192px -96px;
+}
+.icon.ban-circle {
+ background-position: -216px -96px;
+}
+.icon.arrow-left {
+ background-position: -240px -96px;
+}
+.icon.arrow-right {
+ background-position: -264px -96px;
+}
+.icon.arrow-up {
+ background-position: -289px -96px;
+}
+.icon.arrow-down {
+ background-position: -312px -96px;
+}
+.icon.share-alt {
+ background-position: -336px -96px;
+}
+.icon.resize-full {
+ background-position: -360px -96px;
+}
+.icon.resize-small {
+ background-position: -384px -96px;
+}
+.icon.plus {
+ background-position: -408px -96px;
+}
+.icon.minus {
+ background-position: -433px -96px;
+}
+.icon.asterisk {
+ background-position: -456px -96px;
+}
+.icon.exclamation-sign {
+ background-position: 0 -120px;
+}
+.icon.gift {
+ background-position: -24px -120px;
+}
+.icon.leaf {
+ background-position: -48px -120px;
+}
+.icon.fire {
+ background-position: -72px -120px;
+}
+.icon.eye-open {
+ background-position: -96px -120px;
+}
+.icon.eye-close {
+ background-position: -120px -120px;
+}
+.icon.warning-sign {
+ background-position: -144px -120px;
+}
+.icon.plane {
+ background-position: -168px -120px;
+}
+.icon.calendar {
+ background-position: -192px -120px;
+}
+.icon.random {
+ background-position: -216px -120px;
+}
+.icon.comment {
+ background-position: -240px -120px;
+}
+.icon.magnet {
+ background-position: -264px -120px;
+}
+.icon.chevron-up {
+ background-position: -288px -120px;
+}
+.icon.chevron-down {
+ background-position: -313px -119px;
+}
+.icon.retweet {
+ background-position: -336px -120px;
+}
+.icon.shopping-cart {
+ background-position: -360px -120px;
+}
+.icon.folder-close {
+ background-position: -384px -120px;
+}
+.icon.folder-open {
+ background-position: -408px -120px;
+}
+.icon.resize-vertical {
+ background-position: -432px -119px;
+}
+.icon.resize-horizontal {
+ background-position: -456px -118px;
+}
+.tooltip {
+ position: absolute;
+ z-index: 1020;
+ display: block;
+ visibility: visible;
+ padding: 5px;
+ font-size: 11px;
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.tooltip.in {
+ opacity: 0.8;
+ filter: alpha(opacity=80);
+}
+.tooltip.top {
+ margin-top: -2px;
+}
+.tooltip.right {
+ margin-left: 2px;
+}
+.tooltip.bottom {
+ margin-top: 2px;
+}
+.tooltip.left {
+ margin-left: -2px;
+}
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 5px solid #000000;
+}
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-left: 5px solid #000000;
+}
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-bottom: 5px solid #000000;
+}
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-right: 5px solid #000000;
+}
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #ffffff;
+ text-align: center;
+ text-decoration: none;
+ background-color: #000000;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+}
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1010;
+ display: none;
+ padding: 5px;
+}
+.popover.top {
+ margin-top: -5px;
+}
+.popover.right {
+ margin-left: 5px;
+}
+.popover.bottom {
+ margin-top: 5px;
+}
+.popover.left {
+ margin-left: -5px;
+}
+.popover.top .arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 5px solid #000000;
+}
+.popover.right .arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-right: 5px solid #000000;
+}
+.popover.bottom .arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-bottom: 5px solid #000000;
+}
+.popover.left .arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-left: 5px solid #000000;
+}
+.popover .arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+}
+.popover .inner {
+ padding: 3px;
+ width: 280px;
+ overflow: hidden;
+ background: #000000;
+ background: rgba(0, 0, 0, 0.8);
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+}
+.popover .title {
+ padding: 9px 15px;
+ line-height: 1;
+ background-color: #f5f5f5;
+ border-bottom: 1px solid #eee;
+ -webkit-border-radius: 3px 3px 0 0;
+ -moz-border-radius: 3px 3px 0 0;
+ border-radius: 3px 3px 0 0;
+
+ -webkit-margin-before: 0;
+ -webkit-margin-after: 0;
+}
+.popover .content {
+ padding: 14px;
+ background-color: #ffffff;
+ -webkit-border-radius: 0 0 3px 3px;
+ -moz-border-radius: 0 0 3px 3px;
+ border-radius: 0 0 3px 3px;
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding-box;
+ background-clip: padding-box;
+}
+.popover .content p, .popover .content ul, .popover .content ol {
+ margin-bottom: 0;
+}
diff --git a/app/assets/stylesheets/overrides.css.erb b/app/assets/stylesheets/overrides.css.erb
deleted file mode 100644
index 5a96ee2..0000000
--- a/app/assets/stylesheets/overrides.css.erb
+++ /dev/null
@@ -1,35 +0,0 @@
-#main .block .content p {
- font-size: 16px;
-}
-
-#main .block .content h2 {
- margin-left: 0;
-}
-
-#main .block .content .active-scaffold-header h2 {
- font-size: 160%;
-}
-
-#main .block .content .active-scaffold th a {
- text-shadow: none;
-}
-
-#main .block .content .active-scaffold th p {
- font: bold 11px arial, sans-serif;
- text-shadow: none;
-}
-
-body.errors #main .inner {
- margin-top: 15px;
-}
-
-#as_domains-active-scaffold .name-column,
-#as_hosts-active-scaffold .name-column {
- font-weight: bold;
- text-shadow: none;
-}
-
-.flash .alert {
- border: 1px solid #bb9004;
- background: #f9c006 url(<%= image_path("messages/warning.png") %>) no-repeat 10px center;
-}
diff --git a/app/assets/stylesheets/overrides.css.scss b/app/assets/stylesheets/overrides.css.scss
new file mode 100644
index 0000000..eec0638
--- /dev/null
+++ b/app/assets/stylesheets/overrides.css.scss
@@ -0,0 +1,65 @@
+#main .block .content p {
+ font-size: 16px;
+}
+
+#main .block .content h2 {
+ margin-left: 0;
+}
+
+#main .block .content .active-scaffold-header h2 {
+ font-size: 160%;
+}
+
+#main .block .content .active-scaffold th a {
+ text-shadow: none;
+}
+
+#main .block .content .active-scaffold th p {
+ font: bold 11px arial, sans-serif;
+ text-shadow: none;
+}
+
+body.errors #main .inner {
+ margin-top: 15px;
+}
+
+#as_domains-active-scaffold .name-column,
+#as_hosts-active-scaffold .name-column {
+ font-weight: bold;
+ text-shadow: none;
+}
+
+#as_domains-active-scaffold tr.shared-domain {
+ &.record {
+ background-color: mix(#E6F2FF, lighten(yellow, 30%));
+ }
+ &.record td {
+ border-bottom: solid 1px #C5DBF7;
+ border-left: solid 1px #C5DBF7;
+ }
+
+ &.even-record {
+ background-color: mix(#fff, lighten(yellow, 40%));
+ }
+ &.even-record td {
+ border-left-color: #ddd;
+ }
+
+ &.record td.sorted {
+ background-color: mix(#B9DCFF, lighten(yellow, 30%));
+ border-bottom-color: #AFD0F5;
+ }
+
+ &.even-record td.sorted {
+ background-color: mix(#E6F2FF, lighten(yellow, 40%));
+ border-bottom-color: #AFD0F5;
+ }
+ &.record td.actions table td {
+ border: none;
+ }
+}
+
+.flash .alert {
+ border: 1px solid #bb9004;
+ background: #f9c006 url(image-path("messages/warning.png")) no-repeat 10px center;
+}
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 0527f30..7daaccd 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,5 +1,5 @@
class Ability
- CRUD = [:read, :create, :edit, :destroy]
+ CRUD = [:read, :create, :update, :destroy]
include CanCan::Ability
attr_accessor :user
@@ -48,7 +48,7 @@ class Ability
def action_aliases
alias_action :row, :show_search, :render_field, :to => :read
alias_action :update_column, :add_association, :edit_associated,
- :edit_associated, :new_existing, :add_existing, :to => :edit
+ :edit_associated, :new_existing, :add_existing, :to => :update
alias_action :delete, :destroy_existing, :to => :destroy
end
diff --git a/app/views/domains/_form_association_footer.html.erb b/app/views/domains/_form_association_footer.html.erb
index c07da7a..b9aea05 100644
--- a/app/views/domains/_form_association_footer.html.erb
+++ b/app/views/domains/_form_association_footer.html.erb
@@ -1,5 +1,4 @@
-<%
-# hide "Replace with new" for SOA record
+<% # hide "Replace with new" for SOA record
begin
remote_controller = active_scaffold_controller_for(column.association.klass)
diff --git a/app/views/domains/_list_record.html.erb b/app/views/domains/_list_record.html.erb
new file mode 100644
index 0000000..60fca19
--- /dev/null
+++ b/app/views/domains/_list_record.html.erb
@@ -0,0 +1,15 @@
+<% # customize row class to highlight shared domains
+
+record = list_record if list_record # compat with render :partial :collection
+columns ||= list_columns
+tr_class = cycle("", "even-record")
+tr_class += " shared-domain" if cannot?(:crud_permissions, record)
+url_options = params_for(:action => :list, :id => record.id)
+action_links ||= active_scaffold_config.action_links.member
+-%>
+
+
+ <%= render :partial => 'list_record_columns', :locals => {:record => record, :columns => columns} %>
+ <%= render :partial => 'list_actions', :locals => {:record => record, :url_options => url_options, :action_links => action_links} unless action_links.empty? %>
+ <%= render_nested_view(action_links, url_options, record) unless @nested_auto_open.nil? %>
+
diff --git a/app/views/domains/_list_record_columns.html.erb b/app/views/domains/_list_record_columns.html.erb
index 23d515e..82bfd1f 100644
--- a/app/views/domains/_list_record_columns.html.erb
+++ b/app/views/domains/_list_record_columns.html.erb
@@ -3,6 +3,7 @@
<% columns.each do |column| %>
<% authorized = record.authorized_for?(:crud_type => :read, :column => column.name) -%>
<% column_value = authorized ? get_column_value(record, column) : active_scaffold_config.list.empty_field_text -%>
+ <% can_crud_permissions = can?(:crud_permissions, record) -%>
<% if column.name == :name %>
@@ -13,6 +14,13 @@
else
column_value
end %>
+ <% unless can_crud_permissions %>
+ <% who = "#{record.user.name} #{mail_to record.user.email}" %>
+
+ <% end %>
|
<% elsif column.name == :records %>
@@ -24,7 +32,7 @@
<%
if column_value == '-'
column_value = 'Permissions (0)'
- authorized &&= can?(:crud_permissions, record)
+ authorized &&= can_crud_permissions
end
%>
<%= authorized ? render_list_column(column_value, column, record) : column_value %>
|