|
|
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
|
|
|
import '@polymer/paper-toggle-button/paper-toggle-button.js';
|
|
|
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
|
|
|
import {IronA11yKeysBehavior} from '@polymer/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
|
|
|
import '../rhodecode-unsafe-html/rhodecode-unsafe-html.js';
|
|
|
|
|
|
export class RhodecodeToast extends mixinBehaviors([IronA11yKeysBehavior], PolymerElement) {
|
|
|
|
|
|
static get is() {
|
|
|
return 'rhodecode-toast';
|
|
|
}
|
|
|
|
|
|
static get template(){
|
|
|
return html`
|
|
|
<style include="shared-styles">
|
|
|
/* inset border for buttons - does not work in ie */
|
|
|
/* rounded borders */
|
|
|
/* rounded borders - bottom only */
|
|
|
/* rounded borders - top only */
|
|
|
/* text shadow */
|
|
|
/* centers text in a circle - input diameter of circle and color */
|
|
|
/* pill version of the circle */
|
|
|
.absolute-center {
|
|
|
margin: auto;
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
bottom: 0;
|
|
|
right: 0;
|
|
|
}
|
|
|
|
|
|
.top-left-rounded-corner {
|
|
|
-webkit-border-top-left-radius: 2px;
|
|
|
-khtml-border-radius-topleft: 2px;
|
|
|
border-top-left-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.top-right-rounded-corner {
|
|
|
-webkit-border-top-right-radius: 2px;
|
|
|
-khtml-border-radius-topright: 2px;
|
|
|
border-top-right-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.bottom-left-rounded-corner {
|
|
|
-webkit-border-bottom-left-radius: 2px;
|
|
|
-khtml-border-radius-bottomleft: 2px;
|
|
|
border-bottom-left-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.bottom-right-rounded-corner {
|
|
|
-webkit-border-bottom-right-radius: 2px;
|
|
|
-khtml-border-radius-bottomright: 2px;
|
|
|
border-bottom-right-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.top-left-rounded-corner-mid {
|
|
|
-webkit-border-top-left-radius: 2px;
|
|
|
-khtml-border-radius-topleft: 2px;
|
|
|
border-top-left-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.top-right-rounded-corner-mid {
|
|
|
-webkit-border-top-right-radius: 2px;
|
|
|
-khtml-border-radius-topright: 2px;
|
|
|
border-top-right-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.bottom-left-rounded-corner-mid {
|
|
|
-webkit-border-bottom-left-radius: 2px;
|
|
|
-khtml-border-radius-bottomleft: 2px;
|
|
|
border-bottom-left-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.bottom-right-rounded-corner-mid {
|
|
|
-webkit-border-bottom-right-radius: 2px;
|
|
|
-khtml-border-radius-bottomright: 2px;
|
|
|
border-bottom-right-radius: 2px;
|
|
|
}
|
|
|
|
|
|
.alert {
|
|
|
margin: 10px 0;
|
|
|
}
|
|
|
|
|
|
.toast-close {
|
|
|
margin: 0;
|
|
|
float: right;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.toast-message-holder {
|
|
|
background: rgba(255, 255, 255, 0.25);
|
|
|
}
|
|
|
|
|
|
.toast-message-holder.fixed {
|
|
|
position: fixed;
|
|
|
padding: 10px 0;
|
|
|
margin-left: 10px;
|
|
|
margin-right: 10px;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
z-index: 100;
|
|
|
}
|
|
|
</style>
|
|
|
|
|
|
<template is="dom-if" if="[[hasToasts]]">
|
|
|
<div class$="container toast-message-holder [[conditionalClass(isFixed)]]">
|
|
|
<template is="dom-repeat" items="[[toasts]]">
|
|
|
<div class$="alert alert-[[item.level]]">
|
|
|
<div on-click="dismissNotification" class="toast-close" index-pos="[[index]]">
|
|
|
<span>[[_gettext('Close')]]</span>
|
|
|
</div>
|
|
|
<rhodecode-unsafe-html text="[[item.message]]"></rhodecode-unsafe-html>
|
|
|
</div>
|
|
|
</template>
|
|
|
</div>
|
|
|
</template>
|
|
|
`
|
|
|
}
|
|
|
|
|
|
static get properties() {
|
|
|
return {
|
|
|
toasts: {
|
|
|
type: Array,
|
|
|
value() {
|
|
|
return []
|
|
|
}
|
|
|
},
|
|
|
isFixed: {
|
|
|
type: Boolean,
|
|
|
value: false
|
|
|
},
|
|
|
hasToasts: {
|
|
|
type: Boolean,
|
|
|
computed: '_computeHasToasts(toasts.*)'
|
|
|
},
|
|
|
keyEventTarget: {
|
|
|
type: Object,
|
|
|
value() {
|
|
|
return document.body;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
get keyBindings() {
|
|
|
return {
|
|
|
'esc:keyup': '_hideOnEsc'
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static get observers() {
|
|
|
return [
|
|
|
'_changedToasts(toasts.splices)'
|
|
|
]
|
|
|
}
|
|
|
|
|
|
_hideOnEsc(event) {
|
|
|
return this.dismissNotifications();
|
|
|
}
|
|
|
|
|
|
_computeHasToasts() {
|
|
|
return this.toasts.length > 0;
|
|
|
}
|
|
|
|
|
|
_debouncedCalc() {
|
|
|
// calculate once in a while
|
|
|
this.debounce('debouncedCalc', this.toastInWindow, 25);
|
|
|
}
|
|
|
|
|
|
conditionalClass() {
|
|
|
return this.isFixed ? 'fixed' : '';
|
|
|
}
|
|
|
|
|
|
toastInWindow() {
|
|
|
if (!this._headerNode) {
|
|
|
return true
|
|
|
}
|
|
|
var headerHeight = this._headerNode.offsetHeight;
|
|
|
var scrollPosition = window.scrollY;
|
|
|
|
|
|
if (this.isFixed) {
|
|
|
this.isFixed = 1 <= scrollPosition;
|
|
|
}
|
|
|
else {
|
|
|
this.isFixed = headerHeight <= scrollPosition;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
connectedCallback() {
|
|
|
super.connectedCallback();
|
|
|
this._headerNode = document.querySelector('.header', document);
|
|
|
this.listen(window, 'scroll', '_debouncedCalc');
|
|
|
this.listen(window, 'resize', '_debouncedCalc');
|
|
|
this._debouncedCalc();
|
|
|
}
|
|
|
|
|
|
_changedToasts(newValue, oldValue) {
|
|
|
$.Topic('/favicon/update').publish({count: this.toasts.length});
|
|
|
}
|
|
|
|
|
|
dismissNotification(e) {
|
|
|
$.Topic('/favicon/update').publish({count: this.toasts.length - 1});
|
|
|
var idx = e.target.parentNode.indexPos
|
|
|
this.splice('toasts', idx, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
dismissNotifications() {
|
|
|
$.Topic('/favicon/update').publish({count: 0});
|
|
|
this.splice('toasts', 0);
|
|
|
}
|
|
|
|
|
|
handleNotification(data) {
|
|
|
if (!templateContext.rhodecode_user.notification_status && !data.message.force) {
|
|
|
// do not act if notifications are disabled
|
|
|
return
|
|
|
}
|
|
|
this.push('toasts', {
|
|
|
level: data.message.level,
|
|
|
message: data.message.message
|
|
|
});
|
|
|
}
|
|
|
|
|
|
_gettext(x){
|
|
|
return _gettext(x)
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
customElements.define(RhodecodeToast.is, RhodecodeToast);
|
|
|
|