mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Keep upstream changes
This commit is contained in:
commit
91b3e20f7a
14 changed files with 209 additions and 49 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "elasticsearch",
|
||||
"version": "1.5.4",
|
||||
"version": "1.5.8",
|
||||
"authors": [
|
||||
"Spencer Alger <spencer@spenceralger.com>"
|
||||
],
|
||||
|
@ -12,11 +12,11 @@
|
|||
],
|
||||
"license": "Apache 2.0",
|
||||
"homepage": "https://github.com/elasticsearch/bower-elasticsearch-js",
|
||||
"_release": "1.5.4",
|
||||
"_release": "1.5.8",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.5.4",
|
||||
"commit": "5dc3e0b427eb97fa3fe41e38f288774e44bc478d"
|
||||
"tag": "v1.5.8",
|
||||
"commit": "589b05935b702bfe81e442f2d32fbad19bba312c"
|
||||
},
|
||||
"_source": "git://github.com/elasticsearch/bower-elasticsearch-js.git",
|
||||
"_target": "*",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "elasticsearch",
|
||||
"version": "1.5.4",
|
||||
"version": "1.5.8",
|
||||
"authors": [
|
||||
"Spencer Alger <spencer@spenceralger.com>"
|
||||
],
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*! elasticsearch - v1.5.4 - 2014-02-11
|
||||
/*! elasticsearch - v1.5.8 - 2014-02-17
|
||||
* http://www.elasticsearch.org/guide/en/elasticsearch/client/javascript-api/current/index.html
|
||||
* Copyright (c) 2014 Elasticsearch BV; Licensed Apache 2.0 */
|
||||
;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
|
@ -16152,6 +16152,28 @@ api.cluster.prototype.nodeStats = ca({
|
|||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform a [cluster.pendingTasks](http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/cluster-pending.html) request
|
||||
*
|
||||
* @param {Object} params - An object with parameters used to carry out this action
|
||||
* @param {Boolean} params.local - Return local information, do not retrieve the state from master node (default: false)
|
||||
* @param {Date, Number} params.masterTimeout - Specify timeout for connection to master
|
||||
*/
|
||||
api.cluster.prototype.pendingTasks = ca({
|
||||
params: {
|
||||
local: {
|
||||
type: 'boolean'
|
||||
},
|
||||
masterTimeout: {
|
||||
type: 'time',
|
||||
name: 'master_timeout'
|
||||
}
|
||||
},
|
||||
url: {
|
||||
fmt: '/_cluster/pending_tasks'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform a [cluster.putSettings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/cluster-update-settings.html) request
|
||||
*
|
||||
|
@ -18811,6 +18833,9 @@ api.search = ca({
|
|||
type: 'list'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
fmt: '/_search'
|
||||
}
|
||||
],
|
||||
method: 'POST'
|
||||
|
@ -24227,7 +24252,6 @@ Client.apis = require('./apis');
|
|||
module.exports = ClientAction;
|
||||
|
||||
var _ = require('./utils');
|
||||
var when = require('when');
|
||||
|
||||
function ClientAction(spec) {
|
||||
if (!_.isPlainObject(spec.params)) {
|
||||
|
@ -24248,12 +24272,14 @@ function ClientAction(spec) {
|
|||
}
|
||||
|
||||
try {
|
||||
return exec(this.transport, spec, params, cb);
|
||||
return exec(this.transport, spec, _.clone(params), cb);
|
||||
} catch (e) {
|
||||
if (typeof cb === 'function') {
|
||||
_.nextTick(cb, e);
|
||||
} else {
|
||||
return when.reject(e);
|
||||
var def = this.transport.defer();
|
||||
def.reject(e);
|
||||
return def.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24525,7 +24551,7 @@ ClientAction.proxy = function (fn, spec) {
|
|||
};
|
||||
};
|
||||
|
||||
},{"./utils":211,"when":1}],195:[function(require,module,exports){
|
||||
},{"./utils":211}],195:[function(require,module,exports){
|
||||
module.exports = ConnectionAbstract;
|
||||
|
||||
var _ = require('./utils');
|
||||
|
@ -24959,7 +24985,7 @@ ConnectionPool.prototype.close = function () {
|
|||
};
|
||||
ConnectionPool.prototype.empty = ConnectionPool.prototype.close;
|
||||
},{"./connectors":198,"./log":201,"./selectors":206,"./utils":211,"__browserify_process":13}],197:[function(require,module,exports){
|
||||
/**
|
||||
var Buffer=require("__browserify_Buffer").Buffer;/**
|
||||
* Connection that registers a module with angular, using angular's $http service
|
||||
* to communicate with ES.
|
||||
*
|
||||
|
@ -24975,6 +25001,9 @@ function AngularConnector(host, config) {
|
|||
ConnectionAbstract.call(this, host, config);
|
||||
this.defer = config.defer;
|
||||
this.$http = config.$http;
|
||||
if(this.host.auth) {
|
||||
this.$http.defaults.headers.common.Authorization = 'Basic ' + Buffer(this.host.auth, 'utf8').toString('base64');
|
||||
}
|
||||
}
|
||||
_.inherits(AngularConnector, ConnectionAbstract);
|
||||
|
||||
|
@ -25002,7 +25031,7 @@ AngularConnector.prototype.request = function (params, cb) {
|
|||
};
|
||||
};
|
||||
|
||||
},{"../connection":195,"../errors":199,"../utils":211}],198:[function(require,module,exports){
|
||||
},{"../connection":195,"../errors":199,"../utils":211,"__browserify_Buffer":12}],198:[function(require,module,exports){
|
||||
var opts = {
|
||||
xhr: require('./xhr'),
|
||||
jquery: require('./jquery'),
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
/*! elasticsearch - v1.5.4 - 2014-02-11
|
||||
/*! elasticsearch - v1.5.8 - 2014-02-17
|
||||
* http://www.elasticsearch.org/guide/en/elasticsearch/client/javascript-api/current/index.html
|
||||
* Copyright (c) 2014 Elasticsearch BV; Licensed Apache 2.0 */
|
||||
;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
|
@ -16159,6 +16159,28 @@ api.cluster.prototype.nodeStats = ca({
|
|||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform a [cluster.pendingTasks](http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/cluster-pending.html) request
|
||||
*
|
||||
* @param {Object} params - An object with parameters used to carry out this action
|
||||
* @param {Boolean} params.local - Return local information, do not retrieve the state from master node (default: false)
|
||||
* @param {Date, Number} params.masterTimeout - Specify timeout for connection to master
|
||||
*/
|
||||
api.cluster.prototype.pendingTasks = ca({
|
||||
params: {
|
||||
local: {
|
||||
type: 'boolean'
|
||||
},
|
||||
masterTimeout: {
|
||||
type: 'time',
|
||||
name: 'master_timeout'
|
||||
}
|
||||
},
|
||||
url: {
|
||||
fmt: '/_cluster/pending_tasks'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform a [cluster.putSettings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/cluster-update-settings.html) request
|
||||
*
|
||||
|
@ -18818,6 +18840,9 @@ api.search = ca({
|
|||
type: 'list'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
fmt: '/_search'
|
||||
}
|
||||
],
|
||||
method: 'POST'
|
||||
|
@ -24234,7 +24259,6 @@ Client.apis = require('./apis');
|
|||
module.exports = ClientAction;
|
||||
|
||||
var _ = require('./utils');
|
||||
var when = require('when');
|
||||
|
||||
function ClientAction(spec) {
|
||||
if (!_.isPlainObject(spec.params)) {
|
||||
|
@ -24255,12 +24279,14 @@ function ClientAction(spec) {
|
|||
}
|
||||
|
||||
try {
|
||||
return exec(this.transport, spec, params, cb);
|
||||
return exec(this.transport, spec, _.clone(params), cb);
|
||||
} catch (e) {
|
||||
if (typeof cb === 'function') {
|
||||
_.nextTick(cb, e);
|
||||
} else {
|
||||
return when.reject(e);
|
||||
var def = this.transport.defer();
|
||||
def.reject(e);
|
||||
return def.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24532,7 +24558,7 @@ ClientAction.proxy = function (fn, spec) {
|
|||
};
|
||||
};
|
||||
|
||||
},{"./utils":212,"when":1}],196:[function(require,module,exports){
|
||||
},{"./utils":212}],196:[function(require,module,exports){
|
||||
module.exports = ConnectionAbstract;
|
||||
|
||||
var _ = require('./utils');
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
/*! elasticsearch - v1.5.4 - 2014-02-11
|
||||
/*! elasticsearch - v1.5.8 - 2014-02-17
|
||||
* http://www.elasticsearch.org/guide/en/elasticsearch/client/javascript-api/current/index.html
|
||||
* Copyright (c) 2014 Elasticsearch BV; Licensed Apache 2.0 */
|
||||
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.elasticsearch=e():"undefined"!=typeof global?global.elasticsearch=e():"undefined"!=typeof self&&(self.elasticsearch=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
|
@ -17090,6 +17090,28 @@ api.cluster.prototype.nodeStats = ca({
|
|||
]
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform a [cluster.pendingTasks](http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/cluster-pending.html) request
|
||||
*
|
||||
* @param {Object} params - An object with parameters used to carry out this action
|
||||
* @param {Boolean} params.local - Return local information, do not retrieve the state from master node (default: false)
|
||||
* @param {Date, Number} params.masterTimeout - Specify timeout for connection to master
|
||||
*/
|
||||
api.cluster.prototype.pendingTasks = ca({
|
||||
params: {
|
||||
local: {
|
||||
type: 'boolean'
|
||||
},
|
||||
masterTimeout: {
|
||||
type: 'time',
|
||||
name: 'master_timeout'
|
||||
}
|
||||
},
|
||||
url: {
|
||||
fmt: '/_cluster/pending_tasks'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Perform a [cluster.putSettings](http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/cluster-update-settings.html) request
|
||||
*
|
||||
|
@ -19749,6 +19771,9 @@ api.search = ca({
|
|||
type: 'list'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
fmt: '/_search'
|
||||
}
|
||||
],
|
||||
method: 'POST'
|
||||
|
@ -25165,7 +25190,6 @@ Client.apis = require('./apis');
|
|||
module.exports = ClientAction;
|
||||
|
||||
var _ = require('./utils');
|
||||
var when = require('when');
|
||||
|
||||
function ClientAction(spec) {
|
||||
if (!_.isPlainObject(spec.params)) {
|
||||
|
@ -25186,12 +25210,14 @@ function ClientAction(spec) {
|
|||
}
|
||||
|
||||
try {
|
||||
return exec(this.transport, spec, params, cb);
|
||||
return exec(this.transport, spec, _.clone(params), cb);
|
||||
} catch (e) {
|
||||
if (typeof cb === 'function') {
|
||||
_.nextTick(cb, e);
|
||||
} else {
|
||||
return when.reject(e);
|
||||
var def = this.transport.defer();
|
||||
def.reject(e);
|
||||
return def.promise;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25463,7 +25489,7 @@ ClientAction.proxy = function (fn, spec) {
|
|||
};
|
||||
};
|
||||
|
||||
},{"./utils":212,"when":189}],196:[function(require,module,exports){
|
||||
},{"./utils":212}],196:[function(require,module,exports){
|
||||
module.exports = ConnectionAbstract;
|
||||
|
||||
var _ = require('./utils');
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -25,6 +25,7 @@ define(function (require) {
|
|||
if (courier._activeSearchRequest) {
|
||||
return courier._error(new HastyRefresh());
|
||||
}
|
||||
|
||||
courier._activeSearchRequest = SearchSource.fetch(
|
||||
courier,
|
||||
courier._refs.search,
|
||||
|
@ -120,7 +121,7 @@ define(function (require) {
|
|||
|
||||
// store a quick "bound" method for triggering
|
||||
this._onInterval[type] = function () {
|
||||
onFetch[type](courier);
|
||||
if (courier._refs[type].length) onFetch[type](courier);
|
||||
courier._schedule(type);
|
||||
};
|
||||
|
||||
|
@ -171,8 +172,8 @@ define(function (require) {
|
|||
|
||||
// force a fetch of all datasources right now
|
||||
Courier.prototype.fetch = function () {
|
||||
_.forOwn(onFetch, function (method, type) {
|
||||
method(this);
|
||||
_.forOwn(onFetch, function (fn, type) {
|
||||
if (this._refs[type].length) fn(this);
|
||||
}, this);
|
||||
};
|
||||
|
||||
|
|
|
@ -62,6 +62,14 @@ define(function (require) {
|
|||
* PUBLIC API
|
||||
*****/
|
||||
|
||||
/**
|
||||
* Get values from the state
|
||||
* @param {string} name - The name of the property desired
|
||||
*/
|
||||
DataSource.prototype.get = function (name) {
|
||||
return this._state[name];
|
||||
};
|
||||
|
||||
/**
|
||||
* fetch the field names for this DataSource
|
||||
* @param {Function} cb
|
||||
|
@ -102,7 +110,7 @@ define(function (require) {
|
|||
if (EventEmitter.listenerCount(this, 'error')) {
|
||||
this.emit('error', err);
|
||||
} else {
|
||||
this._courier.emit('error', err);
|
||||
this._courier._error(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -156,5 +164,12 @@ define(function (require) {
|
|||
return flatState;
|
||||
};
|
||||
|
||||
DataSource.prototype._resolveIndexPattern = function (start, end) {
|
||||
if (this._state.indexInterval) {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
return this._state.index;
|
||||
};
|
||||
|
||||
return DataSource;
|
||||
});
|
|
@ -2,6 +2,7 @@ define(function (require) {
|
|||
var DataSource = require('courier/data_source/data_source');
|
||||
var inherits = require('utils/inherits');
|
||||
var errors = require('courier/errors');
|
||||
var listenerCount = require('utils/event_emitter').listenerCount;
|
||||
var _ = require('lodash');
|
||||
|
||||
function DocSource(courier, initialState) {
|
||||
|
@ -41,8 +42,7 @@ define(function (require) {
|
|||
var ref = allRefs[i];
|
||||
var source = ref.source;
|
||||
|
||||
//if (resp.error) return this._error(resp);
|
||||
if (resp.error) return false;
|
||||
if (resp.error) return source._error(new errors.DocFetchFailure(resp));
|
||||
if (ref.version === resp._version) return; // no change
|
||||
ref.version = resp._version;
|
||||
source._storeVersion(resp._version);
|
||||
|
@ -62,7 +62,7 @@ define(function (require) {
|
|||
*/
|
||||
DocSource.validate = function (courier, refs, cb) {
|
||||
var invalid = _.filter(refs, function (ref) {
|
||||
var storedVersion = ref.source._getStoredVersion();
|
||||
var storedVersion = ref.source._getVersion();
|
||||
if (ref.version !== storedVersion) return true;
|
||||
});
|
||||
setTimeout(function () {
|
||||
|
@ -92,7 +92,7 @@ define(function (require) {
|
|||
* @param {Function} cb - Callback to know when the update is complete
|
||||
* @return {undefined}
|
||||
*/
|
||||
DocSource.prototype.update = function (fields, cb) {
|
||||
DocSource.prototype.doUpdate = function (fields, cb) {
|
||||
var source = this;
|
||||
var courier = this._courier;
|
||||
var client = courier._getClient();
|
||||
|
@ -113,6 +113,43 @@ define(function (require) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the document stored
|
||||
* @param {[type]} body [description]
|
||||
* @param {Function} cb [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
DocSource.prototype.doIndex = function (body, cb) {
|
||||
var source = this;
|
||||
var courier = this._courier;
|
||||
var client = courier._getClient();
|
||||
var state = this._state;
|
||||
|
||||
client.index({
|
||||
id: state.id,
|
||||
type: state.type,
|
||||
index: state.index,
|
||||
version: source._getVersion(),
|
||||
body: body,
|
||||
ignore: [409]
|
||||
}, function (err, resp) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (resp && resp.status === 409) {
|
||||
err = new errors.VersionConflict(resp);
|
||||
if (listenerCount(source, 'conflict')) {
|
||||
return source.emit('conflict', err);
|
||||
} else {
|
||||
return cb(err);
|
||||
}
|
||||
}
|
||||
|
||||
source._storeVersion(resp._version);
|
||||
courier._docUpdated(source);
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
/*****
|
||||
* PRIVATE API
|
||||
*****/
|
||||
|
@ -163,7 +200,7 @@ define(function (require) {
|
|||
* Fetches the stored version from localStorage
|
||||
* @return {number} - the version number, or NaN
|
||||
*/
|
||||
DocSource.prototype._getStoredVersion = function () {
|
||||
DocSource.prototype._getVersion = function () {
|
||||
var id = this._versionKey();
|
||||
return _.parseInt(localStorage.getItem(id));
|
||||
};
|
||||
|
|
|
@ -64,6 +64,7 @@ define(function (require) {
|
|||
*/
|
||||
SearchSource.prototype._methods = [
|
||||
'index',
|
||||
'indexInterval', // monthly, daily, etc
|
||||
'type',
|
||||
'query',
|
||||
'filter',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
define(function (require, module, exports) {
|
||||
define(function (require) {
|
||||
var listenerCount = require('utils/event_emitter').listenerCount;
|
||||
var errors = {};
|
||||
|
||||
// caused by a refresh attempting to start before the prevous is done
|
||||
function HastyRefresh() {
|
||||
|
@ -8,7 +9,7 @@ define(function (require, module, exports) {
|
|||
}
|
||||
HastyRefresh.prototype = new Error();
|
||||
HastyRefresh.prototype.constructor = HastyRefresh;
|
||||
exports.HastyRefresh = HastyRefresh;
|
||||
errors.HastyRefresh = HastyRefresh;
|
||||
|
||||
// a non-critical cache write to elasticseach failed
|
||||
function CacheWriteFailure() {
|
||||
|
@ -17,7 +18,7 @@ define(function (require, module, exports) {
|
|||
}
|
||||
CacheWriteFailure.prototype = new Error();
|
||||
CacheWriteFailure.prototype.constructor = CacheWriteFailure;
|
||||
exports.CacheWriteFailure = CacheWriteFailure;
|
||||
errors.CacheWriteFailure = CacheWriteFailure;
|
||||
|
||||
// when a field mapping is requested for an unknown field
|
||||
function FieldNotFoundInCache(name) {
|
||||
|
@ -26,6 +27,27 @@ define(function (require, module, exports) {
|
|||
}
|
||||
FieldNotFoundInCache.prototype = new Error();
|
||||
FieldNotFoundInCache.prototype.constructor = FieldNotFoundInCache;
|
||||
exports.FieldNotFoundInCache = FieldNotFoundInCache;
|
||||
errors.FieldNotFoundInCache = FieldNotFoundInCache;
|
||||
|
||||
// where there is an error getting a doc
|
||||
function DocFetchFailure(resp) {
|
||||
this.name = 'DocFetchFailure';
|
||||
this.resp = resp;
|
||||
this.message = 'Failed to get the doc: ' + JSON.stringify(resp);
|
||||
}
|
||||
DocFetchFailure.prototype = new Error();
|
||||
DocFetchFailure.prototype.constructor = DocFetchFailure;
|
||||
errors.DocFetchFailure = DocFetchFailure;
|
||||
|
||||
// there was a conflict storing a doc
|
||||
function VersionConflict(resp) {
|
||||
this.name = 'VersionConflict';
|
||||
this.resp = resp;
|
||||
this.message = 'Failed to store document changes do to a version conflict.';
|
||||
}
|
||||
VersionConflict.prototype = new Error();
|
||||
VersionConflict.prototype.constructor = VersionConflict;
|
||||
errors.VersionConflict = VersionConflict;
|
||||
|
||||
return errors;
|
||||
});
|
|
@ -2,6 +2,7 @@ define(function (require) {
|
|||
var angular = require('angular');
|
||||
var Courier = require('courier/courier');
|
||||
var DocSource = require('courier/data_source/doc');
|
||||
var errors = require('courier/errors');
|
||||
|
||||
require('services/promises');
|
||||
|
||||
|
@ -9,8 +10,8 @@ define(function (require) {
|
|||
.service('courier', function (es, promises) {
|
||||
|
||||
promises.playNice(DocSource.prototype, [
|
||||
'update',
|
||||
'index'
|
||||
'doUpdate',
|
||||
'doIndex'
|
||||
]);
|
||||
|
||||
var courier = new Courier({
|
||||
|
@ -19,6 +20,8 @@ define(function (require) {
|
|||
promises: promises
|
||||
});
|
||||
|
||||
courier.errors = errors;
|
||||
|
||||
return courier;
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue