Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
cf709962d9
54 changed files with 3598 additions and 2843 deletions
7
.babelrc
7
.babelrc
|
|
@ -4,10 +4,9 @@
|
|||
"env",
|
||||
{
|
||||
"targets": {
|
||||
"browsers": [
|
||||
"last 2 versions"
|
||||
]
|
||||
}
|
||||
"esmodules": true
|
||||
},
|
||||
"exclude": ["transform-es2015-classes"]
|
||||
}
|
||||
]
|
||||
],
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ module.exports = function(grunt) {
|
|||
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-terser');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-webpack');
|
||||
grunt.registerTask('default', ['less:production', 'less:components', 'copy', 'webpack', 'concat:dist', 'uglify:dist']);
|
||||
grunt.registerTask('default', ['less:production', 'less:components', 'copy', 'webpack', 'concat:dist', 'terser:dist']);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -667,13 +667,14 @@ search.location = %(here)s/data/index
|
|||
channelstream.enabled = true
|
||||
|
||||
; server address for channelstream server on the backend
|
||||
channelstream.server = channelstream:9800
|
||||
channelstream.server = channelstream:8000
|
||||
|
||||
; location of the channelstream server from outside world
|
||||
; use ws:// for http or wss:// for https. This address needs to be handled
|
||||
; by external HTTP server such as Nginx or Apache
|
||||
; see Nginx/Apache configuration examples in our docs
|
||||
channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
|
||||
; For development, comment this out to use auto-generated proxy URL
|
||||
;channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
|
||||
channelstream.secret = ENV_GENERATED
|
||||
channelstream.history.location = /var/opt/rhodecode_data/channelstream_history
|
||||
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ search.location = %(here)s/data/index
|
|||
channelstream.enabled = true
|
||||
|
||||
; server address for channelstream server on the backend
|
||||
channelstream.server = channelstream:9800
|
||||
channelstream.server = channelstream:8000
|
||||
|
||||
; location of the channelstream server from outside world
|
||||
; use ws:// for http or wss:// for https. This address needs to be handled
|
||||
|
|
|
|||
|
|
@ -52,10 +52,12 @@ Supported Databases
|
|||
Supported Browsers
|
||||
------------------
|
||||
|
||||
* Chrome
|
||||
* Safari
|
||||
* Firefox
|
||||
* Internet Explorer 10 & 11
|
||||
* Chrome 67+
|
||||
* Firefox 63+
|
||||
* Safari 11.1+
|
||||
* Edge 79+
|
||||
|
||||
Note: Internet Explorer is no longer supported
|
||||
|
||||
System Requirements
|
||||
-------------------
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
Release Date
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- 2025-11-05
|
||||
- 2025-11-06
|
||||
|
||||
New Features
|
||||
^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
"src": [
|
||||
"<%= dirs.js.node_modules %>/jquery/dist/jquery.min.js",
|
||||
"<%= dirs.js.node_modules %>/mousetrap/mousetrap.min.js",
|
||||
"<%= dirs.js.node_modules %>/moment/min/moment.min.js",
|
||||
"<%= dirs.js.node_modules %>/luxon/build/global/luxon.min.js",
|
||||
"<%= dirs.js.node_modules %>/clipboard/dist/clipboard.min.js",
|
||||
"<%= dirs.js.node_modules %>/favico.js/favico-0.3.10.min.js",
|
||||
"<%= dirs.js.node_modules %>/dropzone/dist/min/dropzone.min.js",
|
||||
|
|
@ -102,10 +102,23 @@
|
|||
"nonull": true
|
||||
}
|
||||
},
|
||||
"uglify": {
|
||||
"terser": {
|
||||
"dist": {
|
||||
"src": "<%= dirs.js.dest %>/scripts.js",
|
||||
"dest": "<%= dirs.js.dest %>/scripts.min.js"
|
||||
"options": {
|
||||
"compress": {
|
||||
"ecma": 6
|
||||
},
|
||||
"mangle": {
|
||||
"keep_classnames": true,
|
||||
"keep_fnames": false
|
||||
},
|
||||
"output": {
|
||||
"ecma": 6
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
"<%= dirs.js.dest %>/scripts.min.js": "<%= dirs.js.dest %>/scripts.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"less": {
|
||||
|
|
@ -156,7 +169,6 @@
|
|||
"tasks": [
|
||||
"less:development",
|
||||
"less:components",
|
||||
"concat:polymercss",
|
||||
"webpack",
|
||||
"concat:dist"
|
||||
]
|
||||
|
|
@ -169,7 +181,6 @@
|
|||
],
|
||||
"tasks": [
|
||||
"less:components",
|
||||
"concat:polymercss",
|
||||
"webpack",
|
||||
"concat:dist"
|
||||
]
|
||||
|
|
|
|||
4283
package-lock.json
generated
4283
package-lock.json
generated
File diff suppressed because it is too large
Load diff
16
package.json
16
package.json
|
|
@ -21,6 +21,8 @@
|
|||
"@webcomponents/webcomponentsjs": "^2.0.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-syntax-class-properties": "^6.13.0",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"clipboard": "^2.0.1",
|
||||
|
|
@ -35,16 +37,17 @@
|
|||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-jshint": "^0.12.0",
|
||||
"grunt-contrib-less": "^1.1.0",
|
||||
"grunt-contrib-uglify": "^4.0.1",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-terser": "^1.0.0",
|
||||
"grunt-webpack": "^3.1.3",
|
||||
"html-loader": "^0.4.4",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"imports-loader": "^0.7.1",
|
||||
"jquery": "1.11.3",
|
||||
"install": "^0.13.0",
|
||||
"jquery": "^3.7.1",
|
||||
"jshint": "^2.9.1-rc3",
|
||||
"luxon": "^3.7.2",
|
||||
"mark.js": "8.11.1",
|
||||
"moment": "^2.18.1",
|
||||
"mousetrap": "^1.6.1",
|
||||
"polymer-webpack-loader": "^2.0.1",
|
||||
"raw-loader": "1.0.0-beta.0",
|
||||
|
|
@ -54,7 +57,10 @@
|
|||
"ts-loader": "^1.3.3",
|
||||
"waypoints": "4.0.1",
|
||||
"webpack": "4.23.1",
|
||||
"webpack-cli": "3.1.2",
|
||||
"webpack-uglify-js-plugin": "^1.1.9"
|
||||
"webpack-cli": "3.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"lit": "^2.8.0",
|
||||
"regenerator-runtime": "^0.13.9"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
}
|
||||
var stringMatch
|
||||
if (stringMatch = stream.match(/("""|"|')/)) {
|
||||
var tokenize = tokenString.bind(null, stringMatch[0])
|
||||
var tokenize = tokenString.on(null, stringMatch[0])
|
||||
state.tokenize.push(tokenize)
|
||||
return tokenize(stream, state)
|
||||
}
|
||||
|
|
|
|||
2
rhodecode/public/js/src/bootstrap.js
vendored
2
rhodecode/public/js/src/bootstrap.js
vendored
|
|
@ -745,7 +745,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
|
|||
|
||||
if (!isActive || (isActive && e.keyCode == 27)) {
|
||||
if (e.which == 27) $parent.find(toggle).focus()
|
||||
return $this.click()
|
||||
return $this.trigger('click')
|
||||
}
|
||||
|
||||
var $items = $('[role=menu] li:not(.divider):visible a', $parent)
|
||||
|
|
|
|||
|
|
@ -9660,7 +9660,7 @@
|
|||
var wrappedSubmit = form.submit = function () {
|
||||
save();
|
||||
form.submit = realSubmit;
|
||||
form.submit();
|
||||
form.trigger('submit');
|
||||
form.submit = wrappedSubmit;
|
||||
};
|
||||
} catch(e) {}
|
||||
|
|
|
|||
|
|
@ -1,577 +1,446 @@
|
|||
import {Polymer, html} from '@polymer/polymer/polymer-legacy';
|
||||
import '@polymer/iron-ajax/iron-ajax.js';
|
||||
import {LitElement} from 'lit';
|
||||
|
||||
const elemTemplate = html`
|
||||
<iron-ajax
|
||||
id="ajaxConnect"
|
||||
url=""
|
||||
handle-as="json"
|
||||
method="post"
|
||||
content-type="application/json"
|
||||
loading="{{loadingConnect}}"
|
||||
last-response="{{connectLastResponse}}"
|
||||
on-response="_handleConnect"
|
||||
on-error="_handleConnectError"
|
||||
debounce-duration="100"></iron-ajax>
|
||||
/**
|
||||
* Simplified Lit version of channelstream-connection
|
||||
* Replaces iron-ajax with native fetch()
|
||||
*/
|
||||
export class ChannelstreamConnection extends LitElement {
|
||||
static properties = {
|
||||
channels: {type: Array},
|
||||
username: {type: String},
|
||||
connectionId: {type: String},
|
||||
websocket: {type: Object},
|
||||
websocketUrl: {type: String},
|
||||
connectUrl: {type: String},
|
||||
disconnectUrl: {type: String},
|
||||
subscribeUrl: {type: String},
|
||||
unsubscribeUrl: {type: String},
|
||||
messageUrl: {type: String},
|
||||
longPollUrl: {type: String},
|
||||
shouldReconnect: {type: Boolean},
|
||||
heartbeats: {type: Boolean},
|
||||
increaseBounceIv: {type: Number},
|
||||
_currentBounceIv: {type: Number},
|
||||
useWebsocket: {type: Boolean},
|
||||
connected: {type: Boolean},
|
||||
channelsState: {type: Object},
|
||||
userState: {type: Object}
|
||||
};
|
||||
|
||||
<iron-ajax
|
||||
id="ajaxDisconnect"
|
||||
url=""
|
||||
handle-as="json"
|
||||
method="post"
|
||||
content-type="application/json"
|
||||
loading="{{loadingDisconnect}}"
|
||||
last-response="{{_disconnectLastResponse}}"
|
||||
on-response="_handleDisconnect"
|
||||
debounce-duration="100"></iron-ajax>
|
||||
constructor() {
|
||||
super();
|
||||
this.channels = [];
|
||||
this.username = 'Anonymous';
|
||||
this.connectionId = '';
|
||||
this.websocket = null;
|
||||
this.websocketUrl = '';
|
||||
this.connectUrl = '';
|
||||
this.disconnectUrl = '';
|
||||
this.subscribeUrl = '';
|
||||
this.unsubscribeUrl = '';
|
||||
this.messageUrl = '';
|
||||
this.longPollUrl = '';
|
||||
this.shouldReconnect = true;
|
||||
this.heartbeats = true;
|
||||
this.increaseBounceIv = 2000;
|
||||
this._currentBounceIv = 0;
|
||||
this.useWebsocket = true;
|
||||
this.connected = false;
|
||||
this.channelsState = {};
|
||||
this.userState = {};
|
||||
|
||||
<iron-ajax
|
||||
id="ajaxSubscribe"
|
||||
url=""
|
||||
handle-as="json"
|
||||
method="post"
|
||||
content-type="application/json"
|
||||
loading="{{loadingSubscribe}}"
|
||||
last-response="{{subscribeLastResponse}}"
|
||||
on-response="_handleSubscribe"
|
||||
debounce-duration="100"></iron-ajax>
|
||||
// Mutators - simplified to just arrays
|
||||
this.mutators = {
|
||||
connect: [],
|
||||
message: [],
|
||||
subscribe: [],
|
||||
unsubscribe: [],
|
||||
disconnect: []
|
||||
};
|
||||
|
||||
<iron-ajax
|
||||
id="ajaxUnsubscribe"
|
||||
url=""
|
||||
handle-as="json"
|
||||
method="post"
|
||||
content-type="application/json"
|
||||
loading="{{loadingUnsubscribe}}"
|
||||
last-response="{{unsubscribeLastResponse}}"
|
||||
on-response="_handleUnsubscribe"
|
||||
debounce-duration="100"></iron-ajax>
|
||||
this._heartbeatInterval = null;
|
||||
}
|
||||
|
||||
<iron-ajax
|
||||
id="ajaxMessage"
|
||||
url=""
|
||||
handle-as="json"
|
||||
method="post"
|
||||
content-type="application/json"
|
||||
loading="{{loadingMessage}}"
|
||||
last-response="{{messageLastResponse}}"
|
||||
on-response="_handleMessage"
|
||||
on-error="_handleMessageError"
|
||||
debounce-duration="100"></iron-ajax>
|
||||
// No render needed - this component has no template
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
|
||||
<iron-ajax
|
||||
id="ajaxListen"
|
||||
url=""
|
||||
handle-as="text"
|
||||
loading="{{loadingListen}}"
|
||||
last-response="{{listenLastResponse}}"
|
||||
on-request="_handleListenOpen"
|
||||
on-error="_handleListenError"
|
||||
on-response="_handleListenMessageEvent"
|
||||
debounce-duration="100"></iron-ajax>
|
||||
`
|
||||
|
||||
Polymer({
|
||||
is: 'channelstream-connection',
|
||||
|
||||
_template: elemTemplate,
|
||||
|
||||
/**
|
||||
* Fired when `channels` array changes.
|
||||
*
|
||||
* @event channelstream-channels-changed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `connect()` method succeeds.
|
||||
*
|
||||
* @event channelstream-connected
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `connect` fails.
|
||||
*
|
||||
* @event channelstream-connect-error
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `disconnect()` succeeds.
|
||||
*
|
||||
* @event channelstream-disconnected
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `message()` succeeds.
|
||||
*
|
||||
* @event channelstream-message-sent
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `message()` fails.
|
||||
*
|
||||
* @event channelstream-message-error
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `subscribe()` succeeds.
|
||||
*
|
||||
* @event channelstream-subscribed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `subscribe()` fails.
|
||||
*
|
||||
* @event channelstream-subscribe-error
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `unsubscribe()` succeeds.
|
||||
*
|
||||
* @event channelstream-unsubscribed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when `unsubscribe()` fails.
|
||||
*
|
||||
* @event channelstream-unsubscribe-error
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when listening connection receives a message.
|
||||
*
|
||||
* @event channelstream-listen-message
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when listening connection is opened.
|
||||
*
|
||||
* @event channelstream-listen-opened
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when listening connection is closed.
|
||||
*
|
||||
* @event channelstream-listen-closed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fired when listening connection suffers an error.
|
||||
*
|
||||
* @event channelstream-listen-error
|
||||
*/
|
||||
|
||||
properties: {
|
||||
isReady: Boolean,
|
||||
/** List of channels user should be subscribed to. */
|
||||
channels: {
|
||||
type: Array,
|
||||
value: function () {
|
||||
return []
|
||||
},
|
||||
notify: true
|
||||
},
|
||||
/** Username of connecting user. */
|
||||
username: {
|
||||
type: String,
|
||||
value: 'Anonymous',
|
||||
reflectToAttribute: true
|
||||
},
|
||||
/** Connection identifier. */
|
||||
connectionId: {
|
||||
type: String,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
/** Websocket instance. */
|
||||
websocket: {
|
||||
type: Object,
|
||||
value: null
|
||||
},
|
||||
/** Websocket connection url. */
|
||||
websocketUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** URL used in `connect()`. */
|
||||
connectUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** URL used in `disconnect()`. */
|
||||
disconnectUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** URL used in `subscribe()`. */
|
||||
subscribeUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** URL used in `unsubscribe()`. */
|
||||
unsubscribeUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** URL used in `message()`. */
|
||||
messageUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** Long-polling connection url. */
|
||||
longPollUrl: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/** Long-polling connection url. */
|
||||
shouldReconnect: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
/** Should send heartbeats. */
|
||||
heartbeats: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
/** How much should every retry interval increase (in milliseconds) */
|
||||
increaseBounceIv: {
|
||||
type: Number,
|
||||
value: 2000
|
||||
},
|
||||
_currentBounceIv: {
|
||||
type: Number,
|
||||
reflectToAttribute: true,
|
||||
value: 0
|
||||
},
|
||||
/** Should use websockets or long-polling by default */
|
||||
useWebsocket: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true,
|
||||
value: true
|
||||
},
|
||||
connected: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true,
|
||||
value: false
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has('channels')) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-channels-changed', {
|
||||
detail: {value: this.channels}
|
||||
}));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
observers: [
|
||||
'_handleChannelsChange(channels.splices)'
|
||||
],
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
listeners: {
|
||||
'channelstream-connected': 'startListening',
|
||||
'channelstream-connect-error': 'retryConnection',
|
||||
},
|
||||
// Set up self-event listeners (replaces Polymer's 'listeners' property)
|
||||
this.addEventListener('channelstream-connected', this.startListening.bind(this));
|
||||
this.addEventListener('channelstream-connect-error', this.retryConnection.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutators hold functions that you can set locally to change the data
|
||||
* that the client is sending to all endpoints
|
||||
* you can call it like `elem.mutators('connect', yourFunc())`
|
||||
* mutators will be executed in order they were pushed onto arrays
|
||||
*
|
||||
* Helper method for fetch requests
|
||||
*/
|
||||
mutators: {
|
||||
connect: function () {
|
||||
return []
|
||||
}(),
|
||||
message: function () {
|
||||
return []
|
||||
}(),
|
||||
subscribe: function () {
|
||||
return []
|
||||
}(),
|
||||
unsubscribe: function () {
|
||||
return []
|
||||
}(),
|
||||
disconnect: function () {
|
||||
return []
|
||||
}()
|
||||
},
|
||||
ready: function () {
|
||||
this.isReady = true;
|
||||
},
|
||||
async _fetchJSON(url, options = {}) {
|
||||
const {body, headers, ...fetchOptions} = options;
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...headers
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
...fetchOptions
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects user and fetches connection id from the server.
|
||||
*
|
||||
* Connects user and fetches connection id from the server
|
||||
*/
|
||||
connect: function () {
|
||||
var request = this.$['ajaxConnect'];
|
||||
request.url = this.connectUrl;
|
||||
request.body = {
|
||||
async connect() {
|
||||
const body = {
|
||||
username: this.username,
|
||||
channels: this.channels
|
||||
};
|
||||
for (var i = 0; i < this.mutators.connect.length; i++) {
|
||||
this.mutators.connect[i](request);
|
||||
|
||||
// Apply mutators
|
||||
for (let mutator of this.mutators.connect) {
|
||||
mutator({body});
|
||||
}
|
||||
request.generateRequest()
|
||||
},
|
||||
|
||||
try {
|
||||
const response = await this._fetchJSON(this.connectUrl, {body});
|
||||
this._handleConnect({detail: {response}});
|
||||
} catch (error) {
|
||||
this._handleConnectError({detail: {error}});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite with custom function that will
|
||||
* Subscribes user to channels
|
||||
*/
|
||||
addMutator: function (type, func) {
|
||||
this.mutators[type].push(func);
|
||||
},
|
||||
/**
|
||||
* Subscribes user to channels.
|
||||
*
|
||||
*/
|
||||
subscribe: function (channels) {
|
||||
var request = this.$['ajaxSubscribe'];
|
||||
request.url = this.subscribeUrl;
|
||||
request.body = {
|
||||
async subscribe(channels) {
|
||||
const body = {
|
||||
channels: channels,
|
||||
conn_id: this.connectionId
|
||||
};
|
||||
for (var i = 0; i < this.mutators.subscribe.length; i++) {
|
||||
this.mutators.subscribe[i](request);
|
||||
}
|
||||
if (request.body.channels.length) {
|
||||
request.generateRequest();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Unsubscribes user from channels.
|
||||
*
|
||||
*/
|
||||
unsubscribe: function (unsubscribe) {
|
||||
var request = this.$['ajaxUnsubscribe'];
|
||||
|
||||
request.url = this.unsubscribeUrl;
|
||||
request.body = {
|
||||
channels: unsubscribe,
|
||||
// Apply mutators
|
||||
for (let mutator of this.mutators.subscribe) {
|
||||
mutator({body});
|
||||
}
|
||||
|
||||
if (body.channels.length) {
|
||||
try {
|
||||
const response = await this._fetchJSON(this.subscribeUrl, {body});
|
||||
this._handleSubscribe({detail: {response}});
|
||||
} catch (error) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-subscribe-error', {detail: error}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes user from channels
|
||||
*/
|
||||
async unsubscribe(channels) {
|
||||
const body = {
|
||||
channels: channels,
|
||||
conn_id: this.connectionId
|
||||
};
|
||||
for (var i = 0; i < this.mutators.unsubscribe.length; i++) {
|
||||
this.mutators.unsubscribe[i](request);
|
||||
|
||||
// Apply mutators
|
||||
for (let mutator of this.mutators.unsubscribe) {
|
||||
mutator({body});
|
||||
}
|
||||
request.generateRequest()
|
||||
},
|
||||
|
||||
try {
|
||||
const response = await this._fetchJSON(this.unsubscribeUrl, {body});
|
||||
this._handleUnsubscribe({detail: {response}});
|
||||
} catch (error) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-unsubscribe-error', {detail: error}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates list of channels we should add user to based on difference
|
||||
* between channels property and passed channel list
|
||||
* Calculates list of channels to add user to
|
||||
*/
|
||||
calculateSubscribe: function (channels) {
|
||||
var currentlySubscribed = this.channels;
|
||||
var toSubscribe = [];
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
calculateSubscribe(channels) {
|
||||
const currentlySubscribed = this.channels;
|
||||
const toSubscribe = [];
|
||||
for (let i = 0; i < channels.length; i++) {
|
||||
if (currentlySubscribed.indexOf(channels[i]) === -1) {
|
||||
toSubscribe.push(channels[i]);
|
||||
}
|
||||
}
|
||||
return toSubscribe
|
||||
},
|
||||
return toSubscribe;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates list of channels we should remove user from based difference
|
||||
* between channels property and passed channel list
|
||||
* Calculates list of channels to remove user from
|
||||
*/
|
||||
calculateUnsubscribe: function (channels) {
|
||||
var currentlySubscribed = this.channels;
|
||||
var toUnsubscribe = [];
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
calculateUnsubscribe(channels) {
|
||||
const currentlySubscribed = this.channels;
|
||||
const toUnsubscribe = [];
|
||||
for (let i = 0; i < channels.length; i++) {
|
||||
if (currentlySubscribed.indexOf(channels[i]) !== -1) {
|
||||
toUnsubscribe.push(channels[i]);
|
||||
}
|
||||
}
|
||||
return toUnsubscribe
|
||||
},
|
||||
/**
|
||||
* Marks the connection as expired.
|
||||
*
|
||||
*/
|
||||
disconnect: function () {
|
||||
var request = this.$['ajaxDisconnect'];
|
||||
request.url = this.disconnectUrl;
|
||||
request.params = {
|
||||
conn_id: this.connectionId
|
||||
};
|
||||
for (var i = 0; i < this.mutators.disconnect.length; i++) {
|
||||
this.mutators.disconnect[i](request);
|
||||
}
|
||||
// mark connection as expired
|
||||
request.generateRequest();
|
||||
// disconnect existing connection
|
||||
this.closeConnection();
|
||||
},
|
||||
return toUnsubscribe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the server.
|
||||
*
|
||||
* Marks the connection as expired
|
||||
*/
|
||||
message: function (message) {
|
||||
var request = this.$['ajaxMessage'];
|
||||
request.url = this.messageUrl;
|
||||
request.body = message;
|
||||
for (var i = 0; i < this.mutators.message.length; i++) {
|
||||
this.mutators.message[i](request)
|
||||
async disconnect() {
|
||||
const params = new URLSearchParams({conn_id: this.connectionId});
|
||||
|
||||
// Apply mutators
|
||||
for (let mutator of this.mutators.disconnect) {
|
||||
mutator({params});
|
||||
}
|
||||
request.generateRequest();
|
||||
},
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.disconnectUrl}?${params}`);
|
||||
const data = await response.json();
|
||||
this._handleDisconnect({detail: {response: data}});
|
||||
} catch (error) {
|
||||
console.error('Disconnect error:', error);
|
||||
}
|
||||
|
||||
// Disconnect existing connection
|
||||
this.closeConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens "long lived" (websocket/longpoll) connection to the channelstream server.
|
||||
*
|
||||
* Sends a message to the server
|
||||
*/
|
||||
startListening: function (event) {
|
||||
this.fire('start-listening', {});
|
||||
async message(messageData) {
|
||||
const body = messageData;
|
||||
|
||||
// Apply mutators
|
||||
for (let mutator of this.mutators.message) {
|
||||
mutator({body});
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this._fetchJSON(this.messageUrl, {body});
|
||||
this._handleMessage({detail: {response}});
|
||||
} catch (error) {
|
||||
this._handleMessageError({detail: {error}});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens long lived connection (websocket/longpoll)
|
||||
*/
|
||||
startListening(event) {
|
||||
this.dispatchEvent(new CustomEvent('start-listening', {detail: {}}));
|
||||
|
||||
if (this.useWebsocket) {
|
||||
this.useWebsocket = window.WebSocket ? true : false;
|
||||
}
|
||||
|
||||
if (this.useWebsocket) {
|
||||
this.openWebsocket();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.openLongPoll();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens websocket connection.
|
||||
*
|
||||
* Opens websocket connection
|
||||
*/
|
||||
openWebsocket: function () {
|
||||
var url = this.websocketUrl + '?conn_id=' + this.connectionId;
|
||||
openWebsocket() {
|
||||
const url = this.websocketUrl + '?conn_id=' + this.connectionId;
|
||||
this.websocket = new WebSocket(url);
|
||||
this.websocket.onopen = this._handleListenOpen.bind(this);
|
||||
this.websocket.onclose = this._handleListenCloseEvent.bind(this);
|
||||
this.websocket.onerror = this._handleListenErrorEvent.bind(this);
|
||||
this.websocket.onmessage = this._handleListenMessageEvent.bind(this);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens long-poll connection.
|
||||
*
|
||||
* Opens long-poll connection
|
||||
*/
|
||||
openLongPoll: function () {
|
||||
var request = this.$['ajaxListen'];
|
||||
request.url = this.longPollUrl + '?conn_id=' + this.connectionId;
|
||||
request.generateRequest()
|
||||
},
|
||||
async openLongPoll() {
|
||||
const url = this.longPollUrl + '?conn_id=' + this.connectionId;
|
||||
|
||||
try {
|
||||
this._handleListenOpen();
|
||||
const response = await fetch(url);
|
||||
const text = await response.text();
|
||||
this._handleListenMessageEvent({data: text});
|
||||
} catch (error) {
|
||||
this._handleListenError({detail: {error}});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retries `connect()` call while incrementing interval between tries up to 1 minute.
|
||||
*
|
||||
* Retries connect() call with increasing interval
|
||||
*/
|
||||
retryConnection: function () {
|
||||
retryConnection() {
|
||||
if (!this.shouldReconnect) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._currentBounceIv < 60000) {
|
||||
this._currentBounceIv = this._currentBounceIv + this.increaseBounceIv;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._currentBounceIv = 60000;
|
||||
}
|
||||
|
||||
setTimeout(this.connect.bind(this), this._currentBounceIv);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes listening connection.
|
||||
*
|
||||
* Closes listening connection
|
||||
*/
|
||||
closeConnection: function () {
|
||||
var request = this.$['ajaxListen'];
|
||||
closeConnection() {
|
||||
if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
|
||||
this.websocket.onclose = null;
|
||||
this.websocket.onerror = null;
|
||||
this.websocket.close();
|
||||
}
|
||||
if (request.loading) {
|
||||
request.lastRequest.abort();
|
||||
|
||||
if (this._heartbeatInterval) {
|
||||
clearInterval(this._heartbeatInterval);
|
||||
this._heartbeatInterval = null;
|
||||
}
|
||||
|
||||
this.connected = false;
|
||||
},
|
||||
}
|
||||
|
||||
_handleChannelsChange: function (event) {
|
||||
// do not fire the event if set() didn't mutate anything
|
||||
// is this a reliable way to do it?
|
||||
if (!this.isReady || event === undefined) {
|
||||
return
|
||||
/**
|
||||
* Add mutator function
|
||||
*/
|
||||
addMutator(type, func) {
|
||||
this.mutators[type].push(func);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create heartbeat interval
|
||||
*/
|
||||
createHeartBeats() {
|
||||
if (!this._heartbeatInterval && this.websocket !== null && this.heartbeats) {
|
||||
this._heartbeatInterval = setInterval(this._sendHeartBeat.bind(this), 10000);
|
||||
}
|
||||
this.fire('channelstream-channels-changed', event)
|
||||
},
|
||||
}
|
||||
|
||||
_handleListenOpen: function (event) {
|
||||
this.connected = true;
|
||||
this.fire('channelstream-listen-opened', event);
|
||||
this.createHeartBeats();
|
||||
},
|
||||
|
||||
createHeartBeats: function () {
|
||||
if (typeof self._heartbeat === 'undefined' && this.websocket !== null
|
||||
&& this.heartbeats) {
|
||||
self._heartbeat = setInterval(this._sendHeartBeat.bind(this), 10000);
|
||||
}
|
||||
},
|
||||
|
||||
_sendHeartBeat: function () {
|
||||
if (this.websocket.readyState === WebSocket.OPEN && this.heartbeats) {
|
||||
/**
|
||||
* Send heartbeat
|
||||
*/
|
||||
_sendHeartBeat() {
|
||||
if (this.websocket && this.websocket.readyState === WebSocket.OPEN && this.heartbeats) {
|
||||
this.websocket.send(JSON.stringify({type: 'heartbeat'}));
|
||||
}
|
||||
},
|
||||
|
||||
_handleListenError: function (event) {
|
||||
this.connected = false;
|
||||
this.retryConnection();
|
||||
},
|
||||
_handleConnectError: function (event) {
|
||||
this.connected = false;
|
||||
this.fire('channelstream-connect-error', event.detail);
|
||||
},
|
||||
|
||||
_handleListenMessageEvent: function (event) {
|
||||
var data = null;
|
||||
// comes from iron-ajax
|
||||
if (event.detail) {
|
||||
data = JSON.parse(event.detail.response)
|
||||
// comes from websocket
|
||||
setTimeout(this.openLongPoll.bind(this), 0);
|
||||
} else {
|
||||
data = JSON.parse(event.data)
|
||||
}
|
||||
this.fire('channelstream-listen-message', data);
|
||||
|
||||
},
|
||||
|
||||
_handleListenCloseEvent: function (event) {
|
||||
this.connected = false;
|
||||
this.fire('channelstream-listen-closed', event.detail);
|
||||
this.retryConnection();
|
||||
},
|
||||
|
||||
_handleListenErrorEvent: function (event) {
|
||||
this.connected = false;
|
||||
this.fire('channelstream-listen-error', {})
|
||||
},
|
||||
|
||||
_handleConnect: function (event) {
|
||||
this.currentBounceIv = 0;
|
||||
this.connectionId = event.detail.response.conn_id;
|
||||
this.fire('channelstream-connected', event.detail.response);
|
||||
},
|
||||
|
||||
_handleDisconnect: function (event) {
|
||||
this.connected = false;
|
||||
this.fire('channelstream-disconnected', {});
|
||||
},
|
||||
|
||||
_handleMessage: function (event) {
|
||||
this.fire('channelstream-message-sent', event.detail.response);
|
||||
},
|
||||
_handleMessageError: function (event) {
|
||||
this.fire('channelstream-message-error', event.detail);
|
||||
},
|
||||
|
||||
_handleSubscribe: function (event) {
|
||||
this.fire('channelstream-subscribed', event.detail.response);
|
||||
},
|
||||
|
||||
_handleSubscribeError: function (event) {
|
||||
this.fire('channelstream-subscribe-error', event.detail);
|
||||
},
|
||||
|
||||
_handleUnsubscribe: function (event) {
|
||||
this.fire('channelstream-unsubscribed', event.detail.response);
|
||||
},
|
||||
|
||||
_handleUnsubscribeError: function (event) {
|
||||
this.fire('channelstream-unsubscribe-error', event.detail);
|
||||
}
|
||||
});
|
||||
|
||||
// Event handlers
|
||||
_handleListenOpen(event) {
|
||||
this.connected = true;
|
||||
this.dispatchEvent(new CustomEvent('channelstream-listen-opened', {detail: event}));
|
||||
this.createHeartBeats();
|
||||
}
|
||||
|
||||
_handleListenError(event) {
|
||||
this.connected = false;
|
||||
this.retryConnection();
|
||||
}
|
||||
|
||||
_handleConnectError(event) {
|
||||
this.connected = false;
|
||||
this.dispatchEvent(new CustomEvent('channelstream-connect-error', {detail: event.detail}));
|
||||
}
|
||||
|
||||
_handleListenMessageEvent(event) {
|
||||
let data = null;
|
||||
|
||||
// From long-poll (fetch)
|
||||
if (event.detail && event.detail.response) {
|
||||
data = JSON.parse(event.detail.response);
|
||||
setTimeout(this.openLongPoll.bind(this), 0);
|
||||
}
|
||||
// From websocket
|
||||
else if (event.data) {
|
||||
data = JSON.parse(event.data);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-listen-message', {detail: data}));
|
||||
}
|
||||
}
|
||||
|
||||
_handleListenCloseEvent(event) {
|
||||
this.connected = false;
|
||||
this.dispatchEvent(new CustomEvent('channelstream-listen-closed', {detail: event}));
|
||||
this.retryConnection();
|
||||
}
|
||||
|
||||
_handleListenErrorEvent(event) {
|
||||
this.connected = false;
|
||||
this.dispatchEvent(new CustomEvent('channelstream-listen-error', {detail: {}}));
|
||||
}
|
||||
|
||||
_handleConnect(event) {
|
||||
this._currentBounceIv = 0;
|
||||
this.connectionId = event.detail.response.conn_id;
|
||||
this.dispatchEvent(new CustomEvent('channelstream-connected', {detail: event.detail.response}));
|
||||
}
|
||||
|
||||
_handleDisconnect(event) {
|
||||
this.connected = false;
|
||||
this.dispatchEvent(new CustomEvent('channelstream-disconnected', {detail: {}}));
|
||||
}
|
||||
|
||||
_handleMessage(event) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-message-sent', {detail: event.detail.response}));
|
||||
}
|
||||
|
||||
_handleMessageError(event) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-message-error', {detail: event.detail}));
|
||||
}
|
||||
|
||||
_handleSubscribe(event) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-subscribed', {detail: event.detail.response}));
|
||||
}
|
||||
|
||||
_handleUnsubscribe(event) {
|
||||
this.dispatchEvent(new CustomEvent('channelstream-unsubscribed', {detail: event.detail.response}));
|
||||
}
|
||||
|
||||
// Polymer compatibility methods - keep these for rhodecode-app
|
||||
push(path, value) {
|
||||
if (path === 'channels') {
|
||||
this.channels = [...this.channels, value];
|
||||
}
|
||||
}
|
||||
|
||||
set(path, value) {
|
||||
if (typeof path === 'string') {
|
||||
this[path] = value;
|
||||
this.requestUpdate(path);
|
||||
} else if (Array.isArray(path)) {
|
||||
// Handle nested paths like ['channelsState', key] or ['userState', key]
|
||||
if (path.length === 2 && path[0] === 'channelsState') {
|
||||
this.channelsState = {...this.channelsState, [path[1]]: value};
|
||||
} else if (path.length === 2 && path[0] === 'userState') {
|
||||
this.userState = {...this.userState, [path[1]]: value};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('channelstream-connection', ChannelstreamConnection);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'regenerator-runtime/runtime.js';
|
||||
import '@polymer/iron-ajax/iron-ajax.js';
|
||||
import './shared-styles.js';
|
||||
import './channelstream-connection/channelstream-connection.js';
|
||||
|
|
|
|||
|
|
@ -1,211 +1,219 @@
|
|||
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
|
||||
import '../channelstream-connection/channelstream-connection.js';
|
||||
import '../rhodecode-toast/rhodecode-toast.js';
|
||||
import '../rhodecode-favicon/rhodecode-favicon.js';
|
||||
import { html, LitElement, css } from "lit";
|
||||
|
||||
var ccLog = Logger.get('RhodeCodeApp');
|
||||
import "../channelstream-connection/channelstream-connection.js";
|
||||
import "../rhodecode-toast/rhodecode-toast.js";
|
||||
import "../rhodecode-favicon/rhodecode-favicon.js";
|
||||
|
||||
var ccLog = Logger.get("RhodeCodeApp");
|
||||
ccLog.setLevel(Logger.OFF);
|
||||
|
||||
export class RhodecodeApp extends PolymerElement {
|
||||
export class RhodecodeApp extends LitElement {
|
||||
static get is() {
|
||||
return "rhodecode-app";
|
||||
}
|
||||
|
||||
static get is() {
|
||||
return 'rhodecode-app';
|
||||
render() {
|
||||
return html`
|
||||
<channelstream-connection
|
||||
id="channelstream-connection"
|
||||
@channelstream-listen-message="${this.receivedMessage}"
|
||||
@channelstream-connected="${this.handleConnected}"
|
||||
@channelstream-subscribed="${this.handleSubscribed}"
|
||||
>
|
||||
</channelstream-connection>
|
||||
<rhodecode-favicon></rhodecode-favicon>
|
||||
`;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
ccLog.debug("rhodeCodeApp created");
|
||||
$.Topic("/notifications").subscribe(this.handleNotifications.bind(this));
|
||||
$.Topic("/comment").subscribe(this.handleComment.bind(this));
|
||||
$.Topic("/favicon/update").subscribe(this.faviconUpdate.bind(this));
|
||||
$.Topic("/connection_controller/subscribe").subscribe(
|
||||
this.subscribeToChannelTopic.bind(this),
|
||||
);
|
||||
|
||||
// this event can be used to coordinate plugins to do their
|
||||
// initialization before channelstream is kicked off
|
||||
$.Topic("/__MAIN_APP__").publish({});
|
||||
|
||||
for (var i = 0; i < alertMessagePayloads.length; i++) {
|
||||
$.Topic("/notifications").publish(alertMessagePayloads[i]);
|
||||
}
|
||||
this.initPlugins();
|
||||
// after rest of application loads and topics get fired, launch connection
|
||||
$(document).ready(
|
||||
function () {
|
||||
this.kickoffChannelstreamPlugin();
|
||||
}.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
static get template(){
|
||||
return html`
|
||||
<channelstream-connection
|
||||
id="channelstream-connection"
|
||||
on-channelstream-listen-message="receivedMessage"
|
||||
on-channelstream-connected="handleConnected"
|
||||
on-channelstream-subscribed="handleSubscribed">
|
||||
</channelstream-connection>
|
||||
<rhodecode-favicon></rhodecode-favicon>
|
||||
`
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
ccLog.debug('rhodeCodeApp created');
|
||||
$.Topic('/notifications').subscribe(this.handleNotifications.bind(this));
|
||||
$.Topic('/comment').subscribe(this.handleComment.bind(this));
|
||||
$.Topic('/favicon/update').subscribe(this.faviconUpdate.bind(this));
|
||||
$.Topic('/connection_controller/subscribe').subscribe(
|
||||
this.subscribeToChannelTopic.bind(this)
|
||||
);
|
||||
|
||||
// this event can be used to coordinate plugins to do their
|
||||
// initialization before channelstream is kicked off
|
||||
$.Topic('/__MAIN_APP__').publish({});
|
||||
|
||||
for (var i = 0; i < alertMessagePayloads.length; i++) {
|
||||
$.Topic('/notifications').publish(alertMessagePayloads[i]);
|
||||
initPlugins() {
|
||||
for (var i = 0; i < window.APPLICATION_PLUGINS.length; i++) {
|
||||
var pluginDef = window.APPLICATION_PLUGINS[i];
|
||||
if (pluginDef.component) {
|
||||
var pluginElem = document.createElement(pluginDef.component);
|
||||
this.shadowRoot.appendChild(pluginElem);
|
||||
if (typeof pluginElem.init !== "undefined") {
|
||||
pluginElem.init();
|
||||
}
|
||||
this.initPlugins();
|
||||
// after rest of application loads and topics get fired, launch connection
|
||||
$(document).ready(function () {
|
||||
this.kickoffChannelstreamPlugin();
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** proxy to channelstream connection */
|
||||
getChannelStreamConnection() {
|
||||
return this.renderRoot.querySelector("#channelstream-connection");
|
||||
}
|
||||
|
||||
handleNotifications(data) {
|
||||
var elem = document.getElementById("notifications");
|
||||
if (elem) {
|
||||
elem.handleNotification(data);
|
||||
}
|
||||
}
|
||||
|
||||
handleComment(data) {
|
||||
if (data.message.comment_data.length !== 0) {
|
||||
if (window.refreshAllComments !== undefined) {
|
||||
refreshAllComments();
|
||||
}
|
||||
var json_data = data.message.comment_data;
|
||||
|
||||
if (window.commentsController !== undefined) {
|
||||
window.commentsController.attachComment(json_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
faviconUpdate(data) {
|
||||
this.shadowRoot.querySelector("rhodecode-favicon").counter = data.count;
|
||||
}
|
||||
|
||||
/** opens connection to ws server */
|
||||
kickoffChannelstreamPlugin(data) {
|
||||
ccLog.debug("kickoffChannelstreamPlugin");
|
||||
var channels = ["broadcast"];
|
||||
var addChannels = this.checkViewChannels();
|
||||
for (var i = 0; i < addChannels.length; i++) {
|
||||
channels.push(addChannels[i]);
|
||||
}
|
||||
if (window.CHANNELSTREAM_SETTINGS && CHANNELSTREAM_SETTINGS.enabled) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
channelstreamConnection.connectUrl = CHANNELSTREAM_URLS.connect;
|
||||
channelstreamConnection.subscribeUrl = CHANNELSTREAM_URLS.subscribe;
|
||||
channelstreamConnection.websocketUrl = CHANNELSTREAM_URLS.ws + "/ws";
|
||||
channelstreamConnection.longPollUrl =
|
||||
CHANNELSTREAM_URLS.longpoll + "/listen";
|
||||
channelstreamConnection.username =
|
||||
window.templateContext.rhodecode_user.username;
|
||||
// some channels might already be registered by topic
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
channelstreamConnection.push("channels", channels[i]);
|
||||
}
|
||||
// append any additional channels registered in other plugins
|
||||
$.Topic("/connection_controller/subscribe").processPrepared();
|
||||
|
||||
channelstreamConnection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
checkViewChannels() {
|
||||
// subscribe to different channels data is sent.
|
||||
|
||||
var channels = [];
|
||||
// subscribe to PR repo channel for PR's'
|
||||
if (templateContext.pull_request_data.pull_request_id) {
|
||||
var channelName =
|
||||
"/repo$" +
|
||||
templateContext.repo_name +
|
||||
"$/pr/" +
|
||||
String(templateContext.pull_request_data.pull_request_id);
|
||||
channels.push(channelName);
|
||||
}
|
||||
|
||||
initPlugins() {
|
||||
for (var i = 0; i < window.APPLICATION_PLUGINS.length; i++) {
|
||||
var pluginDef = window.APPLICATION_PLUGINS[i];
|
||||
if (pluginDef.component) {
|
||||
var pluginElem = document.createElement(pluginDef.component);
|
||||
this.shadowRoot.appendChild(pluginElem);
|
||||
if (typeof pluginElem.init !== 'undefined') {
|
||||
pluginElem.init();
|
||||
}
|
||||
}
|
||||
if (templateContext.commit_data.commit_id) {
|
||||
var channelName =
|
||||
"/repo$" +
|
||||
templateContext.repo_name +
|
||||
"$/commit/" +
|
||||
String(templateContext.commit_data.commit_id);
|
||||
channels.push(channelName);
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
/** subscribes users from channels in channelstream */
|
||||
subscribeToChannelTopic(channels) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
var toSubscribe = channelstreamConnection.calculateSubscribe(channels);
|
||||
ccLog.debug("subscribeToChannelTopic", toSubscribe);
|
||||
if (toSubscribe.length > 0) {
|
||||
// if we are connected then subscribe
|
||||
if (channelstreamConnection.connected) {
|
||||
channelstreamConnection.subscribe(toSubscribe);
|
||||
}
|
||||
// not connected? just push channels onto the stack
|
||||
else {
|
||||
for (var i = 0; i < toSubscribe.length; i++) {
|
||||
channelstreamConnection.push("channels", toSubscribe[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** proxy to channelstream connection */
|
||||
getChannelStreamConnection() {
|
||||
return this.$['channelstream-connection'];
|
||||
/** publish received messages into correct topic */
|
||||
receivedMessage(event) {
|
||||
for (var i = 0; i < event.detail.length; i++) {
|
||||
var message = event.detail[i];
|
||||
if (message.message.topic) {
|
||||
ccLog.debug("publishing", message.message.topic);
|
||||
$.Topic(message.message.topic).publish(message);
|
||||
} else if (message.type === "presence") {
|
||||
$.Topic("/connection_controller/presence").publish(message);
|
||||
} else {
|
||||
ccLog.warn("unhandled message", message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleNotifications(data) {
|
||||
var elem = document.getElementById('notifications');
|
||||
if (elem) {
|
||||
elem.handleNotification(data);
|
||||
}
|
||||
handleConnected(event) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
channelstreamConnection.set("channelsState", event.detail.channels_info);
|
||||
channelstreamConnection.set("userState", event.detail.state);
|
||||
channelstreamConnection.set("channels", event.detail.channels);
|
||||
this.propagageChannelsState();
|
||||
}
|
||||
|
||||
handleSubscribed(event) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
var channelInfo = event.detail.channels_info;
|
||||
var channelKeys = Object.keys(event.detail.channels_info);
|
||||
for (var i = 0; i < channelKeys.length; i++) {
|
||||
var key = channelKeys[i];
|
||||
channelstreamConnection.set(["channelsState", key], channelInfo[key]);
|
||||
}
|
||||
channelstreamConnection.set("channels", event.detail.channels);
|
||||
this.propagageChannelsState();
|
||||
}
|
||||
|
||||
handleComment(data) {
|
||||
|
||||
if (data.message.comment_data.length !== 0) {
|
||||
if (window.refreshAllComments !== undefined) {
|
||||
refreshAllComments()
|
||||
}
|
||||
var json_data = data.message.comment_data;
|
||||
|
||||
if (window.commentsController !== undefined) {
|
||||
|
||||
window.commentsController.attachComment(json_data)
|
||||
}
|
||||
}
|
||||
/** propagates channel states on topics */
|
||||
propagageChannelsState(event) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
var channel_data = channelstreamConnection.channelsState;
|
||||
var channels = channelstreamConnection.channels;
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
var key = channels[i];
|
||||
$.Topic("/connection_controller/channel_update").publish({
|
||||
channel: key,
|
||||
state: channel_data[key],
|
||||
});
|
||||
}
|
||||
|
||||
faviconUpdate(data) {
|
||||
this.shadowRoot.querySelector('rhodecode-favicon').counter = data.count;
|
||||
}
|
||||
|
||||
/** opens connection to ws server */
|
||||
kickoffChannelstreamPlugin(data) {
|
||||
ccLog.debug('kickoffChannelstreamPlugin');
|
||||
var channels = ['broadcast'];
|
||||
var addChannels = this.checkViewChannels();
|
||||
for (var i = 0; i < addChannels.length; i++) {
|
||||
channels.push(addChannels[i]);
|
||||
}
|
||||
if (window.CHANNELSTREAM_SETTINGS && CHANNELSTREAM_SETTINGS.enabled) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
channelstreamConnection.connectUrl = CHANNELSTREAM_URLS.connect;
|
||||
channelstreamConnection.subscribeUrl = CHANNELSTREAM_URLS.subscribe;
|
||||
channelstreamConnection.websocketUrl = CHANNELSTREAM_URLS.ws + '/ws';
|
||||
channelstreamConnection.longPollUrl = CHANNELSTREAM_URLS.longpoll + '/listen';
|
||||
// some channels might already be registered by topic
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
channelstreamConnection.push('channels', channels[i]);
|
||||
}
|
||||
// append any additional channels registered in other plugins
|
||||
$.Topic('/connection_controller/subscribe').processPrepared();
|
||||
|
||||
channelstreamConnection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
checkViewChannels() {
|
||||
// subscribe to different channels data is sent.
|
||||
|
||||
var channels = [];
|
||||
// subscribe to PR repo channel for PR's'
|
||||
if (templateContext.pull_request_data.pull_request_id) {
|
||||
var channelName = '/repo$' + templateContext.repo_name + '$/pr/' +
|
||||
String(templateContext.pull_request_data.pull_request_id);
|
||||
channels.push(channelName);
|
||||
}
|
||||
|
||||
if (templateContext.commit_data.commit_id) {
|
||||
var channelName = '/repo$' + templateContext.repo_name + '$/commit/' +
|
||||
String(templateContext.commit_data.commit_id);
|
||||
channels.push(channelName);
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
/** subscribes users from channels in channelstream */
|
||||
subscribeToChannelTopic(channels) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
var toSubscribe = channelstreamConnection.calculateSubscribe(channels);
|
||||
ccLog.debug('subscribeToChannelTopic', toSubscribe);
|
||||
if (toSubscribe.length > 0) {
|
||||
// if we are connected then subscribe
|
||||
if (channelstreamConnection.connected) {
|
||||
channelstreamConnection.subscribe(toSubscribe);
|
||||
}
|
||||
// not connected? just push channels onto the stack
|
||||
else {
|
||||
for (var i = 0; i < toSubscribe.length; i++) {
|
||||
channelstreamConnection.push('channels', toSubscribe[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** publish received messages into correct topic */
|
||||
receivedMessage(event) {
|
||||
for (var i = 0; i < event.detail.length; i++) {
|
||||
var message = event.detail[i];
|
||||
if (message.message.topic) {
|
||||
ccLog.debug('publishing', message.message.topic);
|
||||
$.Topic(message.message.topic).publish(message);
|
||||
}
|
||||
else if (message.type === 'presence') {
|
||||
$.Topic('/connection_controller/presence').publish(message);
|
||||
}
|
||||
else {
|
||||
ccLog.warn('unhandled message', message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleConnected(event) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
channelstreamConnection.set('channelsState', event.detail.channels_info);
|
||||
channelstreamConnection.set('userState', event.detail.state);
|
||||
channelstreamConnection.set('channels', event.detail.channels);
|
||||
this.propagageChannelsState();
|
||||
}
|
||||
|
||||
handleSubscribed(event) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
var channelInfo = event.detail.channels_info;
|
||||
var channelKeys = Object.keys(event.detail.channels_info);
|
||||
for (var i = 0; i < channelKeys.length; i++) {
|
||||
var key = channelKeys[i];
|
||||
channelstreamConnection.set(['channelsState', key], channelInfo[key]);
|
||||
}
|
||||
channelstreamConnection.set('channels', event.detail.channels);
|
||||
this.propagageChannelsState();
|
||||
}
|
||||
|
||||
/** propagates channel states on topics */
|
||||
propagageChannelsState(event) {
|
||||
var channelstreamConnection = this.getChannelStreamConnection();
|
||||
var channel_data = channelstreamConnection.channelsState;
|
||||
var channels = channelstreamConnection.channels;
|
||||
for (var i = 0; i < channels.length; i++) {
|
||||
var key = channels[i];
|
||||
$.Topic('/connection_controller/channel_update').publish(
|
||||
{channel: key, state: channel_data[key]}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(RhodecodeApp.is, RhodecodeApp);
|
||||
|
|
|
|||
|
|
@ -1,33 +1,30 @@
|
|||
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
|
||||
import {LitElement} from 'lit';
|
||||
|
||||
export class RhodecodeFavicon extends PolymerElement {
|
||||
export class RhodecodeFavicon extends LitElement {
|
||||
static properties = {
|
||||
favicon: {type: Object},
|
||||
counter: {type: Number}
|
||||
};
|
||||
|
||||
static get is() {
|
||||
return 'rhodecode-favicon';
|
||||
constructor() {
|
||||
super();
|
||||
this.favicon = null;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.favicon = new Favico({
|
||||
type: 'rectangle',
|
||||
animation: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has('counter') && this.favicon) {
|
||||
this.favicon.badge(this.counter);
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
favicon: Object,
|
||||
counter: {
|
||||
type: Number,
|
||||
observer: '_handleCounter'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.favicon = new Favico({
|
||||
type: 'rectangle',
|
||||
animation: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
_handleCounter(newVal, oldVal) {
|
||||
this.favicon.badge(this.counter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(RhodecodeFavicon.is, RhodecodeFavicon);
|
||||
customElements.define('rhodecode-favicon', RhodecodeFavicon);
|
||||
|
|
|
|||
|
|
@ -1,231 +1,241 @@
|
|||
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 {LitElement, html, css} from 'lit';
|
||||
import {classMap} from 'lit/directives/class-map.js';
|
||||
import '../rhodecode-unsafe-html/rhodecode-unsafe-html.js';
|
||||
|
||||
export class RhodecodeToast extends mixinBehaviors([IronA11yKeysBehavior], PolymerElement) {
|
||||
|
||||
static get is() {
|
||||
return 'rhodecode-toast';
|
||||
export class RhodecodeToast extends LitElement {
|
||||
static styles = css`
|
||||
.absolute-center {
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
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-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;
|
||||
}
|
||||
|
||||
.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-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;
|
||||
}
|
||||
|
||||
.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-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;
|
||||
}
|
||||
|
||||
.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-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;
|
||||
}
|
||||
|
||||
.bottom-right-rounded-corner-mid {
|
||||
-webkit-border-bottom-right-radius: 2px;
|
||||
-khtml-border-radius-bottomright: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
.alert {
|
||||
clear: both;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid;
|
||||
border-radius: 2px;
|
||||
color: #7E7F7F;
|
||||
border-color: #84a5d2;
|
||||
background-color: #e6edf6;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.alert-success {
|
||||
border-color: #0ac878;
|
||||
background-color: #daf7eb;
|
||||
}
|
||||
|
||||
.toast-close {
|
||||
margin: 0;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
.alert-error {
|
||||
border-color: #e85e4d;
|
||||
background-color: #fbdfdb;
|
||||
}
|
||||
|
||||
.toast-message-holder {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.alert-warning {
|
||||
border-color: #ffc854;
|
||||
background-color: #fff4dd;
|
||||
}
|
||||
|
||||
.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>
|
||||
.alert-info {
|
||||
border-color: #84a5d2;
|
||||
background-color: #e6edf6;
|
||||
}
|
||||
|
||||
<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>
|
||||
.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;
|
||||
}
|
||||
`;
|
||||
|
||||
static properties = {
|
||||
toasts: {type: Array},
|
||||
isFixed: {type: Boolean}
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.toasts = [];
|
||||
this.isFixed = false;
|
||||
this._headerNode = null;
|
||||
this._debouncedCalcBound = this._debouncedCalc.bind(this);
|
||||
this._handleKeyupBound = this._handleKeyup.bind(this);
|
||||
this._debounceTimeout = null;
|
||||
}
|
||||
|
||||
get hasToasts() {
|
||||
return this.toasts && this.toasts.length > 0;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._headerNode = document.querySelector('.header');
|
||||
window.addEventListener('scroll', this._debouncedCalcBound);
|
||||
window.addEventListener('resize', this._debouncedCalcBound);
|
||||
window.addEventListener('keyup', this._handleKeyupBound);
|
||||
this._debouncedCalc();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener('scroll', this._debouncedCalcBound);
|
||||
window.removeEventListener('resize', this._debouncedCalcBound);
|
||||
window.removeEventListener('keyup', this._handleKeyupBound);
|
||||
if (this._debounceTimeout) {
|
||||
clearTimeout(this._debounceTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has('toasts')) {
|
||||
$.Topic('/favicon/update').publish({count: this.toasts.length});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.hasToasts) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class=${classMap({
|
||||
'container': true,
|
||||
'toast-message-holder': true,
|
||||
'fixed': this.isFixed
|
||||
})}>
|
||||
${this.toasts.map((item, index) => html`
|
||||
<div class="alert alert-${item.level}">
|
||||
<div class="toast-close" @click=${() => this.dismissNotification(index)}>
|
||||
<span>${this._gettext('Close')}</span>
|
||||
</div>
|
||||
</template>
|
||||
`
|
||||
<rhodecode-unsafe-html .text=${item.message}></rhodecode-unsafe-html>
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
_handleKeyup(event) {
|
||||
if (event.key === 'Escape') {
|
||||
this.dismissNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
_debouncedCalc() {
|
||||
if (this._debounceTimeout) {
|
||||
clearTimeout(this._debounceTimeout);
|
||||
}
|
||||
this._debounceTimeout = setTimeout(() => {
|
||||
this.toastInWindow();
|
||||
}, 25);
|
||||
}
|
||||
|
||||
get keyBindings() {
|
||||
return {
|
||||
'esc:keyup': '_hideOnEsc'
|
||||
}
|
||||
toastInWindow() {
|
||||
if (!this._headerNode) {
|
||||
return true;
|
||||
}
|
||||
const headerHeight = this._headerNode.offsetHeight;
|
||||
const scrollPosition = window.scrollY;
|
||||
|
||||
static get observers() {
|
||||
return [
|
||||
'_changedToasts(toasts.splices)'
|
||||
]
|
||||
if (this.isFixed) {
|
||||
this.isFixed = 1 <= scrollPosition;
|
||||
} else {
|
||||
this.isFixed = headerHeight <= scrollPosition;
|
||||
}
|
||||
}
|
||||
|
||||
_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)
|
||||
dismissNotification(index) {
|
||||
$.Topic('/favicon/update').publish({count: this.toasts.length - 1});
|
||||
this.toasts = [
|
||||
...this.toasts.slice(0, index),
|
||||
...this.toasts.slice(index + 1)
|
||||
];
|
||||
}
|
||||
|
||||
dismissNotifications() {
|
||||
$.Topic('/favicon/update').publish({count: 0});
|
||||
this.toasts = [];
|
||||
}
|
||||
|
||||
handleNotification(data) {
|
||||
if (!templateContext.rhodecode_user.notification_status && !data.message.force) {
|
||||
return;
|
||||
}
|
||||
this.toasts = [...this.toasts, {
|
||||
level: data.message.level,
|
||||
message: data.message.message
|
||||
}];
|
||||
}
|
||||
|
||||
_gettext(x) {
|
||||
return _gettext(x);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(RhodecodeToast.is, RhodecodeToast);
|
||||
customElements.define('rhodecode-toast', RhodecodeToast);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,24 @@
|
|||
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
|
||||
import {LitElement, html} from 'lit';
|
||||
|
||||
export class RhodecodeUnsafeHtml extends PolymerElement {
|
||||
export class RhodecodeUnsafeHtml extends LitElement {
|
||||
static properties = {
|
||||
text: {type: String}
|
||||
};
|
||||
|
||||
static get is() {
|
||||
return 'rhodecode-unsafe-html';
|
||||
}
|
||||
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="shared-styles"></style>
|
||||
<slot></slot>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
text: {
|
||||
type: String,
|
||||
observer: '_handleText'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_handleText(newVal, oldVal) {
|
||||
this.innerHTML = this.text;
|
||||
constructor() {
|
||||
super();
|
||||
this.text = '';
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
if (changedProperties.has('text')) {
|
||||
this.innerHTML = this.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(RhodecodeUnsafeHtml.is, RhodecodeUnsafeHtml);
|
||||
customElements.define('rhodecode-unsafe-html', RhodecodeUnsafeHtml);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
testSubject.insertAfter(input);
|
||||
|
||||
$(this).bind('keyup keydown blur update', check);
|
||||
$(this).on('keyup keydown blur update', check);
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@
|
|||
|
||||
$.extend(options, suppliedOptions);
|
||||
|
||||
that.isLocal = $.isArray(options.lookup);
|
||||
that.isLocal = Array.isArray(options.lookup);
|
||||
|
||||
if (that.isLocal) {
|
||||
options.lookup = that.verifySuggestionsFormat(options.lookup);
|
||||
|
|
@ -525,14 +525,14 @@
|
|||
if (that.isLocal) {
|
||||
response = that.getSuggestionsLocal(query);
|
||||
} else {
|
||||
if ($.isFunction(serviceUrl)) {
|
||||
if (typeof serviceUrl === 'function') {
|
||||
serviceUrl = serviceUrl.call(that.element, query);
|
||||
}
|
||||
|
||||
var callParams = {};
|
||||
//make an evaluated copy of params
|
||||
$.each(params, function(index, value) {
|
||||
if($.isFunction(value)){
|
||||
if(typeof value === 'function'){
|
||||
callParams[index] = value();
|
||||
}
|
||||
else {
|
||||
|
|
@ -544,7 +544,7 @@
|
|||
response = that.cachedResponse[cacheKey];
|
||||
}
|
||||
|
||||
if (response && $.isArray(response.suggestions)) {
|
||||
if (response && Array.isArray(response.suggestions)) {
|
||||
that.suggestions = response.suggestions;
|
||||
that.suggest();
|
||||
} else if (!that.isBadQuery(query)) {
|
||||
|
|
@ -658,7 +658,7 @@
|
|||
container.children().first().addClass(classSelected);
|
||||
}
|
||||
|
||||
if ($.isFunction(beforeRender)) {
|
||||
if (typeof beforeRender === 'function') {
|
||||
beforeRender.call(that.element, container);
|
||||
}
|
||||
|
||||
|
|
@ -886,7 +886,7 @@
|
|||
that.suggestions = [];
|
||||
that.selection = suggestion;
|
||||
|
||||
if ($.isFunction(onSelectCallback)) {
|
||||
if (typeof onSelectCallback === 'function') {
|
||||
onSelectCallback.call(this, that.element, suggestion, prevElem);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@
|
|||
var api = this.api( true );
|
||||
|
||||
/* Check if we want to add multiple rows or not */
|
||||
var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
|
||||
var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
|
||||
api.rows.add( data ) :
|
||||
api.row.add( data );
|
||||
|
||||
|
|
@ -337,7 +337,7 @@
|
|||
* var oTable;
|
||||
*
|
||||
* // 'open' an information row when a row is clicked on
|
||||
* $('#example tbody tr').click( function () {
|
||||
* $('#example tbody tr').on('click', function () {
|
||||
* if ( oTable.fnIsOpen(this) ) {
|
||||
* oTable.fnClose( this );
|
||||
* } else {
|
||||
|
|
@ -489,7 +489,7 @@
|
|||
* $(document).ready(function() {
|
||||
* oTable = $('#example').dataTable();
|
||||
*
|
||||
* oTable.$('tr').click( function () {
|
||||
* oTable.$('tr').on('click', function () {
|
||||
* var data = oTable.fnGetData( this );
|
||||
* // ... do something with the array / object of data for the row
|
||||
* } );
|
||||
|
|
@ -500,7 +500,7 @@
|
|||
* $(document).ready(function() {
|
||||
* oTable = $('#example').dataTable();
|
||||
*
|
||||
* oTable.$('td').click( function () {
|
||||
* oTable.$('td').on('click', function () {
|
||||
* var sData = oTable.fnGetData( this );
|
||||
* alert( 'The cell clicked on had the value of '+sData );
|
||||
* } );
|
||||
|
|
@ -562,7 +562,7 @@
|
|||
*
|
||||
* @example
|
||||
* $(document).ready(function() {
|
||||
* $('#example tbody td').click( function () {
|
||||
* $('#example tbody td').on('click', function () {
|
||||
* // Get the position of the current data from the node
|
||||
* var aPos = oTable.fnGetPosition( this );
|
||||
*
|
||||
|
|
@ -611,7 +611,7 @@
|
|||
* var oTable;
|
||||
*
|
||||
* // 'open' an information row when a row is clicked on
|
||||
* $('#example tbody tr').click( function () {
|
||||
* $('#example tbody tr').on('click', function () {
|
||||
* if ( oTable.fnIsOpen(this) ) {
|
||||
* oTable.fnClose( this );
|
||||
* } else {
|
||||
|
|
@ -647,7 +647,7 @@
|
|||
* var oTable;
|
||||
*
|
||||
* // 'open' an information row when a row is clicked on
|
||||
* $('#example tbody tr').click( function () {
|
||||
* $('#example tbody tr').on('click', function () {
|
||||
* if ( oTable.fnIsOpen(this) ) {
|
||||
* oTable.fnClose( this );
|
||||
* } else {
|
||||
|
|
@ -976,7 +976,7 @@
|
|||
// If the length menu is given, but the init display length is not, use the length menu
|
||||
if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
|
||||
{
|
||||
oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
|
||||
oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
|
||||
oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
|
||||
}
|
||||
|
||||
|
|
@ -1092,7 +1092,7 @@
|
|||
if ( oInit.iDeferLoading !== null )
|
||||
{
|
||||
oSettings.bDeferLoading = true;
|
||||
var tmp = $.isArray( oInit.iDeferLoading );
|
||||
var tmp = Array.isArray( oInit.iDeferLoading );
|
||||
oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
|
||||
oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
|
||||
}
|
||||
|
|
@ -1822,7 +1822,7 @@
|
|||
|
||||
// orderData can be given as an integer
|
||||
var dataSort = init.aDataSort;
|
||||
if ( dataSort && ! $.isArray( dataSort ) ) {
|
||||
if ( dataSort && ! Array.isArray( dataSort ) ) {
|
||||
init.aDataSort = [ dataSort ];
|
||||
}
|
||||
}
|
||||
|
|
@ -2303,7 +2303,7 @@
|
|||
def.targets :
|
||||
def.aTargets;
|
||||
|
||||
if ( ! $.isArray( aTargets ) )
|
||||
if ( ! Array.isArray( aTargets ) )
|
||||
{
|
||||
aTargets = [ aTargets ];
|
||||
}
|
||||
|
|
@ -2622,7 +2622,7 @@
|
|||
innerSrc = a.join('.');
|
||||
|
||||
// Traverse each entry in the array getting the properties requested
|
||||
if ( $.isArray( data ) ) {
|
||||
if ( Array.isArray( data ) ) {
|
||||
for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
|
||||
out.push( fetchData( data[j], type, innerSrc ) );
|
||||
}
|
||||
|
|
@ -2725,7 +2725,7 @@
|
|||
innerSrc = b.join('.');
|
||||
|
||||
// Traverse each entry in the array setting the properties requested
|
||||
if ( $.isArray( val ) )
|
||||
if ( Array.isArray( val ) )
|
||||
{
|
||||
for ( var j=0, jLen=val.length ; j<jLen ; j++ )
|
||||
{
|
||||
|
|
@ -3811,7 +3811,7 @@
|
|||
|
||||
// Convert to object based for 1.10+ if using the old array scheme which can
|
||||
// come from server-side processing or serverParams
|
||||
if ( data && $.isArray(data) ) {
|
||||
if ( data && Array.isArray(data) ) {
|
||||
var tmp = {};
|
||||
var rbracket = /(.*?)\[\]$/;
|
||||
|
||||
|
|
@ -3846,12 +3846,12 @@
|
|||
{
|
||||
ajaxData = ajax.data;
|
||||
|
||||
var newData = $.isFunction( ajaxData ) ?
|
||||
var newData = typeof ajaxData === 'function' ?
|
||||
ajaxData( data, oSettings ) : // fn can manipulate data or return
|
||||
ajaxData; // an object object or array to merge
|
||||
|
||||
// If the function returned something, use that alone
|
||||
data = $.isFunction( ajaxData ) && newData ?
|
||||
data = typeof ajaxData === 'function' && newData ?
|
||||
newData :
|
||||
$.extend( true, data, newData );
|
||||
|
||||
|
|
@ -3915,7 +3915,7 @@
|
|||
url: ajax || oSettings.sAjaxSource
|
||||
} ) );
|
||||
}
|
||||
else if ( $.isFunction( ajax ) )
|
||||
else if ( typeof ajax === 'function' )
|
||||
{
|
||||
// Is a function - let the caller define what needs to be done
|
||||
oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
|
||||
|
|
@ -4787,7 +4787,7 @@
|
|||
classes = settings.oClasses,
|
||||
tableId = settings.sTableId,
|
||||
menu = settings.aLengthMenu,
|
||||
d2 = $.isArray( menu[0] ),
|
||||
d2 = Array.isArray( menu[0] ),
|
||||
lengths = d2 ? menu[0] : menu,
|
||||
language = d2 ? menu[1] : menu;
|
||||
|
||||
|
|
@ -5824,7 +5824,7 @@
|
|||
fixedObj = $.isPlainObject( fixed ),
|
||||
nestedSort = [],
|
||||
add = function ( a ) {
|
||||
if ( a.length && ! $.isArray( a[0] ) ) {
|
||||
if ( a.length && ! Array.isArray( a[0] ) ) {
|
||||
// 1D array
|
||||
nestedSort.push( a );
|
||||
}
|
||||
|
|
@ -5836,7 +5836,7 @@
|
|||
|
||||
// Build the sort array, with pre-fix and post-fix options if they have been
|
||||
// specified
|
||||
if ( $.isArray( fixed ) ) {
|
||||
if ( Array.isArray( fixed ) ) {
|
||||
add( fixed );
|
||||
}
|
||||
|
||||
|
|
@ -6465,9 +6465,9 @@
|
|||
*/
|
||||
function _fnMap( ret, src, name, mappedName )
|
||||
{
|
||||
if ( $.isArray( name ) ) {
|
||||
if ( Array.isArray( name ) ) {
|
||||
$.each( name, function (i, val) {
|
||||
if ( $.isArray( val ) ) {
|
||||
if ( Array.isArray( val ) ) {
|
||||
_fnMap( ret, src, val[0], val[1] );
|
||||
}
|
||||
else {
|
||||
|
|
@ -6519,7 +6519,7 @@
|
|||
}
|
||||
$.extend( true, out[prop], val );
|
||||
}
|
||||
else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
|
||||
else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
|
||||
out[prop] = val.slice();
|
||||
}
|
||||
else {
|
||||
|
|
@ -6863,7 +6863,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
if ( $.isArray( context ) ) {
|
||||
if ( Array.isArray( context ) ) {
|
||||
for ( var i=0, ien=context.length ; i<ien ; i++ ) {
|
||||
ctxSettings( context[i] );
|
||||
}
|
||||
|
|
@ -7217,7 +7217,7 @@
|
|||
|
||||
_Api.register = _api_register = function ( name, val )
|
||||
{
|
||||
if ( $.isArray( name ) ) {
|
||||
if ( Array.isArray( name ) ) {
|
||||
for ( var j=0, jen=name.length ; j<jen ; j++ ) {
|
||||
_Api.register( name[j], val );
|
||||
}
|
||||
|
|
@ -7282,7 +7282,7 @@
|
|||
// New API instance returned, want the value from the first item
|
||||
// in the returned array for the singular result.
|
||||
return ret.length ?
|
||||
$.isArray( ret[0] ) ?
|
||||
Array.isArray( ret[0] ) ?
|
||||
new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
|
||||
ret[0] :
|
||||
undefined;
|
||||
|
|
@ -8129,7 +8129,7 @@
|
|||
var rows = [];
|
||||
var addRow = function ( r, k ) {
|
||||
// Recursion to allow for arrays of jQuery objects
|
||||
if ( $.isArray( r ) || r instanceof $ ) {
|
||||
if ( Array.isArray( r ) || r instanceof $ ) {
|
||||
for ( var i=0, ien=r.length ; i<ien ; i++ ) {
|
||||
addRow( r[i], k );
|
||||
}
|
||||
|
|
@ -8890,7 +8890,7 @@
|
|||
// Simple column / direction passed in
|
||||
order = [ [ order, dir ] ];
|
||||
}
|
||||
else if ( order.length && ! $.isArray( order[0] ) ) {
|
||||
else if ( order.length && ! Array.isArray( order[0] ) ) {
|
||||
// Arguments passed in (list of 1D arrays)
|
||||
order = Array.prototype.slice.call( arguments );
|
||||
}
|
||||
|
|
@ -8926,7 +8926,7 @@
|
|||
ctx[0].aaSortingFixed :
|
||||
undefined;
|
||||
|
||||
return $.isArray( fixed ) ?
|
||||
return Array.isArray( fixed ) ?
|
||||
{ pre: fixed } :
|
||||
fixed;
|
||||
}
|
||||
|
|
@ -14548,7 +14548,7 @@
|
|||
for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
|
||||
button = buttons[i];
|
||||
|
||||
if ( $.isArray( button ) ) {
|
||||
if ( Array.isArray( button ) ) {
|
||||
var inner = $( '<'+(button.DT_el || 'div')+'/>' )
|
||||
.appendTo( container );
|
||||
attach( inner, button );
|
||||
|
|
|
|||
|
|
@ -93,13 +93,12 @@
|
|||
//
|
||||
// > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
|
||||
// >
|
||||
// > jQuery('selector').bind( 'someevent', throttled );
|
||||
// > jQuery('selector').unbind( 'someevent', throttled );
|
||||
// > jQuery('selector').on( 'someevent', throttled );
|
||||
// > jQuery('selector').off( 'someevent', throttled );
|
||||
//
|
||||
// This also works in jQuery 1.4+:
|
||||
//
|
||||
// > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
|
||||
// > jQuery('selector').unbind( 'someevent', callback );
|
||||
// > jQuery('selector').on( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
|
||||
// > jQuery('selector').off( 'someevent', callback );
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
|
|
@ -217,13 +216,12 @@
|
|||
//
|
||||
// > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
|
||||
// >
|
||||
// > jQuery('selector').bind( 'someevent', debounced );
|
||||
// > jQuery('selector').unbind( 'someevent', debounced );
|
||||
// > jQuery('selector').on( 'someevent', debounced );
|
||||
// > jQuery('selector').off( 'someevent', debounced );
|
||||
//
|
||||
// This also works in jQuery 1.4+:
|
||||
//
|
||||
// > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
|
||||
// > jQuery('selector').unbind( 'someevent', callback );
|
||||
// > jQuery('selector').on( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
|
||||
// > jQuery('selector').off( 'someevent', callback );
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ function handleSubmit(event, container, options) {
|
|||
function pjax(options) {
|
||||
options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
|
||||
|
||||
if ($.isFunction(options.url)) {
|
||||
if (typeof options.url === 'function') {
|
||||
options.url = options.url()
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ function pjax(options) {
|
|||
// Without adding this secret parameter, some browsers will often
|
||||
// confuse the two.
|
||||
if (!options.data) options.data = {}
|
||||
if ($.isArray(options.data)) {
|
||||
if (Array.isArray(options.data)) {
|
||||
options.data.push({name: '_pjax', value: context.selector})
|
||||
} else {
|
||||
options.data._pjax = context.selector
|
||||
|
|
@ -505,7 +505,7 @@ function onPjaxPopstate(event) {
|
|||
//
|
||||
// Returns nothing since it retriggers a hard form submission.
|
||||
function fallbackPjax(options) {
|
||||
var url = $.isFunction(options.url) ? options.url() : options.url,
|
||||
var url = typeof options.url === 'function' ? options.url() : options.url,
|
||||
method = options.type ? options.type.toUpperCase() : 'GET'
|
||||
|
||||
var form = $('<form>', {
|
||||
|
|
@ -528,7 +528,7 @@ function fallbackPjax(options) {
|
|||
var pair = value.split('=')
|
||||
form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
|
||||
})
|
||||
} else if ($.isArray(data)) {
|
||||
} else if (Array.isArray(data)) {
|
||||
$.each(data, function(index, value) {
|
||||
form.append($('<input>', {type: 'hidden', name: value.name, value: value.value}))
|
||||
})
|
||||
|
|
@ -539,7 +539,7 @@ function fallbackPjax(options) {
|
|||
}
|
||||
|
||||
$(document.body).append(form)
|
||||
form.submit()
|
||||
form.trigger('submit')
|
||||
}
|
||||
|
||||
// Internal: Abort an XmlHttpRequest if it hasn't been completed,
|
||||
|
|
@ -910,9 +910,9 @@ function disable() {
|
|||
|
||||
|
||||
// Add the state property to jQuery's event object so we can use it in
|
||||
// $(window).bind('popstate')
|
||||
if ( $.inArray('state', $.event.props) < 0 )
|
||||
$.event.props.push('state')
|
||||
// $(window).on('popstate')
|
||||
if ( $.event && $.event.addProp )
|
||||
$.event.addProp('state')
|
||||
|
||||
// Is pjax supported by this browser?
|
||||
$.support.pjax =
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@
|
|||
}, _data.latency);
|
||||
};
|
||||
|
||||
$(this).bind('scroll', handler).data(uid1, handler);
|
||||
$(this).on('scroll', handler).data(uid1, handler);
|
||||
},
|
||||
teardown: function() {
|
||||
$(this).unbind('scroll', $(this).data(uid1));
|
||||
$(this).off('scroll', $(this).data(uid1));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -82,10 +82,10 @@
|
|||
}, _data.latency);
|
||||
};
|
||||
|
||||
$(this).bind('scroll', handler).data(uid2, handler);
|
||||
$(this).on('scroll', handler).data(uid2, handler);
|
||||
},
|
||||
teardown: function() {
|
||||
$(this).unbind('scroll', $(this).data(uid2));
|
||||
$(this).off('scroll', $(this).data(uid2));
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -3,25 +3,41 @@ var AgeModule = (function () {
|
|||
return {
|
||||
age: function(prevdate, now, show_short_version, show_suffix, short_format) {
|
||||
|
||||
var prevdate = moment(prevdate).utc();
|
||||
var now = now ? moment(now).utc() : moment().utc();
|
||||
prevdate = luxon.DateTime.fromJSDate(prevdate, { zone: "utc" });
|
||||
now = now
|
||||
? luxon.DateTime.fromJSDate(now, { zone: "utc" })
|
||||
: luxon.DateTime.utc();
|
||||
|
||||
var show_short_version = show_short_version || false;
|
||||
var show_suffix = show_suffix || true;
|
||||
var short_format = short_format || false;
|
||||
|
||||
var _get_relative_delta = function(now, prevdate) {
|
||||
const duration = now.diff(prevdate, [
|
||||
"years",
|
||||
"months",
|
||||
"days",
|
||||
"hours",
|
||||
"minutes",
|
||||
"seconds",
|
||||
]);
|
||||
const {
|
||||
years = 0,
|
||||
months = 0,
|
||||
days = 0,
|
||||
hours = 0,
|
||||
minutes = 0,
|
||||
seconds = 0,
|
||||
} = duration.toObject();
|
||||
|
||||
var duration = moment.duration(moment(now).diff(prevdate));
|
||||
return {
|
||||
'year': duration.years(),
|
||||
'month': duration.months(),
|
||||
'day': duration.days(),
|
||||
'hour': duration.hours(),
|
||||
'minute': duration.minutes(),
|
||||
'second': duration.seconds()
|
||||
};
|
||||
|
||||
return {
|
||||
year: years,
|
||||
month: months,
|
||||
day: days,
|
||||
hour: hours,
|
||||
minute: minutes,
|
||||
second: seconds,
|
||||
};
|
||||
};
|
||||
|
||||
var _is_leap_year = function(year){
|
||||
|
|
@ -29,11 +45,12 @@ var AgeModule = (function () {
|
|||
};
|
||||
|
||||
var get_month = function(prevdate) {
|
||||
return prevdate.getMonth()
|
||||
// mimic moment().month() // 0–11
|
||||
return prevdate.month - 1;
|
||||
};
|
||||
|
||||
var get_year = function(prevdate) {
|
||||
return prevdate.getYear()
|
||||
return prevdate.year;
|
||||
};
|
||||
|
||||
var order = ['year', 'month', 'day', 'hour', 'minute', 'second'];
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
var years = days / 365;
|
||||
|
||||
function substitute(stringOrFunction, number) {
|
||||
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
|
||||
var string = typeof stringOrFunction === 'function' ? stringOrFunction(number, distanceMillis) : stringOrFunction;
|
||||
var value = ($l.numbers && $l.numbers[number]) || number;
|
||||
return string.replace(/%d/i, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ if (typeof console == "undefined" || typeof console.log == "undefined"){
|
|||
* show more
|
||||
*/
|
||||
var show_more_event = function(){
|
||||
$('table .show_more').click(function(e) {
|
||||
$('table .show_more').on('click', function(e) {
|
||||
var cid = e.target.id.substring(1);
|
||||
var button = $(this);
|
||||
if (button.hasClass('open')) {
|
||||
|
|
@ -65,7 +65,7 @@ var compare_radio_buttons = function(repo_name, compare_ref_type){
|
|||
var source = $('input[name=compare_source]:checked').val();
|
||||
var target = $('input[name=compare_target]:checked').val();
|
||||
if(source && target){
|
||||
$('#compare_action').removeAttr("disabled");
|
||||
$('#compare_action').prop('disabled', false);
|
||||
$('#compare_action').removeClass("disabled");
|
||||
}
|
||||
})
|
||||
|
|
@ -188,8 +188,8 @@ function collapsableContent() {
|
|||
|
||||
$('.collapsable-content').not('.no-hide').hide();
|
||||
|
||||
$('.btn-collapse').unbind(); //in case we've been here before
|
||||
$('.btn-collapse').click(function() {
|
||||
$('.btn-collapse').off(); //in case we've been here before
|
||||
$('.btn-collapse').on('click', function() {
|
||||
var button = $(this);
|
||||
var togglename = $(this).data("toggle");
|
||||
$('.collapsable-content[data-toggle='+togglename+']').toggle();
|
||||
|
|
@ -503,7 +503,7 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
$('#expand_all_files').click(function() {
|
||||
$('#expand_all_files').on('click', function() {
|
||||
$('.expand_file').each(function() {
|
||||
var node = $(this);
|
||||
var icon = $($(node.children().first()).children().first());
|
||||
|
|
@ -521,7 +521,7 @@ $(document).ready(function() {
|
|||
});
|
||||
});
|
||||
|
||||
$('#collapse_all_files').click(function() {
|
||||
$('#collapse_all_files').on('click', function() {
|
||||
$('.collapse_file').each(function() {
|
||||
var node = $(this);
|
||||
var icon = $($(node.children().first()).children().first());
|
||||
|
|
@ -652,22 +652,22 @@ var feedLifetimeOptions = function(query, initialData){
|
|||
|
||||
if (isQuery) {
|
||||
|
||||
var now = moment.utc();
|
||||
const now = luxon.DateTime.utc();
|
||||
|
||||
var parseQuery = function(entry, now){
|
||||
var fmt = 'DD/MM/YYYY H:mm';
|
||||
var parsed = moment.utc(entry, fmt);
|
||||
var diffInMin = parsed.diff(now, 'minutes');
|
||||
var fmt = 'dd/LL/yyyy H:mm';
|
||||
var parsed = luxon.DateTime.fromFormat(entry, fmt, { zone: "utc" });
|
||||
var diffInMin = parsed.diff(now, "minutes").as("minutes");
|
||||
|
||||
if (diffInMin > 0){
|
||||
return {
|
||||
id: diffInMin,
|
||||
text: parsed.format(fmt)
|
||||
text: parsed.toFormat(fmt),
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
id: undefined,
|
||||
text: parsed.format('DD/MM/YYYY') + ' ' + _gettext('date not in future')
|
||||
text: parsed.toFormat('DD/MM/YYYY') + ' ' + _gettext('date not in future')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -349,12 +349,12 @@ var initCommentBoxCodeMirror = function(CommentForm, textAreaId, triggerActions)
|
|||
};
|
||||
|
||||
var submitForm = function(cm, pred) {
|
||||
$(cm.display.input.textarea.form).find('.submit-comment-action').click();
|
||||
$(cm.display.input.textarea.form).find('.submit-comment-action').trigger('click');
|
||||
return CodeMirror.Pass;
|
||||
};
|
||||
|
||||
var submitFormAsDraft = function(cm, pred) {
|
||||
$(cm.display.input.textarea.form).find('.submit-draft-action').click();
|
||||
$(cm.display.input.textarea.form).find('.submit-draft-action').trigger('click');
|
||||
return CodeMirror.Pass;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
|
|||
$(self.editButton).parent().removeClass('active');
|
||||
});
|
||||
|
||||
$(this.submitForm).submit(function(e) {
|
||||
$(this.submitForm).on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var allowedToSubmit = self.isAllowedToSubmit();
|
||||
if (!allowedToSubmit){
|
||||
|
|
@ -551,7 +551,7 @@ var initVersionSelector = function(selector, initialData) {
|
|||
|
||||
$(selector).on('select2-selecting', function (e) {
|
||||
// hide the mast as we later do preventDefault()
|
||||
$("#select2-drop-mask").click();
|
||||
$("#select2-drop-mask").trigger('click');
|
||||
e.preventDefault();
|
||||
e.choice.action();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ var checkFileHead = function($editForm, commit_id, f_path, operation) {
|
|||
|
||||
$editForm.find('#commit_btn').data('validHead', true);
|
||||
$editForm.find('#commit_btn').val('Committing...');
|
||||
$editForm.submit();
|
||||
$editForm.trigger('submit');
|
||||
|
||||
} else {
|
||||
var message = '';
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ var quick_repo_menu = function() {
|
|||
$('.menu_items_container').hide();
|
||||
$('.active_quick_repo').removeClass('active_quick_repo');
|
||||
};
|
||||
$('.quick_repo_menu').hover(function() {
|
||||
$('.quick_repo_menu').on('mouseenter', function() {
|
||||
hide_quick_repo_menus();
|
||||
if (!$(this).hasClass('active_quick_repo')) {
|
||||
$('.menu_items_container', this).removeClass("hidden").show();
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ var prButtonLock = function(lockEnabled, msg, scope) {
|
|||
$('#pr_submit').attr('disabled', 'disabled');
|
||||
}
|
||||
else if (checksMeet) {
|
||||
$('#pr_submit').removeAttr('disabled');
|
||||
$('#pr_submit').prop('disabled', false);
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
|
|
@ -653,10 +653,10 @@ window.VersionController = function () {
|
|||
|
||||
|
||||
this.attachVersionListener = function () {
|
||||
self.$verTarget.change(function (e) {
|
||||
self.$verTarget.on('change', function (e) {
|
||||
self.adjustRadioSelectors(this)
|
||||
});
|
||||
self.$verSource.change(function (e) {
|
||||
self.$verSource.on('change', function (e) {
|
||||
self.adjustRadioSelectors(self.$verTarget.filter(':checked'))
|
||||
});
|
||||
};
|
||||
|
|
@ -679,7 +679,7 @@ window.VersionController = function () {
|
|||
$showVersionDiff.html($showVersionDiff.data('labelTextLocked'));
|
||||
}
|
||||
else {
|
||||
$showVersionDiff.removeAttr('disabled');
|
||||
$showVersionDiff.prop('disabled', false);
|
||||
$showVersionDiff.removeClass('disabled');
|
||||
|
||||
if (selectedVersion == otherVersion) {
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ function submitConfirm(event, self, question, confirmText, htmlText) {
|
|||
confirmButtonText: confirmText
|
||||
}).then(function(result) {
|
||||
if (result.value) {
|
||||
$(self).closest("form").submit();
|
||||
$(self).closest("form").trigger('submit');
|
||||
}
|
||||
})
|
||||
}
|
||||
50
rhodecode/public/js/src/select2/select2.js
vendored
50
rhodecode/public/js/src/select2/select2.js
vendored
|
|
@ -428,7 +428,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
if (handler && typeof handler.abort === "function") { handler.abort(); }
|
||||
|
||||
if (options.params) {
|
||||
if ($.isFunction(options.params)) {
|
||||
if (typeof options.params === 'function') {
|
||||
$.extend(params, options.params.call(self));
|
||||
} else {
|
||||
$.extend(params, options.params);
|
||||
|
|
@ -481,12 +481,12 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
tmp,
|
||||
text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
|
||||
|
||||
if ($.isArray(data)) {
|
||||
if (Array.isArray(data)) {
|
||||
tmp = data;
|
||||
data = { results: tmp };
|
||||
}
|
||||
|
||||
if ($.isFunction(data) === false) {
|
||||
if (typeof data !== 'function') {
|
||||
tmp = data;
|
||||
data = function() { return tmp; };
|
||||
}
|
||||
|
|
@ -495,7 +495,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
if (dataItem.text) {
|
||||
text = dataItem.text;
|
||||
// if text is not a function we assume it to be a key name
|
||||
if (!$.isFunction(text)) {
|
||||
if (typeof data !== 'function') {
|
||||
dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
|
||||
text = function (item) { return item[dataText]; };
|
||||
}
|
||||
|
|
@ -535,11 +535,11 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
|
||||
// TODO javadoc
|
||||
function tags(data) {
|
||||
var isFunc = $.isFunction(data);
|
||||
var isFunc = typeof data === 'function';
|
||||
return function (query) {
|
||||
var t = query.term, filtered = {results: []};
|
||||
var result = isFunc ? data(query) : data;
|
||||
if ($.isArray(result)) {
|
||||
if (Array.isArray(result)) {
|
||||
$(result).each(function () {
|
||||
var isObject = this.text !== undefined,
|
||||
text = isObject ? this.text : this;
|
||||
|
|
@ -561,7 +561,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
* @param formatter
|
||||
*/
|
||||
function checkFormatter(formatter, formatterName) {
|
||||
if ($.isFunction(formatter)) return true;
|
||||
if (typeof formatter === 'function') return true;
|
||||
if (!formatter) return false;
|
||||
if (typeof(formatter) === 'string') return true;
|
||||
throw new Error(formatterName +" must be a string, function, or falsy value");
|
||||
|
|
@ -576,7 +576,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
* @returns {*}
|
||||
*/
|
||||
function evaluate(val, context) {
|
||||
if ($.isFunction(val)) {
|
||||
if (typeof val === 'function') {
|
||||
var args = Array.prototype.slice.call(arguments, 2);
|
||||
return val.apply(context, args);
|
||||
}
|
||||
|
|
@ -816,7 +816,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
|
||||
this.lastSearchTerm = undefined;
|
||||
|
||||
if ($.isFunction(this.opts.initSelection)) {
|
||||
if (typeof this.opts.initSelection === 'function') {
|
||||
// initialize selection based on the current value of the source element
|
||||
this.initSelection();
|
||||
|
||||
|
|
@ -1026,7 +1026,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
var elemTags = opts.element.data('tags');
|
||||
|
||||
// data-tags should actually be a boolean
|
||||
if (!$.isArray(elemTags)) {
|
||||
if (!Array.isArray(elemTags)) {
|
||||
elemTags = [];
|
||||
}
|
||||
|
||||
|
|
@ -1045,7 +1045,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
|
||||
// ajax.results -> ajax.processResults
|
||||
if (opts.ajax != null) {
|
||||
if ($.isFunction(opts.ajax.processResults)) {
|
||||
if (typeof opts.ajax.processResults === 'function') {
|
||||
opts.ajax.results = opts.ajax.processResults;
|
||||
}
|
||||
}
|
||||
|
|
@ -1055,32 +1055,32 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
var lang = opts.language;
|
||||
|
||||
// formatNoMatches -> language.noMatches
|
||||
if ($.isFunction(lang.noMatches)) {
|
||||
if (typeof lang.noMatches === 'function') {
|
||||
opts.formatNoMatches = lang.noMatches;
|
||||
}
|
||||
|
||||
// formatSearching -> language.searching
|
||||
if ($.isFunction(lang.searching)) {
|
||||
if (typeof lang.searching === 'function') {
|
||||
opts.formatSearching = lang.searching;
|
||||
}
|
||||
|
||||
// formatInputTooShort -> language.inputTooShort
|
||||
if ($.isFunction(lang.inputTooShort)) {
|
||||
if (typeof lang.inputTooShort === 'function') {
|
||||
opts.formatInputTooShort = lang.inputTooShort;
|
||||
}
|
||||
|
||||
// formatInputTooLong -> language.inputTooLong
|
||||
if ($.isFunction(lang.inputTooLong)) {
|
||||
if (typeof lang.inputTooLong === 'function') {
|
||||
opts.formatInputTooLong = lang.inputTooLong;
|
||||
}
|
||||
|
||||
// formatLoading -> language.loadingMore
|
||||
if ($.isFunction(lang.loadingMore)) {
|
||||
if (typeof lang.loadingMore === 'function') {
|
||||
opts.formatLoading = lang.loadingMore;
|
||||
}
|
||||
|
||||
// formatSelectionTooBig -> language.maximumSelected
|
||||
if ($.isFunction(lang.maximumSelected)) {
|
||||
if (typeof lang.maximumSelected === 'function') {
|
||||
opts.formatSelectionTooBig = lang.maximumSelected;
|
||||
}
|
||||
}
|
||||
|
|
@ -1152,7 +1152,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
opts.id = function (e) { return e[idKey]; };
|
||||
}
|
||||
|
||||
if ($.isArray(opts.element.data("select2Tags"))) {
|
||||
if (Array.isArray(opts.element.data("select2Tags"))) {
|
||||
if ("tags" in opts) {
|
||||
throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");
|
||||
}
|
||||
|
|
@ -1217,7 +1217,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
$(splitVal(element.val(), opts.separator, opts.transformVal)).each(function () {
|
||||
var obj = { id: this, text: this },
|
||||
tags = opts.tags;
|
||||
if ($.isFunction(tags)) tags=tags();
|
||||
if (typeof tags === 'function') tags=tags();
|
||||
$(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } });
|
||||
data.push(obj);
|
||||
});
|
||||
|
|
@ -1321,7 +1321,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
|
||||
// some validation frameworks ignore the change event and listen instead to keyup, click for selects
|
||||
// so here we trigger the click event manually
|
||||
this.opts.element.click();
|
||||
this.opts.element.trigger('click');
|
||||
|
||||
// ValidationEngine ignores the change event and listens instead to blur
|
||||
// so here we trigger the blur event manually if so desired
|
||||
|
|
@ -1904,7 +1904,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
var maxSelSize = this.getMaximumSelectionSize();
|
||||
if (maxSelSize >=1) {
|
||||
data = this.data();
|
||||
if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
|
||||
if (Array.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
|
||||
render("<li class='select2-selection-limit'>" + evaluate(opts.formatSelectionTooBig, opts.element, maxSelSize) + "</li>");
|
||||
return;
|
||||
}
|
||||
|
|
@ -2116,7 +2116,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
}
|
||||
|
||||
return null;
|
||||
} else if ($.isFunction(this.opts.width)) {
|
||||
} else if (typeof this.opts.width === 'function') {
|
||||
return this.opts.width();
|
||||
} else {
|
||||
return this.opts.width;
|
||||
|
|
@ -2530,7 +2530,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
}
|
||||
return is_match;
|
||||
},
|
||||
callback: !$.isFunction(callback) ? $.noop : function() {
|
||||
callback: typeof callback !== 'function' ? $.noop : function() {
|
||||
callback(match);
|
||||
}
|
||||
});
|
||||
|
|
@ -2822,7 +2822,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
}
|
||||
return is_match;
|
||||
},
|
||||
callback: !$.isFunction(callback) ? $.noop : function() {
|
||||
callback: typeof callback !== 'function' ? $.noop : function() {
|
||||
// reorder matches based on the order they appear in the ids array because right now
|
||||
// they are in the order in which they appear in data array
|
||||
var ordered = [];
|
||||
|
|
@ -3642,7 +3642,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
|||
id: function (e) { return e == undefined ? null : e.id; },
|
||||
text: function (e) {
|
||||
if (e && this.data && this.data.text) {
|
||||
if ($.isFunction(this.data.text)) {
|
||||
if (typeof this.data.text === 'function') {
|
||||
return this.data.text(e);
|
||||
} else {
|
||||
return e[this.data.text];
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
$('.toggle-plugin').click(function(e){
|
||||
$('.toggle-plugin').on('click', function(e){
|
||||
var auth_plugins_input = $('#auth_plugins');
|
||||
var elems = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
|
||||
if(detected_mode){
|
||||
$(modes_select).select2("val", mimetype);
|
||||
$(modes_select).change();
|
||||
$(modes_select).trigger('change');
|
||||
setCodeMirrorMode(myCodeMirror, detected_mode);
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
$.Topic('/notifications').publish(alertMessage[0]);
|
||||
}
|
||||
else{
|
||||
$('#eform').submit();
|
||||
$('#eform').trigger('submit');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -108,6 +108,6 @@
|
|||
});
|
||||
|
||||
$('.reset-inheritance').on('click', function(e){
|
||||
$('#inherit_global_issuetracker').prop('checked', false).change();
|
||||
$('#inherit_global_issuetracker').prop('checked', false).trigger('change');
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ executeTask = function() {
|
|||
|
||||
$(displayHtml).append(data);
|
||||
$('#results').html(displayHtml);
|
||||
btn.removeAttr('disabled');
|
||||
btn.prop('disabled', false);
|
||||
btn.removeClass('disabled');
|
||||
};
|
||||
ajaxGET(url, success, null);
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ checkCommits = function() {
|
|||
};
|
||||
|
||||
btn.html('Strip');
|
||||
btn.removeAttr('disabled');
|
||||
btn.prop('disabled', false);
|
||||
btn.removeClass('disabled');
|
||||
btn.attr('onclick','strip();return false;');
|
||||
ajaxPOST(url, postData, success, null);
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ import json
|
|||
setAIFieldsActive(this.checked);
|
||||
});
|
||||
|
||||
$updateModelsBtn.click(function () {
|
||||
$updateModelsBtn.on('click', function () {
|
||||
const $apiKey = $('#rhodecode_ai_api_key input');
|
||||
|
||||
if (!$apiKey.val()) {
|
||||
|
|
@ -211,7 +211,7 @@ import json
|
|||
|
||||
});
|
||||
|
||||
$form.submit(function () {
|
||||
$form.on('submit', function () {
|
||||
let $f = $(this);
|
||||
|
||||
let $tmpEnabled = $f.find(':disabled');
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
$('#check_for_update').click(function(e){
|
||||
$('#check_for_update').on('click', function(e){
|
||||
$('#update_notice').show();
|
||||
$('#update_notice').load("${h.route_path('admin_settings_system_update', _query={'ver': request.GET.get('ver')})}");
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1195,7 +1195,7 @@
|
|||
"use sctrict";
|
||||
|
||||
// details block auto-hide menu
|
||||
$(document).mouseup(function(e) {
|
||||
$(document).on('mouseup', function(e) {
|
||||
var container = $('.details-inline-block');
|
||||
if (!container.is(e.target) && container.has(e.target).length === 0) {
|
||||
$('.details-inline-block[open]').removeAttr('open')
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ c.template_context['attachment_store'] = {
|
|||
</%def>
|
||||
${self.robots()}
|
||||
<link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
|
||||
<script src="${h.asset('js/vendors/webcomponentsjs/custom-elements-es5-adapter.js', ver=c.rhodecode_version_hash)}"></script>
|
||||
<script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-bundle.js', ver=c.rhodecode_version_hash)}"></script>
|
||||
|
||||
## CSS definitions
|
||||
|
|
|
|||
|
|
@ -1170,7 +1170,7 @@ def get_comments_for(diff_type, comments, filename, line_version, line_number):
|
|||
// expand the container if we quick-select the field
|
||||
$('#'+idSelector).next().prop('checked', false);
|
||||
// hide the mast as we later do preventDefault()
|
||||
$("#select2-drop-mask").click();
|
||||
$("#select2-drop-mask").trigger('click');
|
||||
|
||||
window.location.hash = '#'+idSelector;
|
||||
updateSticky();
|
||||
|
|
|
|||
|
|
@ -1135,12 +1135,12 @@ $(document).ready(function () {
|
|||
$('#selected_mode').html(detected_mode);
|
||||
}
|
||||
|
||||
$('#ignorews').change(function(e){
|
||||
$('#ignorews').on('change', function(e){
|
||||
var val = e.currentTarget.checked;
|
||||
$('#compare').mergely('options', {ignorews: val});
|
||||
$('#compare').mergely('update');
|
||||
});
|
||||
$('#edit_mode').change(function(e){
|
||||
$('#edit_mode').on('change', function(e){
|
||||
var val = !e.currentTarget.checked;
|
||||
$('#compare').mergely('cm', 'lhs').setOption('readOnly', val);
|
||||
$('#compare').mergely('cm', 'rhs').setOption('readOnly', val);
|
||||
|
|
|
|||
|
|
@ -934,7 +934,7 @@ $(document).ready(function() {
|
|||
elem.html(elem.html() + ' ' + total );
|
||||
});
|
||||
|
||||
$('#merge_pull_request_form').submit(function() {
|
||||
$('#merge_pull_request_form').on('submit', function() {
|
||||
if (!$('#merge_pull_request').attr('disabled')) {
|
||||
$('#merge_pull_request').attr('disabled', 'disabled');
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -50,7 +50,7 @@
|
|||
var state = getFileState();
|
||||
|
||||
// select code link event
|
||||
$("#hlcode").mouseup(getSelectionLink);
|
||||
$("#hlcode").on('mouseup', getSelectionLink);
|
||||
|
||||
// file history select2 used for history of file, and switch to
|
||||
var initialCommitData = {
|
||||
|
|
|
|||
|
|
@ -131,15 +131,15 @@
|
|||
|
||||
|
||||
<script>
|
||||
$('#squash_merge_pull_request').click(function (e) {
|
||||
$('#squash_merge_pull_request').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('#squash_merge_pull_request_value').val("true");
|
||||
|
||||
$('#merge_pull_request_form').submit();
|
||||
$('#merge_pull_request_form').trigger('submit');
|
||||
});
|
||||
|
||||
$('#merge_pull_request_form').submit(function () {
|
||||
$('#merge_pull_request_form').on('submit', function () {
|
||||
if (!$('#merge_pull_request').attr('disabled')) {
|
||||
$('#merge_pull_request').attr('disabled', 'disabled');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -978,7 +978,7 @@ window.setObserversData = ${c.pull_request_set_observers_data_json | n};
|
|||
// inject closing flag
|
||||
$('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
|
||||
$(generalCommentForm.statusChange).select2("val", status).trigger('change');
|
||||
$(generalCommentForm.submitForm).submit();
|
||||
$(generalCommentForm.submitForm).trigger('submit');
|
||||
};
|
||||
|
||||
//TODO this functionality is now missing
|
||||
|
|
@ -995,7 +995,7 @@ window.setObserversData = ${c.pull_request_set_observers_data_json | n};
|
|||
}
|
||||
});
|
||||
|
||||
$('#merge_pull_request_form').submit(function () {
|
||||
$('#merge_pull_request_form').on('submit', function () {
|
||||
if (!$('#merge_pull_request').attr('disabled')) {
|
||||
$('#merge_pull_request').attr('disabled', 'disabled');
|
||||
}
|
||||
|
|
@ -1038,7 +1038,7 @@ window.setObserversData = ${c.pull_request_set_observers_data_json | n};
|
|||
});
|
||||
|
||||
// fixing issue with caches on firefox
|
||||
$('#update_commits').removeAttr("disabled");
|
||||
$('#update_commits').prop('disabled', false);
|
||||
|
||||
$('.show-inline-comments').on('click', function (e) {
|
||||
var boxid = $(this).attr('data-comment-id');
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ index a934a3360ef6bdf340a036e6f3475daa7a54103c..00000000000000000000000000000000
|
|||
-
|
||||
-/*
|
||||
- // Toggle Calendars
|
||||
- $('div#sidebar ul li a').click(function() {
|
||||
- $('div#sidebar ul li a').on('click', function() {
|
||||
- if ($(this).is('#toggleMonthView')) {
|
||||
- console.log('toggle month');
|
||||
- $(this).addClass('active');
|
||||
|
|
@ -297,8 +297,8 @@ index 0000000000000000000000000000000000000000..db7af7989499dd359737a880828f8d1b
|
|||
+ }
|
||||
+
|
||||
+ // Keyboard controls
|
||||
+ $(document).bind('keydown', keydownHandler);
|
||||
+ $(document).bind('keyup', keyupHandler);
|
||||
+ $(document).on('keydown', keydownHandler);
|
||||
+ $(document).on('keyup', keyupHandler);
|
||||
+
|
||||
+ /**
|
||||
+ * Helpers
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ deleted file mode 100644
|
|||
-
|
||||
-/*
|
||||
- // Toggle Calendars
|
||||
- $('div#sidebar ul li a').click(function() {
|
||||
- $('div#sidebar ul li a').on('click', function() {
|
||||
- if ($(this).is('#toggleMonthView')) {
|
||||
- console.log('toggle month');
|
||||
- $(this).addClass('active');
|
||||
|
|
@ -286,8 +286,8 @@ new file mode 100755
|
|||
+ }
|
||||
+
|
||||
+ // Keyboard controls
|
||||
+ $(document).bind('keydown', keydownHandler);
|
||||
+ $(document).bind('keyup', keyupHandler);
|
||||
+ $(document).on('keydown', keydownHandler);
|
||||
+ $(document).on('keyup', keyupHandler);
|
||||
+
|
||||
+ /**
|
||||
+ * Helpers
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ search.location = %(here)s/.rc-test-data/data/index
|
|||
channelstream.enabled = false
|
||||
|
||||
; server address for channelstream server on the backend
|
||||
channelstream.server = channelstream:9800
|
||||
channelstream.server = channelstream:8000
|
||||
|
||||
; location of the channelstream server from outside world
|
||||
; use ws:// for http or wss:// for https. This address needs to be handled
|
||||
|
|
|
|||
|
|
@ -15,11 +15,19 @@ let babelRCOptions = {
|
|||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"browsers": ["last 2 versions"]
|
||||
}
|
||||
"esmodules": true
|
||||
},
|
||||
"exclude": [
|
||||
"transform-es2015-classes",
|
||||
"transform-regenerator",
|
||||
"transform-async-to-generator"
|
||||
]
|
||||
}]
|
||||
],
|
||||
"plugins": ["transform-object-rest-spread"]
|
||||
"plugins": [
|
||||
["transform-class-properties", { "loose": true }],
|
||||
"transform-object-rest-spread"
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
@ -67,9 +75,10 @@ module.exports = {
|
|||
{
|
||||
// If you see a file that ends in .js, just send it to the babel-loader.
|
||||
test: /\.js$/,
|
||||
// Exclude node_modules, but process our Lit components
|
||||
// Babel is configured to NOT transpile ES6 classes (see babelRCOptions exclude)
|
||||
exclude: /node_modules/,
|
||||
use: {loader: 'babel-loader', options: babelRCOptions}
|
||||
// Optionally exclude node_modules from transpilation except for polymer-webpack-loader:
|
||||
// exclude: /node_modules\/(?!polymer-webpack-loader\/).*/
|
||||
},
|
||||
// this is required because of bug:
|
||||
// https://github.com/webpack-contrib/polymer-webpack-loader/issues/49
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue