Archived
1
0
Fork 0

Merge branch 'dev' into 31-admin-user-management

# Conflicts:
#	app/forms/UserSettings.php
This commit is contained in:
Henrik Hautakoski 2022-08-08 23:35:37 +02:00
commit 4b750f0f37
70 changed files with 7831 additions and 5620 deletions

View file

@ -1,42 +0,0 @@
{
"disallowEmptyBlocks": true,
"disallowKeywords": ["with"],
"disallowMixedSpacesAndTabs": true,
"disallowMultipleLineStrings": true,
"disallowMultipleVarDecl": true,
"disallowQuotedKeysInObjects": "allButReserved",
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
"disallowSpaceBeforeBinaryOperators": [","],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
"disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true },
"disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true },
"disallowSpacesInsideArrayBrackets": true,
"disallowSpacesInsideParentheses": true,
"disallowTrailingComma": true,
"disallowTrailingWhitespace": true,
"requireCamelCaseOrUpperCaseIdentifiers": true,
"requireCapitalizedConstructors": true,
"requireCommaBeforeLineBreak": true,
"requireDollarBeforejQueryAssignment": true,
"requireDotNotation": true,
"requireLineFeedAtFileEnd": true,
"requirePaddingNewLinesAfterUseStrict": true,
"requirePaddingNewLinesBeforeExport": true,
"requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"requireSpaceAfterLineComment": true,
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="],
"requireSpaceBetweenArguments": true,
"requireSpacesInAnonymousFunctionExpression": { "beforeOpeningCurlyBrace": true, "beforeOpeningRoundBrace": true },
"requireSpacesInConditionalExpression": true,
"requireSpacesInForStatement": true,
"requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
"requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true },
"requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true },
"requireSpacesInsideObjectBrackets": "allButNested",
"validateAlignedFunctionParameters": true,
"validateIndentation": 2,
"validateLineBreaks": "LF",
"validateNewlineAfterArrayElements": true,
"validateQuoteMarks": "'"
}

View file

@ -1,15 +0,0 @@
{
"asi" : true,
"browser" : true,
"eqeqeq" : false,
"eqnull" : true,
"es3" : true,
"expr" : true,
"jquery" : true,
"latedef" : true,
"laxbreak" : true,
"nonbsp" : true,
"strict" : true,
"undef" : true,
"unused" : true
}

View file

