var app = angular.module('plunker', ['smart-table']);
app.controller('MainCtrl', function($scope) {
$scope.probes = [
{ "type": "temperature", "name": "74 DP22000-15060", "value": "+12.7" },
{ "type": "temperature", "name": "Ambiance C8", "value": "+31.6°C" },
{ "type": "temperature", "name": "Ambiance ST", "value": "+33.6°C" },
{ "type": "temperature", "name": "ambiance C12", "value": "+23.6°C" },
{ "type": "temperature", "name": "Ambiance C10", "value": "+23.6°C" },
{ "type": "hygrometry", "name": "Congélateur", "value": "25%" },
{ "type": "hygrometry", "name": "Congélateur 2", "value": "53%" },
{ "type": "hygrometry", "name": "Congélateur 6", "value": "18%" },
{ "type": "hygrometry", "name": "Hygrometry 6", "value": "5%" },
{ "type": "temperature", "name": "Frigo 1", "value": "4°C" },
{ "type": "", "name": "mobile 05", "value": "#######" },
{ "type": "particle", "name": "Particule 420", "value": "555 p/m" },
{ "type": "particle", "name": "Ambiance C9", "value": "#######" },
{ "type": "particle", "name": "Salle blanche C1", "value": "#######" },
{ "type": "particle", "name": "salle blanche C8", "value": "-######" },
{ "type": "pressure", "name": "Salle blanche C7", "value": "-######" },
{ "type": "tor", "name": "TOR 75", "value": "ON" },
{ "type": "tor", "name": "TOR PRE", "value": "ON" }
];
$scope.sortByName = function (row) {
return row.name.toLowerCase();
};
$scope.rowCollection = [
{firstName: 'Laurent', lastName: 'Renard', birthDate: new Date('1987-05-21'), balance: 102, email: 'whatever@gmail.com'},
{firstName: 'Blandine', lastName: 'Faivre', birthDate: new Date('1987-04-25'), balance: -2323.22, email: 'oufblandou@gmail.com'},
{firstName: 'Francoise', lastName: 'Frere', birthDate: new Date('1955-08-27'), balance: 42343, email: 'raymondef@gmail.com'}
];
$scope.getters = {
firstName: function (value) {
//this will sort by the length of the first name string
return value.firstName.length;
}
};
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script data-require="angular.js@1.6.x" src="https://code.angularjs.org/1.6.8/angular.js" data-semver="1.6.8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.1.11/smart-table.min.js"></script>
<script src="st-multi-sort.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="container-fluid">
<h1>Probes</h1>
<table st-safe-src="probes" st-table="displayProbes" class="table table-striped">
<thead>
<tr>
<th st-multi-sort="type">Type</th>
<th st-multi-sort="sortByName" st-sort-default="true">Name</th>
<th st-multi-sort="value">Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="probe in displayProbes track by $index">
<td><img src="./img/{{probe.type}}" alt="{{probe.type}}" /></td>
<td>{{probe.name}}</td>
<td>{{probe.value}}</td>
</tr>
</tbody>
</table>
<h2>Second exemple</h2>
<table st-table="rowCollection" class="table table-striped">
<thead>
<tr>
<th st-sort="getters.firstName" st-sort-default="true">first name</th>
<th st-sort="lastName">last name</th>
<th st-sort="birthDate">birth date</th>
<th st-sort="balance">balance</th>
<th>email</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rowCollection">
<td>{{row.firstName | uppercase}}</td>
<td>{{row.lastName}}</td>
<td>{{row.birthDate | date}}</td>
<td>{{row.balance | currency}}</td>
<td><a ng-href="mailto:{{row.email}}">email</a></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
/* Styles go here */
.st-sort-ascent:before {
content: '\25B2';
}
.st-sort-descent:before {
content: '\25BC';
}
(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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.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){
// Generated by CoffeeScript 1.9.2
var compareProperty, dot;
module.exports = function(collection, expressions) {
return collection.sort(function(a, b) {
var expression, i, len, predicate, reverse, value;
for (i = 0, len = expressions.length; i < len; i++) {
expression = expressions[i];
if (typeof expression === 'object') {
predicate = expression.predicate;
reverse = expression.reverse;
} else {
predicate = expression;
}
value = compareProperty(predicate, reverse)(a, b);
if (value !== 0) {
return value;
}
}
});
};
dot = {
get: function(obj, field) {
var i, key, keys, len, value;
keys = field.split('.');
value = obj;
for (i = 0, len = keys.length; i < len; i++) {
key = keys[i];
value = value[key];
}
return value;
},
set: function(obj, field, setValue) {
var allButLastKey, i, key, keys, lastKey, len, value;
keys = field.split('.');
allButLastKey = keys.slice(0, -1);
lastKey = keys[keys.length - 1];
value = obj;
for (i = 0, len = allButLastKey.length; i < len; i++) {
key = allButLastKey[i];
value = value[key] != null ? value[key] : value[key] = {};
}
return value[lastKey] = setValue;
}
};
compareProperty = function(predicate, reverse) {
var getter;
getter = typeof predicate === 'function' ? function(obj) {
return predicate(obj);
} : function(obj) {
return dot.get(obj, predicate);
};
getter;
if (!reverse) {
return function(a, b) {
if (getter(a) < getter(b)) {
return -1;
} else if (getter(a) > getter(b)) {
return 1;
} else {
return 0;
}
};
} else {
return function(a, b) {
if (getter(a) > getter(b)) {
return -1;
} else if (getter(a) < getter(b)) {
return 1;
} else {
return 0;
}
};
}
};
},{}],2:[function(require,module,exports){
var ng;
require('./multi_order_by');
require('./st_element_id');
ng = angular;
angular.module('smart-table').directive('stMultiSort', [
'stConfig', '$parse', '$rootScope', 'stUniqueId', function(stConfig, $parse, $rootScope, stUniqueId) {
return {
restrict: 'A',
require: '^stTable',
link: function(scope, element, attr, ctrl) {
var classAscent, classDescent, elementId, getter, index, predicate, sort, sortDefault, stateClasses;
predicate = attr.stMultiSort;
getter = $parse(predicate);
index = 0;
classAscent = attr.stClassAscent || stConfig.sort.ascentClass;
classDescent = attr.stClassDescent || stConfig.sort.descentClass;
stateClasses = [classAscent, classDescent];
sortDefault = void 0;
elementId = stUniqueId.generate();
/*
Use our custom orderBy filter, which supports reversing rows independently
*/
ctrl.setSortFunction('multiOrderBy');
/*
Sort the rows.
@param {Boolean} holdingShiftKey
*/
sort = function(holdingShiftKey) {
var base, reverse, tableState;
index++;
tableState = ctrl.tableState();
if ((base = tableState.sort).predicate == null) {
base.predicate = [];
}
reverse = index % 2 === 0;
predicate = ng.isFunction(getter(scope)) ? getter(scope) : attr.stMultiSort;
(function() {
var indexOfExistingSort;
indexOfExistingSort = (function() {
var i, ref, sortConfig;
ref = ctrl.tableState().sort.predicate;
for (i in ref) {
sortConfig = ref[i];
if (sortConfig.elementId === elementId) {
return i;
}
}
return -1;
})();
if (indexOfExistingSort !== -1) {
return tableState.sort.predicate.splice(indexOfExistingSort, 1);
}
})();
(function() {
index = index % 2 === 0 ? 2 : 1;
element.removeClass(stateClasses[index % 2]).addClass(stateClasses[index - 1]);
if (!holdingShiftKey) {
return $rootScope.$broadcast('clearOtherSortClasses', elementId);
}
})();
(function() {
if (!holdingShiftKey) {
tableState.sort.predicate.length = 0;
}
return tableState.sort.predicate.push({
elementId: elementId,
predicate: predicate,
reverse: reverse === true
});
})();
tableState.pagination.start = 0;
return ctrl.pipe();
};
if (attr.stSortDefault) {
sortDefault = scope.$eval(attr.stSortDefault) != null ? scope.$eval(attr.stSortDefault) : attr.stSortDefault;
}
if (sortDefault) {
index = sortDefault === 'reverse' ? 1 : 0;
sort();
}
element.bind('click', function(e) {
if (!predicate) {
return;
}
return scope.$apply(function() {
return sort(e.shiftKey || e.ctrlKey);
});
});
return scope.$on('clearOtherSortClasses', function(e, sortedElementId) {
if (sortedElementId !== elementId) {
index = 0;
return element.removeClass(classAscent).removeClass(classDescent);
}
});
}
};
}
]);
},{"./multi_order_by":3,"./st_element_id":4}],3:[function(require,module,exports){
/*
Like angular orderBy filter, but allows reversing each parameter individually (even getters)
*/
angular.module('smart-table').filter('multiOrderBy', function() {
return require('orderby');
});
},{"orderby":1}],4:[function(require,module,exports){
/*
Generate unique ids to identify each sortable element on the page
*/
angular.module('smart-table').factory('stUniqueId', function() {
var id;
id = 0;
return {
generate: function() {
return id++;
}
};
});
},{}]},{},[2])
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvb3JkZXJieS9saWIvaW5kZXguanMiLCIvVXNlcnMvZGFubnluZWxzb24vUHJvamVjdHMvc3QtbXVsdGktc29ydC9zcmMvaW5kZXguY29mZmVlIiwiL1VzZXJzL2Rhbm55bmVsc29uL1Byb2plY3RzL3N0LW11bHRpLXNvcnQvc3JjL211bHRpX29yZGVyX2J5LmNvZmZlZSIsIi9Vc2Vycy9kYW5ueW5lbHNvbi9Qcm9qZWN0cy9zdC1tdWx0aS1zb3J0L3NyYy9zdF9lbGVtZW50X2lkLmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RUEsSUFBQTs7QUFBQSxPQUFBLENBQVEsa0JBQVI7O0FBQ0EsT0FBQSxDQUFRLGlCQUFSOztBQUVBLEVBQUEsR0FBSzs7QUFFTCxPQUFPLENBQUMsTUFBUixDQUFlLGFBQWYsQ0FBNkIsQ0FBQyxTQUE5QixDQUF3QyxhQUF4QyxFQUF1RDtFQUNyRCxVQURxRCxFQUVyRCxRQUZxRCxFQUdyRCxZQUhxRCxFQUlyRCxZ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VUFDaEQsSUFBQSxDQUFBLEVBRkY7O1FBSUEsT0FBTyxDQUFDLElBQVIsQ0FBYSxPQUFiLEVBQXNCLFNBQUMsQ0FBRDtVQUNwQixJQUFBLENBQWMsU0FBZDtBQUFBLG1CQUFBOztpQkFDQSxLQUFLLENBQUMsTUFBTixDQUFhLFNBQUE7bUJBQUcsSUFBQSxDQUFLLENBQUMsQ0FBQyxRQUFGLElBQWMsQ0FBQyxDQUFDLE9BQXJCO1VBQUgsQ0FBYjtRQUZvQixDQUF0QjtlQUlBLEtBQUssQ0FBQyxHQUFOLENBQVUsdUJBQVYsRUFBbUMsU0FBQyxDQUFELEVBQUksZUFBSjtVQUNqQyxJQUFHLGVBQUEsS0FBcUIsU0FBeEI7WUFDRSxLQUFBLEdBQVE7bUJBQ1IsT0FBTyxDQUFDLFdBQVIsQ0FBb0IsV0FBcEIsQ0FBZ0MsQ0FBQyxXQUFqQyxDQUE2QyxZQUE3QyxFQUZGOztRQURpQyxDQUFuQztNQWxFSSxDQUZOOztFQURGLENBTHFEO0NBQXZEOzs7OztBQ0xBOzs7QUFHQSxPQUFPLENBQUMsTUFBUixDQUFlLGFBQWYsQ0FBNkIsQ0FBQyxNQUE5QixDQUFxQyxjQUFyQyxFQUFxRCxTQUFBO1NBQ25ELE9BQUEsQ0FBUSxTQUFSO0FBRG1ELENBQXJEOzs7OztBQ0hBOzs7QUFHQSxPQUFPLENBQUMsTUFBUixDQUFlLGFBQWYsQ0FFQSxDQUFDLE9BRkQsQ0FFUyxZQUZULEVBRXVCLFNBQUE7QUFDckIsTUFBQTtFQUFBLEVBQUEsR0FBSztTQUVMO0lBQ0UsUUFBQSxFQUFVLFNBQUE7YUFBRyxFQUFBO0lBQUgsQ0FEWjs7QUFIcUIsQ0FGdkIiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gR2VuZXJhdGVkIGJ5IENvZmZlZVNjcmlwdCAxLjkuMlxudmFyIGNvbXBhcmVQcm9wZXJ0eSwgZG90O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGV4cHJlc3Npb25zKSB7XG4gIHJldHVybiBjb2xsZWN0aW9uLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgIHZhciBleHByZXNzaW9uLCBpLCBsZW4sIHByZWRpY2F0ZSwgcmV2ZXJzZSwgdmFsdWU7XG4gICAgZm9yIChpID0gMCwgbGVuID0gZXhwcmVzc2lvbnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGV4cHJlc3Npb24gPSBleHByZXNzaW9uc1tpXTtcbiAgICAgIGlmICh0eXBlb2YgZXhwcmVzc2lvbiA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgcHJlZGljYXRlID0gZXhwcmVzc2lvbi5wcmVkaWNhdGU7XG4gICAgICAgIHJldmVyc2UgPSBleHByZXNzaW9uLnJldmVyc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwcmVkaWNhdGUgPSBleHByZXNzaW9uO1xuICAgICAgfVxuICAgICAgdmFsdWUgPSBjb21wYXJlUHJvcGVydHkocHJlZGljYXRlLCByZXZlcnNlKShhLCBiKTtcbiAgICAgIGlmICh2YWx1ZSAhPT0gMCkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn07XG5cbmRvdCA9IHtcbiAgZ2V0OiBmdW5jdGlvbihvYmosIGZpZWxkKSB7XG4gICAgdmFyIGksIGtleSwga2V5cywgbGVuLCB2YWx1ZTtcbiAgICBrZXlzID0gZmllbGQuc3BsaXQoJy4nKTtcbiAgICB2YWx1ZSA9IG9iajtcbiAgICBmb3IgKGkgPSAwLCBsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBrZXkgPSBrZXlzW2ldO1xuICAgICAgdmFsdWUgPSB2YWx1ZVtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH0sXG4gIHNldDogZnVuY3Rpb24ob2JqLCBmaWVsZCwgc2V0VmFsdWUpIHtcbiAgICB2YXIgYWxsQnV0TGFzdEtleSwgaSwga2V5LCBrZXlzLCBsYXN0S2V5LCBsZW4sIHZhbHVlO1xuICAgIGtleXMgPSBmaWVsZC5zcGxpdCgnLicpO1xuICAgIGFsbEJ1dExhc3RLZXkgPSBrZXlzLnNsaWNlKDAsIC0xKTtcbiAgICBsYXN0S2V5ID0ga2V5c1trZXlzLmxlbmd0aCAtIDFdO1xuICAgIHZhbHVlID0gb2JqO1xuICAgIGZvciAoaSA9IDAsIGxlbiA9IGFsbEJ1dExhc3RLZXkubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGtleSA9IGFsbEJ1dExhc3RLZXlbaV07XG4gICAgICB2YWx1ZSA9IHZhbHVlW2tleV0gIT0gbnVsbCA/IHZhbHVlW2tleV0gOiB2YWx1ZVtrZXldID0ge307XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZVtsYXN0S2V5XSA9IHNldFZhbHVlO1xuICB9XG59O1xuXG5jb21wYXJlUHJvcGVydHkgPSBmdW5jdGlvbihwcmVkaWNhdGUsIHJldmVyc2UpIHtcbiAgdmFyIGdldHRlcjtcbiAgZ2V0dGVyID0gdHlwZW9mIHByZWRpY2F0ZSA9PT0gJ2Z1bmN0aW9uJyA/IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBwcmVkaWNhdGUob2JqKTtcbiAgfSA6IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBkb3QuZ2V0KG9iaiwgcHJlZGljYXRlKTtcbiAgfTtcbiAgZ2V0dGVyO1xuICBpZiAoIXJldmVyc2UpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgICAgaWYgKGdldHRlcihhKSA8IGdldHRlcihiKSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9IGVsc2UgaWYgKGdldHRlcihhKSA+IGdldHRlcihiKSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgIGlmIChnZXR0ZXIoYSkgPiBnZXR0ZXIoYikpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIGlmIChnZXR0ZXIoYSkgPCBnZXR0ZXIoYikpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cbiAgICB9O1xuICB9XG59O1xuIiwicmVxdWlyZSAnLi9tdWx0aV9vcmRlcl9ieSdcbnJlcXVpcmUgJy4vc3RfZWxlbWVudF9pZCdcblxubmcgPSBhbmd1bGFyXG5cbmFuZ3VsYXIubW9kdWxlKCdzbWFydC10YWJsZScpLmRpcmVjdGl2ZSAnc3RNdWx0aVNvcnQnLCBbXG4gICdzdENvbmZpZydcbiAgJyRwYXJzZSdcbiAgJyRyb290U2NvcGUnXG4gICdzdFVuaXF1ZUlkJ1xuICAoc3RDb25maWcsICRwYXJzZSwgJHJvb3RTY29wZSwgc3RVbmlxdWVJZCkgLT5cbiAgICByZXN0cmljdDogJ0EnXG4gICAgcmVxdWlyZTogJ15zdFRhYmxlJ1xuICAgIGxpbms6IChzY29wZSwgZWxlbWVudCwgYXR0ciwgY3RybCkgLT5cbiAgICAgIHByZWRpY2F0ZSA9IGF0dHIuc3RNdWx0aVNvcnRcbiAgICAgIGdldHRlciA9ICRwYXJzZShwcmVkaWNhdGUpXG4gICAgICBpbmRleCA9IDBcbiAgICAgIGNsYXNzQXNjZW50ID0gYXR0ci5zdENsYXNzQXNjZW50IG9yIHN0Q29uZmlnLnNvcnQuYXNjZW50Q2xhc3NcbiAgICAgIGNsYXNzRGVzY2VudCA9IGF0dHIuc3RDbGFzc0Rlc2NlbnQgb3Igc3RDb25maWcuc29ydC5kZXNjZW50Q2xhc3NcbiAgICAgIHN0YXRlQ2xhc3NlcyA9IFtcbiAgICAgICAgY2xhc3NBc2NlbnRcbiAgICAgICAgY2xhc3NEZXNjZW50XG4gICAgICBdXG4gICAgICBzb3J0RGVmYXVsdCA9IHVuZGVmaW5lZFxuICAgICAgZWxlbWVudElkID0gc3RVbmlxdWVJZC5nZW5lcmF0ZSgpXG5cbiAgICAgICMjI1xuICAgICAgVXNlIG91ciBjdXN0b20gb3JkZXJCeSBmaWx0ZXIsIHdoaWNoIHN1cHBvcnRzIHJldmVyc2luZyByb3dzIGluZGVwZW5kZW50bHlcbiAgICAgICMjI1xuICAgICAgY3RybC5zZXRTb3J0RnVuY3Rpb24gJ211bHRpT3JkZXJCeSdcblxuICAgICAgIyMjXG4gICAgICBTb3J0IHRoZSByb3dzLlxuICAgICAgQHBhcmFtIHtCb29sZWFufSBob2xkaW5nU2hpZnRLZXlcbiAgICAgICMjI1xuICAgICAgc29ydCA9IChob2xkaW5nU2hpZnRLZXkpIC0+XG4gICAgICAgIGluZGV4KytcbiAgICAgICAgdGFibGVTdGF0ZSA9IGN0cmwudGFibGVTdGF0ZSgpXG4gICAgICAgIHRhYmxlU3RhdGUuc29ydC5wcmVkaWNhdGUgPz0gW11cbiAgICAgICAgcmV2ZXJzZSA9IGluZGV4ICUgMiBpcyAwXG4gICAgICAgIHByZWRpY2F0ZSA9IGlmIG5nLmlzRnVuY3Rpb24oZ2V0dGVyKHNjb3BlKSkgdGhlbiBnZXR0ZXIoc2NvcGUpIGVsc2UgYXR0ci5zdE11bHRpU29ydFxuXG4gICAgICAgIGRvIC0+ICMgY2xlYXIgZXhpc3Rpbmcgc29ydFxuICAgICAgICAgIGluZGV4T2ZFeGlzdGluZ1NvcnQgPSBkbyAtPlxuICAgICAgICAgICAgZm9yIGksIHNvcnRDb25maWcgb2YgY3RybC50YWJsZVN0YXRlKCkuc29ydC5wcmVkaWNhdGVcbiAgICAgICAgICAgICAgaWYgc29ydENvbmZpZy5lbGVtZW50SWQgaXMgZWxlbWVudElkXG4gICAgICAgICAgICAgICAgcmV0dXJuIGlcbiAgICAgICAgICAgIHJldHVybiAtMVxuICAgICAgICAgIGlmIGluZGV4T2ZFeGlzdGluZ1NvcnQgaXNudCAtMVxuICAgICAgICAgICAgdGFibGVTdGF0ZS5zb3J0LnByZWRpY2F0ZS5zcGxpY2UgaW5kZXhPZkV4aXN0aW5nU29ydCwgMVxuXG4gICAgICAgIGRvIC0+ICMgdXBkYXRlIHNvcnQgY2xhc3Nlc1xuICAgICAgICAgIGluZGV4ID0gaWYgaW5kZXggJSAyID09IDAgdGhlbiAyIGVsc2UgMVxuICAgICAgICAgIGVsZW1lbnQucmVtb3ZlQ2xhc3Moc3RhdGVDbGFzc2VzW2luZGV4ICUgMl0pLmFkZENsYXNzIHN0YXRlQ2xhc3Nlc1tpbmRleCAtIDFdXG4gICAgICAgICAgaWYgIWhvbGRpbmdTaGlmdEtleVxuICAgICAgICAgICAgJHJvb3RTY29wZS4kYnJvYWRjYXN0ICdjbGVhck90aGVyU29ydENsYXNzZXMnLCBlbGVtZW50SWRcblxuICAgICAgICBkbyAtPiAjIHVwZGF0ZSBzb3J0XG4gICAgICAgICAgaWYgIWhvbGRpbmdTaGlmdEtleVxuICAgICAgICAgICAgdGFibGVTdGF0ZS5zb3J0LnByZWRpY2F0ZS5sZW5ndGggPSAwO1xuICAgICAgICAgIHRhYmxlU3RhdGUuc29ydC5wcmVkaWNhdGUucHVzaFxuICAgICAgICAgICAgZWxlbWVudElkOiBlbGVtZW50SWRcbiAgICAgICAgICAgIHByZWRpY2F0ZTogcHJlZGljYXRlXG4gICAgICAgICAgICByZXZlcnNlOiByZXZlcnNlID09IHRydWVcblxuICAgICAgICB0YWJsZVN0YXRlLnBhZ2luYXRpb24uc3RhcnQgPSAwXG4gICAgICAgIGN0cmwucGlwZSgpXG5cbiAgICAgIGlmIGF0dHIuc3RTb3J0RGVmYXVsdFxuICAgICAgICBzb3J0RGVmYXVsdCA9IGlmIHNjb3BlLiRldmFsKGF0dHIuc3RTb3J0RGVmYXVsdCk/IHRoZW4gc2NvcGUuJGV2YWwoYXR0ci5zdFNvcnREZWZhdWx0KSBlbHNlIGF0dHIuc3RTb3J0RGVmYXVsdFxuXG4gICAgICBpZiBzb3J0RGVmYXVsdFxuICAgICAgICBpbmRleCA9IGlmIHNvcnREZWZhdWx0ID09ICdyZXZlcnNlJyB0aGVuIDEgZWxzZSAwXG4gICAgICAgIHNvcnQoKVxuXG4gICAgICBlbGVtZW50LmJpbmQgJ2NsaWNrJywgKGUpIC0+XG4gICAgICAgIHJldHVybiB1bmxlc3MgcHJlZGljYXRlXG4gICAgICAgIHNjb3BlLiRhcHBseSAtPiBzb3J0KGUuc2hpZnRLZXkgb3IgZS5jdHJsS2V5KVxuXG4gICAgICBzY29wZS4kb24gJ2NsZWFyT3RoZXJTb3J0Q2xhc3NlcycsIChlLCBzb3J0ZWRFbGVtZW50SWQpIC0+XG4gICAgICAgIGlmIHNvcnRlZEVsZW1lbnRJZCBpc250IGVsZW1lbnRJZFxuICAgICAgICAgIGluZGV4ID0gMFxuICAgICAgICAgIGVsZW1lbnQucmVtb3ZlQ2xhc3MoY2xhc3NBc2NlbnQpLnJlbW92ZUNsYXNzKGNsYXNzRGVzY2VudClcbl1cbiIsIiMjI1xuTGlrZSBhbmd1bGFyIG9yZGVyQnkgZmlsdGVyLCBidXQgYWxsb3dzIHJldmVyc2luZyBlYWNoIHBhcmFtZXRlciBpbmRpdmlkdWFsbHkgKGV2ZW4gZ2V0dGVycylcbiMjI1xuYW5ndWxhci5tb2R1bGUoJ3NtYXJ0LXRhYmxlJykuZmlsdGVyICdtdWx0aU9yZGVyQnknLCAtPlxuICByZXF1aXJlICdvcmRlcmJ5J1xuIiwiIyMjXG5HZW5lcmF0ZSB1bmlxdWUgaWRzIHRvIGlkZW50aWZ5IGVhY2ggc29ydGFibGUgZWxlbWVudCBvbiB0aGUgcGFnZVxuIyMjXG5hbmd1bGFyLm1vZHVsZSgnc21hcnQtdGFibGUnKVxuXG4uZmFjdG9yeSAnc3RVbmlxdWVJZCcsIC0+XG4gIGlkID0gMFxuXG4gIHtcbiAgICBnZW5lcmF0ZTogLT4gaWQrK1xuICB9XG4iXX0=