@ -1,162 +0,0 @@
/* ========================================================================
* Bootstrap: affix.js v3.3.6
* http://getbootstrap.com/javascript/#affix
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// AFFIX CLASS DEFINITION
// ======================
var Affix = function (element, options) {
this.options = $.extend({}, Affix.DEFAULTS, options)
this.$target = $(this.options.target)
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
.on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
this.$element = $(element)
this.affixed = null
this.unpin = null
this.pinnedOffset = null
this.checkPosition()
}
Affix.VERSION = '3.3.6'
Affix.RESET = 'affix affix-top affix-bottom'
Affix.DEFAULTS = {
offset: 0,
target: window
}
Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
var scrollTop = this.$target.scrollTop()
var position = this.$element.offset()
var targetHeight = this.$target.height()
if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
if (this.affixed == 'bottom') {
if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
}
var initializing = this.affixed == null
var colliderTop = initializing ? scrollTop : position.top
var colliderHeight = initializing ? targetHeight : height
if (offsetTop != null && scrollTop <= offsetTop) return 'top'
if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
return false
}
Affix.prototype.getPinnedOffset = function () {
if (this.pinnedOffset) return this.pinnedOffset
this.$element.removeClass(Affix.RESET).addClass('affix')
var scrollTop = this.$target.scrollTop()
var position = this.$element.offset()
return (this.pinnedOffset = position.top - scrollTop)
}
Affix.prototype.checkPositionWithEventLoop = function () {
setTimeout($.proxy(this.checkPosition, this), 1)
}
Affix.prototype.checkPosition = function () {
if (!this.$element.is(':visible')) return
var height = this.$element.height()
var offset = this.options.offset
var offsetTop = offset.top
var offsetBottom = offset.bottom
var scrollHeight = Math.max($(document).height(), $(document.body).height())
if (typeof offset != 'object') offsetBottom = offsetTop = offset
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
if (this.affixed != affix) {
if (this.unpin != null) this.$element.css('top', '')
var affixType = 'affix' + (affix ? '-' + affix : '')
var e = $.Event(affixType + '.bs.affix')
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
this.affixed = affix
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
this.$element
.removeClass(Affix.RESET)
.addClass(affixType)
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
}
if (affix == 'bottom') {
this.$element.offset({
top: scrollHeight - height - offsetBottom
})
}
}
// AFFIX PLUGIN DEFINITION
// =======================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.affix')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.affix
$.fn.affix = Plugin
$.fn.affix.Constructor = Affix
// AFFIX NO CONFLICT
// =================
$.fn.affix.noConflict = function () {
$.fn.affix = old
return this
}
// AFFIX DATA-API
// ==============
$(window).on('load', function () {
$('[data-spy="affix"]').each(function () {
var $spy = $(this)
var data = $spy.data()
data.offset = data.offset || {}
if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
if (data.offsetTop != null) data.offset.top = data.offsetTop
Plugin.call($spy, data)
})
})
}(jQuery);

View file

@ -1,94 +0,0 @@
/* ========================================================================
* Bootstrap: alert.js v3.3.6
* http://getbootstrap.com/javascript/#alerts
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// ALERT CLASS DEFINITION
// ======================
var dismiss = '[data-dismiss="alert"]'
var Alert = function (el) {
$(el).on('click', dismiss, this.close)
}
Alert.VERSION = '3.3.6'
Alert.TRANSITION_DURATION = 150
Alert.prototype.close = function (e) {
var $this = $(this)
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = $(selector)
if (e) e.preventDefault()
if (!$parent.length) {
$parent = $this.closest('.alert')
}
$parent.trigger(e = $.Event('close.bs.alert'))
if (e.isDefaultPrevented()) return
$parent.removeClass('in')
function removeElement() {
// detach from parent, fire event then clean up data
$parent.detach().trigger('closed.bs.alert').remove()
}
$.support.transition && $parent.hasClass('fade') ?
$parent
.one('bsTransitionEnd', removeElement)
.emulateTransitionEnd(Alert.TRANSITION_DURATION) :
removeElement()
}
// ALERT PLUGIN DEFINITION
// =======================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.alert')
if (!data) $this.data('bs.alert', (data = new Alert(this)))
if (typeof option == 'string') data[option].call($this)
})
}
var old = $.fn.alert
$.fn.alert = Plugin
$.fn.alert.Constructor = Alert
// ALERT NO CONFLICT
// =================
$.fn.alert.noConflict = function () {
$.fn.alert = old
return this
}
// ALERT DATA-API
// ==============
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
}(jQuery);

View file

@ -1,120 +0,0 @@
/* ========================================================================
* Bootstrap: button.js v3.3.6
* http://getbootstrap.com/javascript/#buttons
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
var Button = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Button.DEFAULTS, options)
this.isLoading = false
}
Button.VERSION = '3.3.6'
Button.DEFAULTS = {
loadingText: 'loading...'
}
Button.prototype.setState = function (state) {
var d = 'disabled'
var $el = this.$element
var val = $el.is('input') ? 'val' : 'html'
var data = $el.data()
state += 'Text'
if (data.resetText == null) $el.data('resetText', $el[val]())
// push to event loop to allow forms to submit
setTimeout($.proxy(function () {
$el[val](data[state] == null ? this.options[state] : data[state])
if (state == 'loadingText') {
this.isLoading = true
$el.addClass(d).attr(d, d)
} else if (this.isLoading) {
this.isLoading = false
$el.removeClass(d).removeAttr(d)
}
}, this), 0)
}
Button.prototype.toggle = function () {
var changed = true
var $parent = this.$element.closest('[data-toggle="buttons"]')
if ($parent.length) {
var $input = this.$element.find('input')
if ($input.prop('type') == 'radio') {
if ($input.prop('checked')) changed = false
$parent.find('.active').removeClass('active')
this.$element.addClass('active')
} else if ($input.prop('type') == 'checkbox') {
if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
this.$element.toggleClass('active')
}
$input.prop('checked', this.$element.hasClass('active'))
if (changed) $input.trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
this.$element.toggleClass('active')
}
}
// BUTTON PLUGIN DEFINITION
// ========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.button')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.button', (data = new Button(this, options)))
if (option == 'toggle') data.toggle()
else if (option) data.setState(option)
})
}
var old = $.fn.button
$.fn.button = Plugin
$.fn.button.Constructor = Button
// BUTTON NO CONFLICT
// ==================
$.fn.button.noConflict = function () {
$.fn.button = old
return this
}
// BUTTON DATA-API
// ===============
$(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
var $btn = $(e.target)
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
Plugin.call($btn, 'toggle')
if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
})
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
$(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
})
}(jQuery);

View file

@ -1,237 +0,0 @@
/* ========================================================================
* Bootstrap: carousel.js v3.3.6
* http://getbootstrap.com/javascript/#carousel
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// CAROUSEL CLASS DEFINITION
// =========================
var Carousel = function (element, options) {
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
this.paused = null
this.sliding = null
this.interval = null
this.$active = null
this.$items = null
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
Carousel.VERSION = '3.3.6'
Carousel.TRANSITION_DURATION = 600
Carousel.DEFAULTS = {
interval: 5000,
pause: 'hover',
wrap: true,
keyboard: true
}
Carousel.prototype.keydown = function (e) {
if (/input|textarea/i.test(e.target.tagName)) return
switch (e.which) {
case 37: this.prev(); break
case 39: this.next(); break
default: return
}
e.preventDefault()
}
Carousel.prototype.cycle = function (e) {
e || (this.paused = false)
this.interval && clearInterval(this.interval)
this.options.interval
&& !this.paused
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
return this
}
Carousel.prototype.getItemIndex = function (item) {
this.$items = item.parent().children('.item')
return this.$items.index(item || this.$active)
}
Carousel.prototype.getItemForDirection = function (direction, active) {
var activeIndex = this.getItemIndex(active)
var willWrap = (direction == 'prev' && activeIndex === 0)
|| (direction == 'next' && activeIndex == (this.$items.length - 1))
if (willWrap && !this.options.wrap) return active
var delta = direction == 'prev' ? -1 : 1
var itemIndex = (activeIndex + delta) % this.$items.length
return this.$items.eq(itemIndex)
}
Carousel.prototype.to = function (pos) {
var that = this
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
if (pos > (this.$items.length - 1) || pos < 0) return
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
if (activeIndex == pos) return this.pause().cycle()
return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
}
Carousel.prototype.pause = function (e) {
e || (this.paused = true)
if (this.$element.find('.next, .prev').length && $.support.transition) {
this.$element.trigger($.support.transition.end)
this.cycle(true)
}
this.interval = clearInterval(this.interval)
return this
}
Carousel.prototype.next = function () {
if (this.sliding) return
return this.slide('next')
}
Carousel.prototype.prev = function () {
if (this.sliding) return
return this.slide('prev')
}
Carousel.prototype.slide = function (type, next) {
var $active = this.$element.find('.item.active')
var $next = next || this.getItemForDirection(type, $active)
var isCycling = this.interval
var direction = type == 'next' ? 'left' : 'right'
var that = this
if ($next.hasClass('active')) return (this.sliding = false)
var relatedTarget = $next[0]
var slideEvent = $.Event('slide.bs.carousel', {
relatedTarget: relatedTarget,
direction: direction
})
this.$element.trigger(slideEvent)
if (slideEvent.isDefaultPrevented()) return
this.sliding = true
isCycling && this.pause()
if (this.$indicators.length) {
this.$indicators.find('.active').removeClass('active')
var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
$nextIndicator && $nextIndicator.addClass('active')
}
var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
if ($.support.transition && this.$element.hasClass('slide')) {
$next.addClass(type)
$next[0].offsetWidth // force reflow
$active.addClass(direction)
$next.addClass(direction)
$active
.one('bsTransitionEnd', function () {
$next.removeClass([type, direction].join(' ')).addClass('active')
$active.removeClass(['active', direction].join(' '))
that.sliding = false
setTimeout(function () {
that.$element.trigger(slidEvent)
}, 0)
})
.emulateTransitionEnd(Carousel.TRANSITION_DURATION)
} else {
$active.removeClass('active')
$next.addClass('active')
this.sliding = false
this.$element.trigger(slidEvent)
}
isCycling && this.cycle()
return this
}
// CAROUSEL PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.carousel')
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
var action = typeof option == 'string' ? option : options.slide
if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
if (typeof option == 'number') data.to(option)
else if (action) data[action]()
else if (options.interval) data.pause().cycle()
})
}
var old = $.fn.carousel
$.fn.carousel = Plugin
$.fn.carousel.Constructor = Carousel
// CAROUSEL NO CONFLICT
// ====================
$.fn.carousel.noConflict = function () {
$.fn.carousel = old
return this
}
// CAROUSEL DATA-API
// =================
var clickHandler = function (e) {
var href
var $this = $(this)
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
if (!$target.hasClass('carousel')) return
var options = $.extend({}, $target.data(), $this.data())
var slideIndex = $this.attr('data-slide-to')
if (slideIndex) options.interval = false
Plugin.call($target, options)
if (slideIndex) {
$target.data('bs.carousel').to(slideIndex)
}
e.preventDefault()
}
$(document)
.on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
.on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
$(window).on('load', function () {
$('[data-ride="carousel"]').each(function () {
var $carousel = $(this)
Plugin.call($carousel, $carousel.data())
})
})
}(jQuery);

View file

@ -1,211 +0,0 @@
/* ========================================================================
* Bootstrap: collapse.js v3.3.6
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
'[data-toggle="collapse"][data-target="#' + element.id + '"]')
this.transitioning = null
if (this.options.parent) {
this.$parent = this.getParent()
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
}
if (this.options.toggle) this.toggle()
}
Collapse.VERSION = '3.3.6'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
if (actives && actives.length) {
Plugin.call(actives, 'hide')
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
.attr('aria-expanded', true)
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('collapse in')[dimension]('')
this.transitioning = 0
this.$element
.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse in')
.attr('aria-expanded', false)
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.removeClass('collapsing')
.addClass('collapse')
.trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
Collapse.prototype.getParent = function () {
return $(this.options.parent)
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
.each($.proxy(function (i, element) {
var $element = $(element)
this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
}, this))
.end()
}
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
var isOpen = $element.hasClass('in')
$element.attr('aria-expanded', isOpen)
$trigger
.toggleClass('collapsed', !isOpen)
.attr('aria-expanded', isOpen)
}
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target)
}
// COLLAPSE PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.collapse
$.fn.collapse = Plugin
$.fn.collapse.Constructor = Collapse
// COLLAPSE NO CONFLICT
// ====================
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return this
}
// COLLAPSE DATA-API
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
var $this = $(this)
if (!$this.attr('data-target')) e.preventDefault()
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $this.data()
Plugin.call($target, option)
})
}(jQuery);

View file

@ -1,165 +0,0 @@
/* ========================================================================
* Bootstrap: dropdown.js v3.3.6
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// DROPDOWN CLASS DEFINITION
// =========================
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle="dropdown"]'
var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle)
}
Dropdown.VERSION = '3.3.6'
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
function clearMenus(e) {
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
var $this = $(this)
var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return
if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
})
}
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
$(document.createElement('div'))
.addClass('dropdown-backdrop')
.insertAfter($(this))
.on('click', clearMenus)
}
var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this
.trigger('focus')
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger($.Event('shown.bs.dropdown', relatedTarget))
}
return false
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if (!isActive && e.which != 27 || isActive && e.which == 27) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
var desc = ' li:not(.disabled):visible a'
var $items = $parent.find('.dropdown-menu' + desc)
if (!$items.length) return
var index = $items.index(e.target)
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.dropdown')
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
}(jQuery);

View file

@ -1,337 +0,0 @@
/* ========================================================================
* Bootstrap: modal.js v3.3.6
* http://getbootstrap.com/javascript/#modals
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) {
this.options = options
this.$body = $(document.body)
this.$element = $(element)
this.$dialog = this.$element.find('.modal-dialog')
this.$backdrop = null
this.isShown = null
this.originalBodyPad = null
this.scrollbarWidth = 0
this.ignoreBackdropClick = false
if (this.options.remote) {
this.$element
.find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
}
Modal.VERSION = '3.3.6'
Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
keyboard: true,
show: true
}
Modal.prototype.toggle = function (_relatedTarget) {
return this.isShown ? this.hide() : this.show(_relatedTarget)
}
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
this.isShown = true
this.checkScrollbar()
this.setScrollbar()
this.$body.addClass('modal-open')
this.escape()
this.resize()
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.$dialog.on('mousedown.dismiss.bs.modal', function () {
that.$element.one('mouseup.dismiss.bs.modal', function (e) {
if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
})
})
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
}
that.$element
.show()
.scrollTop(0)
that.adjustDialog()
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element.addClass('in')
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$dialog // wait for modal to slide in
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
this.escape()
this.resize()
$(document).off('focusin.bs.modal')
this.$element
.removeClass('in')
.off('click.dismiss.bs.modal')
.off('mouseup.dismiss.bs.modal')
this.$dialog.off('mousedown.dismiss.bs.modal')
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
Modal.prototype.enforceFocus = function () {
$(document)
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.trigger('focus')
}
}, this))
}
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
this.$element.off('keydown.dismiss.bs.modal')
}
}
Modal.prototype.resize = function () {
if (this.isShown) {
$(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
} else {
$(window).off('resize.bs.modal')
}
}
Modal.prototype.hideModal = function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetAdjustments()
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
Modal.prototype.backdrop = function (callback) {
var that = this
var animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $(document.createElement('div'))
.addClass('modal-backdrop ' + animate)
.appendTo(this.$body)
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (this.ignoreBackdropClick) {
this.ignoreBackdropClick = false
return
}
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus()
: this.hide()
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if (!callback) return
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
var callbackRemove = function () {
that.removeBackdrop()
callback && callback()
}
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if (callback) {
callback()
}
}
// these following methods are used to handle overflowing modals
Modal.prototype.handleUpdate = function () {
this.adjustDialog()
}
Modal.prototype.adjustDialog = function () {
var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
this.$element.css({
paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
})
}
Modal.prototype.resetAdjustments = function () {
this.$element.css({
paddingLeft: '',
paddingRight: ''
})
}
Modal.prototype.checkScrollbar = function () {
var fullWindowWidth = window.innerWidth
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
var documentElementRect = document.documentElement.getBoundingClientRect()
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
}
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
this.scrollbarWidth = this.measureScrollbar()
}
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
this.originalBodyPad = document.body.style.paddingRight || ''
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
}
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', this.originalBodyPad)
}
Modal.prototype.measureScrollbar = function () { // thx walsh
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv)
return scrollbarWidth
}
// MODAL PLUGIN DEFINITION
// =======================
function Plugin(option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
}
var old = $.fn.modal
$.fn.modal = Plugin
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT
// =================
$.fn.modal.noConflict = function () {
$.fn.modal = old
return this
}
// MODAL DATA-API
// ==============
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
if ($this.is('a')) e.preventDefault()
$target.one('show.bs.modal', function (showEvent) {
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
$target.one('hidden.bs.modal', function () {
$this.is(':visible') && $this.trigger('focus')
})
})
Plugin.call($target, option, this)
})
}(jQuery);

View file

@ -1,108 +0,0 @@
/* ========================================================================
* Bootstrap: popover.js v3.3.6
* http://getbootstrap.com/javascript/#popovers
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// POPOVER PUBLIC CLASS DEFINITION
// ===============================
var Popover = function (element, options) {
this.init('popover', element, options)
}
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
Popover.VERSION = '3.3.6'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right',
trigger: 'click',
content: '',
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
})
// NOTE: POPOVER EXTENDS tooltip.js
// ================================
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
Popover.prototype.constructor = Popover
Popover.prototype.getDefaults = function () {
return Popover.DEFAULTS
}
Popover.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
var content = this.getContent()
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
](content)
$tip.removeClass('fade top bottom left right in')
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
// this manually by checking the contents.
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
}
Popover.prototype.hasContent = function () {
return this.getTitle() || this.getContent()
}
Popover.prototype.getContent = function () {
var $e = this.$element
var o = this.options
return $e.attr('data-content')
|| (typeof o.content == 'function' ?
o.content.call($e[0]) :
o.content)
}
Popover.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
}
// POPOVER PLUGIN DEFINITION
// =========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.popover
$.fn.popover = Plugin
$.fn.popover.Constructor = Popover
// POPOVER NO CONFLICT
// ===================
$.fn.popover.noConflict = function () {
$.fn.popover = old
return this
}
}(jQuery);

View file

@ -1,172 +0,0 @@
/* ========================================================================
* Bootstrap: scrollspy.js v3.3.6
* http://getbootstrap.com/javascript/#scrollspy
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// SCROLLSPY CLASS DEFINITION
// ==========================
function ScrollSpy(element, options) {
this.$body = $(document.body)
this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
this.selector = (this.options.target || '') + ' .nav li > a'
this.offsets = []
this.targets = []
this.activeTarget = null
this.scrollHeight = 0
this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
this.refresh()
this.process()
}
ScrollSpy.VERSION = '3.3.6'
ScrollSpy.DEFAULTS = {
offset: 10
}
ScrollSpy.prototype.getScrollHeight = function () {
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}
ScrollSpy.prototype.refresh = function () {
var that = this
var offsetMethod = 'offset'
var offsetBase = 0
this.offsets = []
this.targets = []
this.scrollHeight = this.getScrollHeight()
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
this.$body
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
return ($href
&& $href.length
&& $href.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
.each(function () {
that.offsets.push(this[0])
that.targets.push(this[1])
})
}
ScrollSpy.prototype.process = function () {
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
var scrollHeight = this.getScrollHeight()
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
var offsets = this.offsets
var targets = this.targets
var activeTarget = this.activeTarget
var i
if (this.scrollHeight != scrollHeight) {
this.refresh()
}
if (scrollTop >= maxScroll) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
&& this.activate(targets[i])
}
}
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target
this.clear()
var selector = this.selector +
'[data-target="' + target + '"],' +
this.selector + '[href="' + target + '"]'
var active = $(selector)
.parents('li')
.addClass('active')
if (active.parent('.dropdown-menu').length) {
active = active
.closest('li.dropdown')
.addClass('active')
}
active.trigger('activate.bs.scrollspy')
}
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
// SCROLLSPY PLUGIN DEFINITION
// ===========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.scrollspy')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.scrollspy
$.fn.scrollspy = Plugin
$.fn.scrollspy.Constructor = ScrollSpy
// SCROLLSPY NO CONFLICT
// =====================
$.fn.scrollspy.noConflict = function () {
$.fn.scrollspy = old
return this
}
// SCROLLSPY DATA-API
// ==================
$(window).on('load.bs.scrollspy.data-api', function () {
$('[data-spy="scroll"]').each(function () {
var $spy = $(this)
Plugin.call($spy, $spy.data())
})
})
}(jQuery);

View file

@ -1,155 +0,0 @@
/* ========================================================================
* Bootstrap: tab.js v3.3.6
* http://getbootstrap.com/javascript/#tabs
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// TAB CLASS DEFINITION
// ====================
var Tab = function (element) {
// jscs:disable requireDollarBeforejQueryAssignment
this.element = $(element)
// jscs:enable requireDollarBeforejQueryAssignment
}
Tab.VERSION = '3.3.6'
Tab.TRANSITION_DURATION = 150
Tab.prototype.show = function () {
var $this = this.element
var $ul = $this.closest('ul:not(.dropdown-menu)')
var selector = $this.data('target')
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
if ($this.parent('li').hasClass('active')) return
var $previous = $ul.find('.active:last a')
var hideEvent = $.Event('hide.bs.tab', {
relatedTarget: $this[0]
})
var showEvent = $.Event('show.bs.tab', {
relatedTarget: $previous[0]
})
$previous.trigger(hideEvent)
$this.trigger(showEvent)
if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
var $target = $(selector)
this.activate($this.closest('li'), $ul)
this.activate($target, $target.parent(), function () {
$previous.trigger({
type: 'hidden.bs.tab',
relatedTarget: $this[0]
})
$this.trigger({
type: 'shown.bs.tab',
relatedTarget: $previous[0]
})
})
}
Tab.prototype.activate = function (element, container, callback) {
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
&& ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
function next() {
$active
.removeClass('active')
.find('> .dropdown-menu > .active')
.removeClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', false)
element
.addClass('active')
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
if (transition) {
element[0].offsetWidth // reflow for transition
element.addClass('in')
} else {
element.removeClass('fade')
}
if (element.parent('.dropdown-menu').length) {
element
.closest('li.dropdown')
.addClass('active')
.end()
.find('[data-toggle="tab"]')
.attr('aria-expanded', true)
}
callback && callback()
}
$active.length && transition ?
$active
.one('bsTransitionEnd', next)
.emulateTransitionEnd(Tab.TRANSITION_DURATION) :
next()
$active.removeClass('in')
}
// TAB PLUGIN DEFINITION
// =====================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tab')
if (!data) $this.data('bs.tab', (data = new Tab(this)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.tab
$.fn.tab = Plugin
$.fn.tab.Constructor = Tab
// TAB NO CONFLICT
// ===============
$.fn.tab.noConflict = function () {
$.fn.tab = old
return this
}
// TAB DATA-API
// ============
var clickHandler = function (e) {
e.preventDefault()
Plugin.call($(this), 'show')
}
$(document)
.on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
.on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
}(jQuery);

View file

@ -1,514 +0,0 @@
/* ========================================================================
* Bootstrap: tooltip.js v3.3.6
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// TOOLTIP PUBLIC CLASS DEFINITION
// ===============================
var Tooltip = function (element, options) {
this.type = null
this.options = null
this.enabled = null
this.timeout = null
this.hoverState = null
this.$element = null
this.inState = null
this.init('tooltip', element, options)
}
Tooltip.VERSION = '3.3.6'
Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = {
animation: true,
placement: 'top',
selector: false,
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
trigger: 'hover focus',
title: '',
delay: 0,
html: false,
container: false,
viewport: {
selector: 'body',
padding: 0
}
}
Tooltip.prototype.init = function (type, element, options) {
this.enabled = true
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
this.inState = { click: false, hover: false, focus: false }
if (this.$element[0] instanceof document.constructor && !this.options.selector) {
throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
}
var triggers = this.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
var trigger = triggers[i]
if (trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (trigger != 'manual') {
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
Tooltip.prototype.getDefaults = function () {
return Tooltip.DEFAULTS
}
Tooltip.prototype.getOptions = function (options) {
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay,
hide: options.delay
}
}
return options
}
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
})
return options
}
Tooltip.prototype.enter = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
if (obj instanceof $.Event) {
self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
}
if (self.tip().hasClass('in') || self.hoverState == 'in') {
self.hoverState = 'in'
return
}
clearTimeout(self.timeout)
self.hoverState = 'in'
if (!self.options.delay || !self.options.delay.show) return self.show()
self.timeout = setTimeout(function () {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
Tooltip.prototype.isInStateTrue = function () {
for (var key in this.inState) {
if (this.inState[key]) return true
}
return false
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
if (obj instanceof $.Event) {
self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
}
if (self.isInStateTrue()) return
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
Tooltip.prototype.show = function () {
var e = $.Event('show.bs.' + this.type)
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
var $tip = this.tip()
var tipId = this.getUID(this.type)
this.setContent()
$tip.attr('id', tipId)
this.$element.attr('aria-describedby', tipId)
if (this.options.animation) $tip.addClass('fade')
var placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
var autoToken = /\s?auto?\s?/i
var autoPlace = autoToken.test(placement)
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
$tip
.detach()
.css({ top: 0, left: 0, display: 'block' })
.addClass(placement)
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
this.$element.trigger('inserted.bs.' + this.type)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var orgPlacement = placement
var viewportDim = this.getPosition(this.$viewport)
placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
}
}
Tooltip.prototype.applyPlacement = function (offset, placement) {
var $tip = this.tip()
var width = $tip[0].offsetWidth
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference
var marginTop = parseInt($tip.css('margin-top'), 10)
var marginLeft = parseInt($tip.css('margin-left'), 10)
// we must check for NaN for ie 8/9
if (isNaN(marginTop)) marginTop = 0
if (isNaN(marginLeft)) marginLeft = 0
offset.top += marginTop
offset.left += marginLeft
// $.fn.offset doesn't round pixel values
// so we use setOffset directly with our own function B-0
$.offset.setOffset($tip[0], $.extend({
using: function (props) {
$tip.css({
top: Math.round(props.top),
left: Math.round(props.left)
})
}
}, offset), 0)
$tip.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
offset.top = offset.top + height - actualHeight
}
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
if (delta.left) offset.left += delta.left
else offset.top += delta.top
var isVertical = /top|bottom/.test(placement)
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
this.arrow()
.css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
.css(isVertical ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
var $tip = this.tip()
var title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = $(this.$tip)
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
that.$element
.removeAttr('aria-describedby')
.trigger('hidden.bs.' + that.type)
callback && callback()
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
$tip.removeClass('in')
$.support.transition && $tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
return this
}
Tooltip.prototype.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') || '').attr('title', '')
}
}
Tooltip.prototype.hasContent = function () {
return this.getTitle()
}
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName == 'BODY'
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
var delta = { top: 0, left: 0 }
if (!this.$viewport) return delta
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
var viewportDimensions = this.getPosition(this.$viewport)
if (/right|left/.test(placement)) {
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
if (topEdgeOffset < viewportDimensions.top) { // top overflow
delta.top = viewportDimensions.top - topEdgeOffset
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
}
} else {
var leftEdgeOffset = pos.left - viewportPadding
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
delta.left = viewportDimensions.left - leftEdgeOffset
} else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
}
}
return delta
}
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
var o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
Tooltip.prototype.getUID = function (prefix) {
do prefix += ~~(Math.random() * 1000000)
while (document.getElementById(prefix))
return prefix
}
Tooltip.prototype.tip = function () {
if (!this.$tip) {
this.$tip = $(this.options.template)
if (this.$tip.length != 1) {
throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
}
}
return this.$tip
}
Tooltip.prototype.arrow = function () {
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
Tooltip.prototype.disable = function () {
this.enabled = false
}
Tooltip.prototype.toggleEnabled = function () {
this.enabled = !this.enabled
}
Tooltip.prototype.toggle = function (e) {
var self = this
if (e) {
self = $(e.currentTarget).data('bs.' + this.type)
if (!self) {
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
$(e.currentTarget).data('bs.' + this.type, self)
}
}
if (e) {
self.inState.click = !self.inState.click
if (self.isInStateTrue()) self.enter(self)
else self.leave(self)
} else {
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
}
Tooltip.prototype.destroy = function () {
var that = this
clearTimeout(this.timeout)
this.hide(function () {
that.$element.off('.' + that.type).removeData('bs.' + that.type)
if (that.$tip) {
that.$tip.detach()
}
that.$tip = null
that.$arrow = null
that.$viewport = null
})
}
// TOOLTIP PLUGIN DEFINITION
// =========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.tooltip
$.fn.tooltip = Plugin
$.fn.tooltip.Constructor = Tooltip
// TOOLTIP NO CONFLICT
// ===================
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
}(jQuery);

View file

@ -1,59 +0,0 @@
/* ========================================================================
* Bootstrap: transition.js v3.3.6
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false
var $el = this
$(this).one('bsTransitionEnd', function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
if (!$.support.transition) return
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
}
})
}(jQuery);

View file

@ -0,0 +1,65 @@
// ----------------------------------
// Components
// ----------------------------------
$enable-shadows: true;
$enable-reduced-motion: false;
// ----------------------------------
// Colors
// ----------------------------------
$body-bg: #f5f5f8;
$gray-100: #f1f3f5;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #868e96;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$primary: #03a9f4;
$blue: #2680d9;
$green: #5cb85c;
$yellow: #f0ad4e;
$red: #d9534f;
// ----------------------------------
// Typography
// ----------------------------------
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-size-root: 15px;
$navbar-brand-font-size: 1.4rem;
// ----------------------------------
// Links
// ----------------------------------
$link-decoration: none;
// ----------------------------------
// Tables
// ----------------------------------
$table-cell-padding-y: .3rem;
$table-cell-padding-x: .3rem;
$table-cell-padding-y-sm: .23rem;
$table-cell-padding-x-sm: .23rem;
$table-striped-bg: $gray-100;
$table-hover-bg: $gray-200;
// ----------------------------------
// Form
// ----------------------------------
$input-bg: white;
$form-label-font-weight: bold;

View file

@ -1,32 +0,0 @@
// ---------------------------
// Custom bootstrap variables.
// ---------------------------
$body-bg: #f5f5f8;
$font-size-base: 15px;
$nav-link-hover-bg: none;
// ---------------------------
// Source imports
// ---------------------------
@import "bootstrap/variables";
@import "bootstrap/mixins";
@import "bootstrap/normalize";
@import "bootstrap/close";
@import "bootstrap/alerts";
@import "bootstrap/print";
@import "bootstrap/type";
@import "bootstrap/code";
@import "bootstrap/tables";
@import "bootstrap/forms";
@import "bootstrap/scaffolding";
@import "bootstrap/grid";
@import "bootstrap/utilities";
@import "bootstrap/navs";
@import "bootstrap/dropdowns";
@import "bootstrap/modals";
@import "bootstrap/component-animations";

View file

@ -1,3 +1,4 @@
@import "mixins/button";
@import "mixins/center-block";
@import "mixins/icon-vcenter";

View file

@ -8,12 +8,12 @@ $image-path: #{$base-path}/img;
// ----------------------------------
// Colors
// ----------------------------------
$gray-lightest: #f9f9f9;
$gray-light: #dcdcdc;
$gray-dark: #444;
$gray-darker: #202020;
$black: #000;
$white: #fff;
// TODO: Remove
$gray-lightest: $gray-100;
$gray-light: $gray-300;
$gray-dark: $gray-700;
$gray-darker: $gray-900;
// Text
$text-color: #333;
@ -25,37 +25,26 @@ $foreground-color: $white;
$hover-color: $gray-lightest;
$border-color: $gray-light;
// Brand
$brand-color: #03a9f4;
$brand-info: hsl(210, 70%, 50%);
$google-color: #db4437;
$github-color: #4183c4;
$gitlab-color: #548;
$linkedin-color: #0077B5;
// ----------------------------------
// Font
// Typography
// ----------------------------------
$font-size-navigation: 20px;
$text-size-large: 20px;
$font-size-navigation: $navbar-brand-font-size;
$font-size-large: 20px;
$font-size-small: 14px;
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-family-base: $font-family-sans-serif;
// ----------------------------------
// Layout
// ----------------------------------
$header-text-shadow: 1px 3px 4px rgba(0, 0, 0, 0.45);
// navigation
$navbar-breakpoint-min: $screen-md-min;
$navbar-height: 60px;
$navbar-link-vertical-spacing: 8px;
$navbar-link-underline-height: 2px;
@ -70,8 +59,10 @@ $navbar-link-hover-underline: $navbar-link-color;
$navbar-link-active-color: $navbar-link-color;
$navbar-link-active-underline: $navbar-link-color;
$navbar-brand-color: $brand-color;
$navbar-brand-hover-color: darken($brand-color, 15%);
$navbar-brand-color: $primary;
$navbar-brand-hover-color: darken($primary, 15%);
$nav-link-hover-bg: none;
// User menu
$usermenu-button-bg: $navbar-background;
@ -79,6 +70,7 @@ $usermenu-button-hover-bg: darken($usermenu-button-bg, 8%);
// Footer
$footer-height: 80px;
$footer-spacing: 1rem;
$footer-border-color: $border-color;
$footer-text-color: $text-secondary-color;
$footer-link-color: $footer-text-color;
@ -99,17 +91,17 @@ $button-primary-color: white;
$button-primary-bg: #5fbc49;
$button-brand-color: white;
$button-brand-bg: $brand-color;
$button-brand-bg: $primary;
// State
$button-info-color: white;
$button-info-bg: $brand-info;
$button-info-bg: $info;
$button-success-color: white;
$button-success-bg: $brand-success;
$button-success-bg: $success;
$button-warning-color: white;
$button-warning-bg: $brand-warning;
$button-warning-bg: $warning;
$button-danger-color: white;
$button-danger-bg: $brand-danger;
$button-danger-bg: $danger;
// Company.
@ -136,7 +128,7 @@ $list-group-item-background: transparent;
$list-group-item-border-color: $gray-light;
$list-group-hover-background: $gray-lightest;
$list-group-item-active-background: $brand-color;
$list-group-item-active-background: $primary;
// ----------------------------------
// List group
@ -185,8 +177,8 @@ $pagination-border: $border-color;
$pagination-hover: $hover-color;
$pagination-active-color: $white;
$pagination-active-bg: $brand-color;
$pagination-active-border: darken($brand-color, 5%);
$pagination-active-bg: $primary;
$pagination-active-border: darken($primary, 5%);
// ----------------------------------
// Section
@ -218,4 +210,4 @@ $callback-list-arrow-color: $callback-list-border-color;
// ----------------------------------
$request-item-secondary-color: $text-secondary-color;
$request-detail-background: lighten($brand-color, 45%);
$request-detail-background: lighten($primary, 45%);

View file

@ -1,23 +1,54 @@
// ---------------------------
// Bootstrap & Fonts
// ---------------------------
@import "bootstrap-custom";
// Fonts
@import url('https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i');
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700,700i');
@import "bootstrap/scss/functions";
// ---------------------------
// Bootstrap config
// ---------------------------
@import "bootstrap-config";
// ---------------------------
// Bootstrap
// ---------------------------
@import "bootstrap/scss/variables";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";
// Optional
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/close";
@import "bootstrap/scss/alert";
@import "bootstrap/scss/type";
@import "bootstrap/scss/tables";
@import "bootstrap/scss/forms";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/dropdown";
@import "bootstrap/scss/modal";
@import "bootstrap/scss/images";
@import "bootstrap/scss/transitions";
@import "bootstrap/scss/utilities/api";
// ---------------------------
// Site
// ---------------------------
// variables & mixins.
@import "variables";
@import "mixins";
// Base
@import "base/global";
@import "base/typography";
@import "base/utils";
// Layout
@import "layout/sections";

View file

@ -1,5 +1,6 @@
html {
position: relative;
min-height: 100%;
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}

View file

@ -12,3 +12,14 @@
.text-gitlab { color: $gitlab-color; }
.text-google { color: $google-color; }
.text-linkedin { color: $linkedin-color; }
a:hover {
text-decoration: underline;
}
.code {
background: $gray-100;
border: solid $gray-300 1px;
border-radius: $border-radius;
padding: .6em;
}

View file

@ -0,0 +1,8 @@
.center-block {
@include center-block();
}
.clearfix {
@include clearfix();
}

View file

@ -21,7 +21,7 @@
&-primary {
color: white;
background-color: $brand-color;
background-color: $primary;
}
&-info {

View file

@ -64,7 +64,7 @@
// Sizes
// ----------------------------------
.button-large { font-size: $text-size-large; }
.button-large { font-size: $font-size-large; }
.button-small { font-size: 0.6em; }
// Block button

View file

@ -1,78 +1,81 @@
.callback-list {
margin-top: 1em;
.callback-list-item {
@extend .clearfix;
position: relative;
padding: .6em 1em;
&-item {
@include clearfix();
position: relative;
padding: .6em 1em;
&:hover {
background: $gray-lightest;
}
&:hover {
background: $gray-lightest;
}
// Borders.
// --------
// Borders.
// --------
border: solid $callback-list-border-color $callback-list-border-size;
border: solid $callback-list-border-color $callback-list-border-size;
// Remove top border for all except first child.
&:not(:first-child) {
border-top: 0;
}
// Remove top border for all except first child.
&:not(:first-child) {
border-top: 0;
}
// top border radius for first child.
&:first-child {
border-top-left-radius: $callback-list-border-radius;
border-top-right-radius: $callback-list-border-radius;
}
// top border radius for first child.
&:first-child {
border-top-left-radius: $callback-list-border-radius;
border-top-right-radius: $callback-list-border-radius;
}
// bottom border radius for first child.
&:last-child {
border-bottom-left-radius: $callback-list-border-radius;
border-bottom-right-radius: $callback-list-border-radius;
}
// bottom border radius for first child.
&:last-child {
border-bottom-left-radius: $callback-list-border-radius;
border-bottom-right-radius: $callback-list-border-radius;
}
// Sections.
// ---------
// Sections.
// ---------
&-header {
margin-bottom: .4em;
}
&-header {
margin-bottom: .4em;
}
&-info {
font-size: $font-size-small;
color: $callback-list-info-color;
&-info {
font-size: $font-size-small;
color: $callback-list-info-color;
> span {
display: inline-block;
margin-right: 1.6em;
}
> span {
display: inline-block;
margin-right: 1.6em;
}
.icon {
@include icon-vcenter();
font-size: 20px;
padding: .2em;
}
}
.icon {
@include icon-vcenter();
font-size: 20px;
padding: .2em;
}
}
&-name {
margin-right: 1em;
font-size: $callback-list-name-text-size;
color: $callback-list-name-color;
&-name {
margin-right: 1em;
font-size: $callback-list-name-text-size;
color: $callback-list-name-color;
&:hover {
color: $callback-list-name-hover-color;
text-decoration: none;
}
}
&:hover {
color: $callback-list-name-hover-color;
text-decoration: none;
}
}
&-arrow {
color: $callback-list-arrow-color;
position: absolute;
right: .8em;
top: 50%;
> .icon {
font-size: 35px;
transform: translateY(-50%);
}
}
&-arrow {
color: $callback-list-arrow-color;
position: absolute;
right: .8em;
top: 50%;
> .icon {
font-size: 35px;
transform: translateY(-50%);
}
}
}
}

View file

@ -1,6 +1,6 @@
.pagination {
@extend .nav;
@extend .center-block;
margin-top: 1em;
margin-bottom: 1em;

View file

@ -3,6 +3,7 @@
@extend .container;
display: flex;
align-items: center;
column-gap: $footer-spacing;
min-height: $footer-height;
a {
@ -14,22 +15,23 @@
}
}
&-left,
&-right {
@include make-xs-column(5);
}
&-middle {
@include make-xs-column(2);
&-left {
margin-left: $footer-spacing;
}
&-right {
display: flex;
justify-content: right;
margin-right: $footer-spacing;
}
&-left,
&-right {
text-align: right;
flex: 1;
}
// Top button
&-button-top {
@extend .center-block;
@extend .button;
@extend .button-round;
@include button-variant($footer-link-color, white, white);

View file

@ -6,7 +6,7 @@
.navigation {
// General styling (for all viewport widths)
@extend .clearfix;
@include clearfix();
@extend .container;
min-height: $navbar-height;
@ -34,9 +34,9 @@
font-size: 24px;
// Hide for larger view-ports.
@media (min-width: $navbar-breakpoint-min) {
display: none !important;
}
@include media-breakpoint-up(md) {
@include visually-hidden;
}
}
// Menu
@ -47,18 +47,13 @@
> li {
// Inline list for larger viewports.
@media (min-width: $navbar-breakpoint-min) {
@include media-breakpoint-up(md) {
display: inline-block;
a {
display: block;
@include navbar-vertical-align($line-height-computed + ($navbar-link-vertical-spacing * 2));
margin: 4px calc($navbar-link-spacing / 2);
padding: $navbar-link-vertical-spacing 10px $navbar-link-vertical-spacing;
line-height: $line-height-computed;
margin-left: ($navbar-link-spacing / 2);
margin-right: ($navbar-link-spacing / 2);
&:hover {
color: $navbar-link-hover-color;
@ -76,7 +71,7 @@
}
// Only for small viewports.
@media (max-width: $navbar-breakpoint-min) {
@include media-breakpoint-down(md) {
margin: 1em 0;
@ -99,7 +94,8 @@
}
// Always show menu for larger viewport.
@media (min-width: $navbar-breakpoint-min) {
@include media-breakpoint-up(md) {
&-menu.collapse {
display: block;
}
@ -108,7 +104,7 @@
// User Menu
// -------------------
&-user-menu {
@extend .nav, .pull-right;
@extend .nav, .float-end;
margin-top: 10px;
&-login {
@ -123,7 +119,7 @@
display: inline-block;
padding: .3em .8em;
background: $usermenu-button-bg;
border-radius: $border-radius-base;
border-radius: $border-radius;
&:hover {
background: $usermenu-button-hover-bg;
@ -131,11 +127,11 @@
}
&-list {
@extend .dropdown-menu;
@extend .dropdown-menu-right;
@extend .dropdown-menu-end;
vertical-align: middle;
> li > a {
@extend .dropdown-item;
display: flex;
align-items: center;
}

View file

@ -6,7 +6,7 @@
.head-section {
background-color: $brand-color;
background-color: $primary;
background-image: url(#{$image-path}/header-pattern.jpg);
margin-bottom: 60px;
@ -23,7 +23,7 @@
.content-section {
@extend .container;
margin-bottom: $footer-height;
flex: 1 0 auto;
}
@ -33,8 +33,6 @@
.footer-section {
position: absolute;
bottom: 0;
width: 100%;
color: $footer-text-color;
border-top: 1px solid #bcbcbc;

View file

@ -0,0 +1,6 @@
@mixin center-block() {
display: block;
margin-left: auto;
margin-right: auto;
}

View file

@ -3,11 +3,16 @@
@extend .row;
&-main {
@include make-sm-column(8);
@include make-col-ready();
@include media-breakpoint-up(sm) {
@include make-col(8);
}
}
&-reference {
@include make-sm-column(4);
@include make-col-ready();
@include media-breakpoint-up(sm) {
@include make-col(4);
}
}
}

View file

@ -11,10 +11,11 @@
}
.steps {
@extend .row;
display: flex;
justify-content: center;
column-gap: 2rem;
.steps-img {
@extend .center-block;
width: 270px;
height: 220px;
}
@ -32,7 +33,9 @@
.steps-step1,
.steps-step2,
.steps-step3 {
@include make-md-column(4);
display: flex;
flex-flow: column;
align-items: center;
@extend .text-center;
}
}

View file

@ -12,13 +12,6 @@ use App\Controller\ControllerBase,
class AuthController extends ControllerBase
{
public function initialize()
{
// We need event manager here from DI.
$eventManager = $this->di->get('eventsManager');
$this->setEventsManager($eventManager);
}
public function indexAction()
{
$form = new LoginForm();
@ -74,7 +67,7 @@ class AuthController extends ControllerBase
$user->{'set' . $name . 'Id'}($data->getId());
$user->save();
$this->getEventsManager()->fire('user:onOAuthConnected', $user, $data);
$this->eventsManager->fire('user:onOAuthConnected', $user, $data);
$this->flash->message('success', sprintf("OAuth provider <strong>%s</strong> was connected!", $name));
$this->response->redirect('/settings');

View file

@ -25,11 +25,11 @@ class CallbackController extends ControllerBase
{
$paginator = CallbackModel::getPaginationList($this->_user->getId(), $page, 10);
if ($paginator->getPaginate()->current > $paginator->getPaginate()->total_pages) {
if ($paginator->paginate()->current > $paginator->paginate()->last) {
$paginator->setCurrentPage(1);
}
$this->view->page = $paginator->getPaginate();
$this->view->page = $paginator->paginate();
$this->view->pagination_url = '/callback/list/';
}
@ -111,7 +111,7 @@ class CallbackController extends ControllerBase
$paginator = $callback->getRequestPaginator($page, 30);
$this->view->item = $callback;
$this->view->page = $paginator->getPaginate();
$this->view->page = $paginator->paginate();
$this->view->pagination_url = '/callback/show/' . $id . '/';
}
}

View file

@ -10,13 +10,6 @@ use App\Controller\ControllerBase,
class UserController extends ControllerBase
{
public function initialize()
{
// We need event manager here from DI.
$eventManager = $this->di->get('eventsManager');
$this->setEventsManager($eventManager);
}
public function settingsAction()
{
$user = $this->_getAuth()->getUser();
@ -112,10 +105,10 @@ class UserController extends ControllerBase
$paginator = ActivityLog::getPaginationList($user->getId(), $page);
$this->view->page = $paginator->getPaginate();
$this->view->page = $paginator->paginate();
$this->view->pagination_url = '/user/activity/';
}
public function oauthDisconnectAction($provider, $last_unlink_confirmed = false)
{
$user = $this->_getAuth()->getUser();
@ -156,7 +149,7 @@ class UserController extends ControllerBase
$user->{'set' . $provider . 'Id'}(null);
$user->save();
$this->getEventsManager()->fire('user:onOAuthDisconnect', $user, $provider);
$this->eventsManager->fire('user:onOAuthDisconnect', $user, $provider);
$this->flash->message('success', "<p><strong>{$provider}</strong> was disconnected</p>");

View file

@ -15,7 +15,7 @@ class LogController extends \Phalcon\Mvc\Controller
{
$paginator = ActivityLog::getAllPaginationList($page);
$this->view->page = $paginator->getPaginate();
$this->view->page = $paginator->paginate();
$this->view->pagination_url = '/admin/log/';
}
}

View file

@ -20,7 +20,7 @@ class UserController extends \Phalcon\Mvc\Controller
$paginator = User::getPaginationList($page,15);
$this->view->pagination_url = '/admin/user/list/';
$this->view->page = $paginator->getPaginate();
$this->view->page = $paginator->paginate();
}
public function newAction()

View file

@ -10,8 +10,7 @@ use App\Model\Data\User;
/**
* Phalcon Form
*/
use Httpcb\Form as FormBase,
Phalcon\Forms\Element as FormElement;
use Httpcb\Form as FormBase;
/**
* Element types

View file

@ -8,10 +8,9 @@ namespace App\Form;
use App\Model\Data\User as UserModel;
/**
* Phalcon Form
* Form
*/
use Phalcon\Forms\Form as FormBase,
Phalcon\Forms\Element as FormElement;
use Httpcb\Form as FormBase;
/**
* Element types
@ -56,13 +55,16 @@ class UserSettings extends FormBase
// Id
if ($entity && $entity->getId()) {
$id = new Text('id', array(
'class' => 'form-control',
'readonly' => '',
));
$id = new Text('id', array(
'class' => 'form-control',
'readonly' => '',
'disabled' => 'disabled',
));
$id->addValidator(new IdenticalValidator([
'accepted' => $entity->getId(),
'allowEmpty' => true
]));
$id->setLabel('ID');
@ -114,10 +116,12 @@ class UserSettings extends FormBase
'class' => 'form-control',
'placeholder' => 'Email',
'readonly' => '',
'disabled' => 'disabled',
));
$email->addValidator(new IdenticalValidator([
'accepted' => $entity->getEmail(),
'allowEmpty' => true
]));
} else {
$email = new Text('email', array(
@ -215,63 +219,4 @@ class UserSettings extends FormBase
'with' => 'passwordNew',
]));
}
public function renderDecorated($name, $opt = [])
{
$options = [
'label-class' => 'control-label',
'class' => 'col-sm-10',
'message' => ''
];
$ele = $this->get($name);
if (isset($opt['label-length'])) {
$length = (int) $opt['label-length'];
} else {
$length = 2;
}
$options['label-class'] .= ' col-sm-' . $length;
if (isset($opt['length'])) {
$len = $opt['length'];
if ($len === 'full') {
$options['class'] = '';
} else {
$options['class'] = 'col-sm-' . $opt['length'];
}
}
if ($ele->hasMessages()) {
$options['class'] .= ' has-error';
$options['message'] = $ele->getMessages()->current();
}
return $this->_render($ele, $options);
}
protected function _render(FormElement $ele, $opt)
{
$xhtml = '';
if (strlen($ele->getLabel()) > 0) {
$xhtml .= sprintf(
'<label class="%s" for="%s">%s</label>',
$opt['label-class'], $ele->getName(), $ele->getLabel());
}
$xhtml .= '<div class="' . $opt['class'] . '">'
. $ele->render();
if (strlen($opt['message']) > 0) {
$xhtml .= '<span class="help-block">' . $opt['message'] . '</span>';
}
$xhtml .= '</div>';
return $xhtml;
}
}

View file

@ -3,6 +3,7 @@
namespace Httpcb;
use Phalcon\Config,
Phalcon\Acl\Enum,
Phalcon\Acl\Role,
Phalcon\Acl\Adapter\Memory as Adapter;
@ -21,7 +22,7 @@ class Acl
$this->_adapter = new Adapter();
// Deny access to everything by default.
$this->_adapter->setDefaultAction(\Phalcon\Acl::DENY);
$this->_adapter->setDefaultAction(Enum::DENY);
$this->fromConfig($config);
}
@ -46,7 +47,7 @@ class Acl
$resource = $wildcard;
}
}
return $this->_adapter->isAllowed($role, $resource, 'All') == \Phalcon\Acl::ALLOW;
return $this->_adapter->isAllowed($role, $resource, 'All') == Enum::ALLOW;
}
/**
@ -55,7 +56,7 @@ class Acl
*/
public function hasResource($resource)
{
return $this->_adapter->isResource($resource);
return $this->_adapter->isComponent($resource);
}
public function fromConfig(Config $config)
@ -84,7 +85,7 @@ class Acl
}
foreach($resources as $resource) {
$this->_adapter->addResource($resource, 'All');
$this->_adapter->addComponent($resource, 'All');
}
}
@ -98,9 +99,12 @@ class Acl
}
foreach($zones as $zone) {
$resources = (array) $config->zones->get($zone);
$resources = $config->zones->get($zone);
if (!($resources instanceof Config)) {
$resources = new Config([ $resources ]);
}
foreach($resources as $resource) {
$this->_adapter->allow($name, $resource, 'All');
$this->_adapter->allow($name, $resource, 'All');
}
}
}

View file

@ -5,9 +5,9 @@ namespace Httpcb;
use App\Model\Data\User,
Httpcb\OAuth\UserData\UserDataInterface,
Httpcb\Auth\Result,
Phalcon\Mvc\User\Component;
Phalcon\Di\Injectable;
class Auth extends Component
class Auth extends Injectable
{
const SESSION_KEY = 'auth';

View file

@ -4,7 +4,7 @@ namespace Httpcb;
use Phalcon\Di\FactoryDefault as DiDefault;
use Phalcon\Di\Injectable;
use Phalcon\DiInterface;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\Application;
class Bootstrap extends Injectable
@ -54,12 +54,16 @@ class Bootstrap extends Injectable
/**
* Runs the application.
*
* @return string
*/
public function run()
public function run($uri)
{
$this->_app->setDI($this->getDI());
return $this->_app->handle()->getContent();
try {
$response = $this->_app->handle($uri);
$response->send();
} catch(\Exception $ex) {
echo $ex->getMessage();
}
}
}

View file

@ -3,14 +3,14 @@
namespace Httpcb;
use Phalcon\Forms\Form as FormBase,
Phalcon\Forms\Element as FormElement;
Phalcon\Forms\Element\AbstractElement;
class Form extends FormBase
{
public function renderDecorated($name, $opt = [])
{
$options = [
'label-class' => 'control-label',
'label-class' => 'col-form-label text-end',
'class' => [ 'col-sm-10' ],
'message' => ''
];
@ -45,7 +45,7 @@ class Form extends FormBase
return $this->_render($ele, $options);
}
protected function _render(FormElement $ele, $opt)
protected function _render(AbstractElement $ele, $opt)
{
$xhtml = '';

View file

@ -57,11 +57,11 @@ class RandomId extends Behavior implements BehaviorInterface
*/
public function generateId(\Phalcon\Mvc\ModelInterface $model)
{
$field = $this->_options['field'];
$len = $this->_options['length'];
$field = $this->options['field'];
$len = $this->options['length'];
if (isset($this->_options['expression'])) {
$expr = 'AND ' . $this->_options['expression'];
if (isset($this->options['expression'])) {
$expr = 'AND ' . $this->options['expression'];
} else {
$expr = '';
}

View file

@ -2,23 +2,21 @@
namespace Httpcb;
use Phalcon\DiInterface,
Phalcon\Di\FactoryDefault as DiDefault,
use Phalcon\Di\FactoryDefault as DiDefault,
Phalcon\Config\Adapter\Yaml as Config,
Phalcon\Mvc\View,
Phalcon\Mvc\View\Simple as SimpleView,
Phalcon\Assets\Manager as AssetsManager,
Phalcon\Mvc\Url as UrlResolver,
Phalcon\Url as UrlResolver,
Phalcon\Mvc\View\Engine\Volt as VoltEngine,
Phalcon\Flash\Direct as FlashDirect,
Phalcon\Mvc\Model\Metadata\Memory as MemoryMetaData,
Phalcon\Mvc\Model\MetaData\Apc as ApcMetaData,
Phalcon\Mvc\ViewBaseInterface,
Phalcon\Cache\Frontend\Data as FrontendDataCache,
Phalcon\Cache\Backend\Apc as BackendApcCache,
Phalcon\Translate\Adapter\NativeArray as TranslateAdapter,
Phalcon\Logger,
Phalcon\Logger\Adapter\File as FileLogAdapter,
Phalcon\Session\Adapter\Files as SessionAdapter,
Phalcon\Mvc\Router;
use Httpcb\Auth,
@ -155,7 +153,7 @@ class Services extends DiDefault
$eventsManager->attach('db', function ($event, $connection) use ($logger) {
if ($event->getType() == 'beforeQuery') {
$logger->log($connection->getRealSQLStatement(), Logger::INFO);
$logger->info($connection->getRealSQLStatement());
}
});
@ -190,25 +188,23 @@ class Services extends DiDefault
protected function _initSession()
{
$config = $this->get('config');
$session = new \Phalcon\Session\Manager();
if (isset($config->session)) {
$data = $config->session->toArray();
$adapter = isset($data['adapter']) ? $data['adapter'] : 'Files';
$adapter_name = isset($data['adapter']) ? $data['adapter'] : 'Stream';
$options = $data['options'];
// For "Files": Set session path if defined.
if ($adapter === 'Files' && isset($options['path'])) {
session_save_path($config->application->path);
}
$class = 'Phalcon\Session\Adapter\\' . $adapter;
$session = new $class($options);
$class = 'Phalcon\Session\Adapter\\' . $adapter_name;
$adapter = new $class($options);
}
// Default to File storage
// Default to Stream
else {
$session = new \Phalcon\Session\Adapter\Files();
$adapter = new \Phalcon\Session\Adapter\Stream();
}
$session->setAdapter($adapter);
// Start session.
$session->start();
return $session;
@ -228,23 +224,23 @@ class Services extends DiDefault
$view->setPartialsDir('_partials/');
$view->registerEngines(array(
'.volt' => function ($view, $di) use ($config) {
'.volt' => function (ViewBaseInterface $view) use ($config) {
$volt = new VoltEngine($view, $di);
$volt = new VoltEngine($view, $this);
$volt->setOptions(array(
'compiledPath' => $config->application->viewCacheDir,
'compiledSeparator' => '_',
'compileAlways' => true,
'path' => $config->application->viewCacheDir,
'separator' => '_',
'always' => true,
));
// Register view helpers
$compiler = $volt->getCompiler();
$compiler->addExtension(new ViewHelperVoltExtension($di));
$compiler->addExtension(new ViewHelperVoltExtension($this));
return $volt;
},
'.phtml' => 'Phalcon\Mvc\View\Engine\Php'
'.phtml' => \Phalcon\Mvc\View\Engine\Php::class
));
// Set default main layout.
@ -347,9 +343,7 @@ class Services extends DiDefault
protected function _initAuth()
{
$auth = new Auth($this->get('config'));
$auth->setEventsManager($this->get('eventsManager'));
return $auth;
return new Auth($this->get('config'));
}
protected function _initAcl()
@ -359,8 +353,10 @@ class Services extends DiDefault
protected function _initSharedLogger()
{
$path = $this->get('config')->application->logDir;
return new FileLogAdapter($path . "app.txt");
$path = $this->get('config')->application->logDir;
return new \Phalcon\Logger('default', [
'main' => new \Phalcon\Logger\Adapter\Stream($path . 'app.txt')
]);
}
protected function _initTemplate()
@ -370,17 +366,17 @@ class Services extends DiDefault
$view = new SimpleView();
$view->setViewsDir($config->application->templateDir);
$view->registerEngines([
'.volt' => function ($view, $di) use ($config) {
$volt = new VoltEngine($view, $di);
'.volt' => function (ViewBaseInterface $view) use ($config) {
$volt = new VoltEngine($view, $this);
$volt->setOptions(array(
'compiledPath' => $config->application->viewCacheDir,
'compiledSeparator' => '_',
'path' => $config->application->viewCacheDir,
'separator' => '_',
));
return $volt;
},
'.phtml' => 'Phalcon\Mvc\View\Engine\Php'
'.phtml' => \Phalcon\Mvc\View\Engine\Php::class,
]);
return $view;
}

View file

@ -3,7 +3,7 @@
namespace Httpcb\Validation\Validator;
use Phalcon\Validation\Message;
use Phalcon\Validation\Validator as BaseValidator;
use Phalcon\Validation\AbstractValidator;
/**
* The same as the default Alpha validator shipped with phalcon.
@ -12,16 +12,16 @@ use Phalcon\Validation\Validator as BaseValidator;
*
* @package Validation\Validator
*/
class Alpha extends BaseValidator
class Alpha extends AbstractValidator
{
/**
* Executes the validation
*
* @param mixed $validation
* @param string $attribute
* @param string $field
* @return bool
*/
public function validate(\Phalcon\Validation $validation, $attribute)
public function validate(\Phalcon\Validation $validation, $field) : bool
{
$allowSpace = $this->getOption('allowSpace', false);
@ -30,13 +30,13 @@ class Alpha extends BaseValidator
$charlist .= '[:space:]';
}
$value = $validation->getValue($attribute);
$value = $validation->getValue($field);
if (preg_match("/[^{$charlist}]/imu", $value)) {
$label = $this->getOption('label');
if (empty($label)) {
$label = $validation->getLabel($attribute);
$label = $validation->getLabel($field);
}
$message = $this->getOption('message');
@ -48,12 +48,12 @@ class Alpha extends BaseValidator
$code = $this->getOption("code");
if (is_array($code)) {
$code = $code[$attribute];
$code = $code[$field];
}
$message = str_replace(array_keys($replace), $replace, $message);
$msg = new Message($message, $attribute, "Alpha", $code);
$msg = new Message($message, $field, "Alpha", $code);
$validation->appendMessage($msg);
return false;

View file

@ -2,7 +2,7 @@
namespace Httpcb\ViewHelper;
use Phalcon\DiInterface;
use Phalcon\Di\DiInterface;
use Phalcon\Di\InjectionAwareInterface;
abstract class AbstractHelper implements InjectionAwareInterface
@ -12,19 +12,19 @@ abstract class AbstractHelper implements InjectionAwareInterface
/**
* Sets the dependency injector
*
* @param mixed $dependencyInjector
* @param DiInterface $container
*/
public function setDI(DiInterface $dependencyInjector)
public function setDI(DiInterface $container) : void
{
$this->_di = $dependencyInjector;
$this->_di = $container;
}
/**
* Returns the internal dependency injector
*
* @return \Phalcon\DiInterface
* @return DiInterface
*/
public function getDI()
public function getDI() : DiInterface
{
return $this->_di;
}

View file

@ -2,7 +2,7 @@
namespace Httpcb\ViewHelper;
use Phalcon\DiInterface,
use Phalcon\Di\DiInterface,
Phalcon\Di\InjectionAwareInterface;
class Service implements InjectionAwareInterface
@ -14,19 +14,19 @@ class Service implements InjectionAwareInterface
/**
* Sets the dependency injector
*
* @param mixed $dependencyInjector
* @param DiInterface $container
*/
public function setDI(DiInterface $dependencyInjector)
public function setDI(DiInterface $container) : void
{
$this->_di = $dependencyInjector;
$this->_di = $container;
}
/**
* Returns the internal dependency injector
*
* @return \Phalcon\DiInterface
* @return DiInterface
*/
public function getDI()
public function getDI() : DiInterface
{
return $this->_di;
}

View file

@ -2,7 +2,7 @@
namespace Httpcb\ViewHelper\Volt;
use Phalcon\DiInterface,
use Phalcon\Di\DiInterface,
Phalcon\Di\InjectionAwareInterface;
class Extension implements InjectionAwareInterface
@ -38,19 +38,19 @@ class Extension implements InjectionAwareInterface
/**
* Sets the dependency injector
*
* @param mixed $dependencyInjector
* @param DiInterface $container
*/
public function setDI(DiInterface $dependencyInjector)
public function setDI(DiInterface $container) : void
{
$this->_di = $dependencyInjector;
$this->_di = $container;
}
/**
* Returns the internal dependency injector
*
* @return \Phalcon\DiInterface
* @return DiInterface
*/
public function getDI()
public function getDI() : DiInterface
{
return $this->_di;
}

View file

@ -2,14 +2,14 @@
namespace App\Listener;
use Phalcon\Events\Event,
use Phalcon\Di\Injectable,
Phalcon\Events\Event,
Phalcon\Mvc\Dispatcher,
Phalcon\Mvc\User\Plugin,
Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
use Httpcb\Acl;
class AccessListener extends Plugin
class AccessListener extends Injectable
{
protected $_ignored_resources = [
'index',

View file

@ -2,20 +2,15 @@
namespace App\Listener;
use Phalcon\Mvc\User\Plugin,
use Phalcon\Di\Injectable,
Phalcon\Events\Event,
App\Model\Data\User,
App\Model\Data\ActivityLog as ActivityLogger,
Httpcb\OAuth\UserData\UserDataInterface as OAuthUserDataInterface,
Httpcb\Auth;
class ActivityLog extends Plugin
class ActivityLog extends Injectable
{
/**
* @var ActivityLogger
*/
protected $_table = null;
/**
* On login event.
*
@ -74,20 +69,10 @@ class ActivityLog extends Plugin
{
$ip = (new \Phalcon\Http\Request())->getClientAddress();
$data = [
return (new ActivityLogger())->assign([
'user_id' => $user->getId(),
'ip' => $ip,
'message' => $message
];
return $this->_getLogger()->create($data);
}
protected function _getLogger()
{
if ($this->_table === null) {
$this->_table = new ActivityLogger();
}
return $this->_table;
])->create();
}
}

View file

@ -4,7 +4,7 @@ namespace App\Listener;
use Exception,
Phalcon\Events\Event,
Phalcon\Mvc\User\Plugin,
Phalcon\Di\Injectable,
Phalcon\Mvc\Dispatcher,
Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
@ -14,7 +14,7 @@ use Exception,
* Plugin for forwarding user to 404 (not found) page
* if a request could not be dispatched.
*/
class DispatchListener extends Plugin
class DispatchListener extends Injectable
{
protected $_route_notfound = array(
'controller' => 'error',

View file

@ -18,7 +18,7 @@ class Base extends Model
* @param boolean $allFields
* @return bool
*/
public function hasChanged($fieldName = null, $allFields = false)
public function hasChanged($fieldName = null, bool $allFields = false) : bool
{
return $this->hasSnapshotData() === false
|| parent::hasChanged($fieldName, $allFields);

View file

@ -216,6 +216,9 @@ class Callback extends Model
*/
public function initialize()
{
// Set table name mapped in the model.
$this->setSource('callback');
$this->useDynamicUpdate(true);
$this->hasMany('id', RequestMeta::class, 'callbackid', array('foreignKey' => true, 'alias' => 'Requests'));
@ -227,16 +230,6 @@ class Callback extends Model
)));
}
/**
* Returns table name mapped in the model.
*
* @return string
*/
public function getSource()
{
return 'callback';
}
public function getRequestPaginator($page = 1, $limit = 30)
{
return RequestMeta::getPaginator($this, $page, $limit);

View file

@ -3,7 +3,7 @@
namespace App\Module;
use Phalcon\Loader,
Phalcon\DiInterface,
Phalcon\Di\DiInterface,
Phalcon\Mvc\Dispatcher,
Phalcon\Mvc\ModuleDefinitionInterface;

View file

@ -10,12 +10,9 @@
{% for type, messages in flash.getMessages() %}
{% for message in messages %}
<div class="alert alert-{{ types[type] }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{ type|capitalize }}</strong>
<p>
{{ message }}
</p>
<h5 class="alert-heading">{{ type|capitalize }}</h5>
<p class="mb-0">{{ message }}</p>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
</div>
{% endfor%}
{% endfor %}

View file

@ -1,7 +1,7 @@
<footer class="footer">
<div class="footer-left">
Copyright &copy; 2017 - 2018
Copyright &copy; 2017 - 2022
<a target="_blank" href="http://www.shufflingpixels.com">
Shufflingpixels
</a>

View file

@ -9,15 +9,15 @@
{% if auth.hasIdentity() %}
<div class="navigation-user-menu-dropdown">
<a id="user-dropdown-button" class="navigation-user-menu-dropdown-button"
data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
data-bs-toggle="dropdown" role="button" aria-expanded="false">
{{ icon('solid/user') }} <strong>{{ auth.getUser().username }}</strong>
</a>
<ul aria-labelledby="user-dropdown" class="navigation-user-menu-dropdown-list">
<ul class="dropdown-menu navigation-user-menu-dropdown-list">
<li>{{ link_to(['for': 'user-settings'], '<i class="icon fas fa-cog"></i> Settings') }}</li>
<li>{{ link_to('/user/activity', '<i class="icon fas fa-list-alt"></i> Activity') }}</li>
<li role="separator" class="divider"></li>
<li><hr class="dropdown-divider"></li>
<li>{{ link_to(['for': 'logout'], '<i class="icon far fa-times-circle"></i> Log out') }}</li>
</ul>
</div>

View file

@ -9,19 +9,19 @@
{% set pagination_slider = 3 %}
{% if (page.total_pages > 1) %}
{% if (page.last > 1) %}
<ul class="pagination">
{% if page.current !== page.before %}
{% if page.current !== page.previous %}
<li>
<a href="{{ pagination_url ~ page.before }}">
<a href="{{ pagination_url ~ page.previous }}">
{{ icon('solid/arrow-left') }} Previous
</a>
</li>
{% endif %}
{% if page.total_pages > pagination_slider and page.current > (pagination_slider + 1) %}
{% if page.last > pagination_slider and page.current > (pagination_slider + 1) %}
<li>
<a href="{{ pagination_url ~ 1 }}">1</a>
</li>
@ -30,7 +30,7 @@
</li>
{% endif %}
{% for n in max(page.current - pagination_slider, 1)..min(page.current + pagination_slider, page.total_pages) %}
{% for n in max(page.current - pagination_slider, 1)..min(page.current + pagination_slider, page.last) %}
{% if (n == page.current) %}
<li class="active">
{% else %}
@ -40,12 +40,12 @@
</li>
{% endfor %}
{% if page.total_pages > pagination_slider and page.current < page.total_pages - pagination_slider %}
{% if page.last > pagination_slider and page.current < page.last - pagination_slider %}
<li class="middle">
...
</li>
<li>
<a href="{{ pagination_url ~ page.total_pages }}">{{ page.total_pages }}</a>
<a href="{{ pagination_url ~ page.last }}">{{ page.last }}</a>
</li>
{% endif %}

View file

@ -2,9 +2,9 @@
<div class="section">
<div class="clearfix">
<h2 class="pull-left">Callbacks</h2>
<h2 class="float-start">Callbacks</h2>
<div class="pull-right">
<div class="float-end">
<a class="button button-large button-primary" href="{{ url('/callback/new') }}">
{{ icon('solid/plus') }} New
</a>

View file

@ -3,37 +3,17 @@
<h2>Create callback</h2>
<!--
<form class="form-horizontal" method="post">
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" id="name">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="button button-brand" value="Create">
</div>
</div>
</form>
-->
<form class="form-horizontal" method="post">
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name</label>
<div class="row mb-3">
<label class="col-sm-2 col-form-label text-end" for="name">Name</label>
<div class="col-sm-10">
{{ form.render('Name') }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="row mb-3">
<div class="offset-sm-2 col-sm-10">
{{ form.render('Create') }}
</div>
</div>
</form>
</div>

View file

@ -1,18 +1,18 @@
<div class="section">
<div class="clearfix">
<h3 class="pull-left">{{ item.name|e }}</h3>
<h5 class="pull-right"><strong>Created at:</strong> {{ item.created_at }}</h5>
<h4 class="float-start">{{ item.name|e }}</h4>
<h6 class="float-end"><strong>Created at:</strong> {{ item.created_at }}</h6>
</div>
<div class="panel-group request-list" id="request-list" role="tablist" aria-multiselectable="true">
<div class="panel-group request-list" id="request-list">
{% for index, req in page.items %}
<div class="panel request-list-item">
<a id="request-item-head-{{ index }}" class="request-list-item-header collapsed"
href="#request-item-body-{{ index }}" aria-controls="request-item-body-{{ index }}"
data-parent="#request-list" data-toggle="collapse" aria-expanded="true" >
href="#request-item-body-{{ index }}" role="button" aria-controls="request-item-body-{{ index }}"
data-bs-toggle="collapse" aria-expanded="true" >
<div class="request-list-item-header-row">
@ -46,20 +46,19 @@
</div>
</a>
<div id="request-item-body-{{ index }}" class="collapse"
role="tabpanel" aria-labelledby="request-item-head-{{ index }}">
<div id="request-item-body-{{ index }}" class="collapse" data-bs-parent="#request-list">
<div class="request-list-item-detail">
{% if req.getUriQuery()|length > 0 %}
<button class="request-list-item-detail-button" type="button"
data-toggle="collapse" data-target="#request-list-item-detail-query-{{ index }}"
<button class="request-list-item-detail-button" type="button" role="button"
data-bs-toggle="collapse" data-bs-target="#request-list-item-detail-query-{{ index }}"
aria-expanded="false" aria-controls="request-list-item-detail-query-{{ index }}">
Query
</button>
<div id="request-list-item-detail-query-{{ index }}" class="collapse in">
<div id="request-list-item-detail-query-{{ index }}" class="collapse show">
<table class="request-list-item-detail-headers">
<thead>
<tr>
@ -81,7 +80,7 @@
{% endif %}
<button class="request-list-item-detail-button" type="button"
data-toggle="collapse" data-target="#request-list-item-detail-headers-{{ index }}"
data-bs-toggle="collapse" data-bs-target="#request-list-item-detail-headers-{{ index }}"
aria-expanded="false" aria-controls="request-list-item-detail-headers-{{ index }}">
Headers
</button>
@ -106,7 +105,7 @@
</div>
<button class="request-list-item-detail-button" type="button"
data-toggle="collapse" data-target="#request-list-item-detail-body-{{ index }}"
data-bs-toggle="collapse" data-bs-target="#request-list-item-detail-body-{{ index }}"
aria-expanded="false" aria-controls="request-list-item-detail-body-{{ index }}">
Body
</button>
@ -118,7 +117,7 @@
<h3>Empty body</h3>
</div>
{% else %}
<pre>{{ req.getBody() }}</pre>
<pre class="code"><code>{{ req.getBody() }}</code></pre>
{% endif %}
</div>
</div>

View file

@ -33,7 +33,7 @@
<p>
So if you want you can send me a <a href="mailto:henrik.hautakoski@gmail.com">email</a>
if you find a bug, request som future or just to let me know that i helped someone with debugging.
if you find a bug, request some feature or just to let me know that i helped someone with debugging.
</p>
</div>
</div>
@ -46,7 +46,7 @@
<div class="phalcon">
<a target="_blank" href="http://phalconphp.com">
<img class="img-responsive" src="/img/phalcon-php.png" />
<img class="img-fluid" src="/img/phalcon-php.png" />
</a>
</div>

View file

@ -11,47 +11,48 @@
<form class="form-horizontal" method="post" action="">
<div class="form-group">
<div class="row mb-3">
{{ form.renderDecorated('username', [ 'length': 7 ]) }}
{{ form.renderDecorated('id', [ 'length': 2, 'label-length' : 1 ]) }}
</div>
<div class="form-group">
<div class="row mb-3">
{{ form.renderDecorated('name') }}
</div>
<div class="form-group">
<div class="row mb-3">
{{ form.renderDecorated('email') }}
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<h4>Password</h4>
<div class="row mb-3">
<div class="col-sm-10 offset-sm-2">
<h5>Password</h5>
</div>
</div>
{% if form.has('passwordCurrent') %}
<div class="form-group">
<div class="row mb-3">
{{ form.renderDecorated('passwordCurrent') }}
</div>
{% endif %}
<div class="form-group">
<div class="row mb-3">
{{ form.renderDecorated('passwordNew') }}
</div>
<div class="form-group">
<div class="row mb-3">
{{ form.renderDecorated('passwordConfirm') }}
</div>
<div class="form-group">
<div class="row mb-3">
<div class="col-sm-offset-2 col-sm-10">
<div class="col-sm-10 offset-sm-2">
<h4>Social sign-in</h4>
<h5>Social sign-in</h5>
<hr />
<div class="row">
{% for name,info in social_links %}
<div class="col-sm-2 text-center">
{% set class = info['class'] | default(false) %}
@ -63,16 +64,17 @@
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="row mb-3">
<div class="col-sm-10 offset-sm-2">
<hr />
{{ form.render('Save') }}
<button class="button button-danger pull-right" type="button" data-toggle="modal" data-target="#deleteModal">
<button class="button button-danger float-end" type="button" data-bs-toggle="modal" data-bs-target="#deleteModal">
Delete Account
</button>
</div>
@ -81,14 +83,12 @@
</form>
</div>
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title pull-left" id="deleteModalLabel">Delete account</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title float-start" id="deleteModalLabel">Delete account</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="/user/delete">
@ -105,12 +105,10 @@
</div>
<div class="modal-footer">
<button type="button" class="button button-default" data-dismiss="modal">Close</button>
<button type="button" class="button button-default" data-bs-dismiss="modal">Close</button>
<input type="submit" name="deleteAcc" class="button button-danger" value="Delete account">
</div>
</form>
</div>
</div>
</div>