You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/07/02 10:48:32 UTC
[46/50] [abbrv] incubator-ignite git commit: Merge branches
'ignite-843' and 'ignite-sprint-7' of
https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-843
Merge branches 'ignite-843' and 'ignite-sprint-7' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-843
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/92c06985
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/92c06985
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/92c06985
Branch: refs/heads/ignite-843
Commit: 92c06985426981eb1637a6af16d945ddcbb115e6
Parents: 4a0fd03 872fc38
Author: AKuznetsov <ak...@gridgain.com>
Authored: Thu Jul 2 15:17:58 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Thu Jul 2 15:17:58 2015 +0700
----------------------------------------------------------------------
assembly/dependencies-fabric.xml | 1 +
examples/pom.xml | 2 +-
modules/aop/pom.xml | 2 +-
modules/aws/pom.xml | 2 +-
modules/clients/pom.xml | 2 +-
.../ClientAbstractConnectivitySelfTest.java | 4 +-
modules/cloud/pom.xml | 2 +-
modules/codegen/pom.xml | 2 +-
modules/core/pom.xml | 2 +-
.../apache/ignite/IgniteSystemProperties.java | 3 +
.../org/apache/ignite/cluster/ClusterGroup.java | 18 +-
.../org/apache/ignite/cluster/ClusterNode.java | 2 +
.../configuration/CacheConfiguration.java | 105 +--
.../configuration/IgniteReflectionFactory.java | 81 +-
.../configuration/NearCacheConfiguration.java | 10 +-
.../ignite/internal/GridKernalContextImpl.java | 5 +-
.../ignite/internal/MarshallerContextImpl.java | 12 +-
.../internal/cluster/ClusterGroupAdapter.java | 50 +-
.../cluster/IgniteClusterAsyncImpl.java | 12 +-
.../internal/managers/GridManagerAdapter.java | 8 +-
.../managers/communication/GridIoManager.java | 49 +-
.../discovery/GridDiscoveryManager.java | 62 +-
.../processors/cache/GridCacheContext.java | 2 +-
.../cache/GridCacheDeploymentManager.java | 10 +-
.../GridCachePartitionExchangeManager.java | 7 +-
.../processors/cache/GridCacheProcessor.java | 62 +-
.../processors/cache/GridCacheSwapManager.java | 12 +-
.../processors/cache/IgniteCacheFutureImpl.java | 42 +
.../processors/cache/IgniteCacheProxy.java | 2 +-
.../distributed/dht/GridDhtLocalPartition.java | 3 +-
.../distributed/dht/GridDhtLockFuture.java | 2 +-
.../dht/atomic/GridDhtAtomicCache.java | 9 +-
.../GridDhtPartitionsExchangeFuture.java | 95 ++-
.../continuous/CacheContinuousQueryHandler.java | 8 +
.../processors/clock/GridClockServer.java | 21 +-
.../datastructures/DataStructuresProcessor.java | 64 +-
.../processors/hadoop/HadoopJobInfo.java | 4 +-
.../hadoop/counter/HadoopCounterWriter.java | 5 +-
.../offheap/GridOffHeapProcessor.java | 19 +-
.../processors/plugin/CachePluginManager.java | 10 +-
.../processors/rest/GridRestProcessor.java | 4 +-
.../handlers/task/GridTaskCommandHandler.java | 12 +-
.../processors/task/GridTaskWorker.java | 4 +-
.../internal/util/GridConfigurationFinder.java | 55 +-
.../apache/ignite/internal/util/GridDebug.java | 37 +-
.../ignite/internal/util/IgniteUtils.java | 6 +-
.../internal/util/future/IgniteFutureImpl.java | 18 +-
.../shmem/IpcSharedMemoryServerEndpoint.java | 10 +-
.../util/nio/GridNioMessageTracker.java | 23 +-
.../ignite/internal/util/nio/GridNioServer.java | 64 +-
.../apache/ignite/internal/visor/VisorJob.java | 2 +
.../internal/visor/log/VisorLogSearchTask.java | 2 +-
.../visor/node/VisorNodeDataCollectorJob.java | 4 +
.../visor/query/VisorQueryCleanupTask.java | 14 +
.../util/VisorClusterGroupEmptyException.java | 37 +
.../org/apache/ignite/spi/IgniteSpiAdapter.java | 7 +-
.../org/apache/ignite/spi/IgniteSpiContext.java | 9 +-
.../communication/tcp/TcpCommunicationSpi.java | 104 ++-
.../tcp/TcpCommunicationSpiMBean.java | 19 +
.../ignite/spi/discovery/DiscoverySpi.java | 3 +-
.../ignite/spi/discovery/tcp/ClientImpl.java | 234 ++++--
.../ignite/spi/discovery/tcp/ServerImpl.java | 127 ++-
.../spi/discovery/tcp/TcpDiscoveryImpl.java | 3 +-
.../spi/discovery/tcp/TcpDiscoverySpi.java | 9 +-
.../TcpDiscoveryMulticastIpFinder.java | 74 +-
.../messages/TcpDiscoveryNodeFailedMessage.java | 18 +
.../core/src/main/resources/ignite.properties | 2 +-
.../core/src/test/config/spark/spark-config.xml | 46 ++
modules/core/src/test/config/tests.properties | 6 +-
.../internal/ClusterGroupAbstractTest.java | 777 ++++++++++++++++++
.../internal/ClusterGroupHostsSelfTest.java | 141 ++++
.../ignite/internal/ClusterGroupSelfTest.java | 251 ++++++
.../internal/GridDiscoveryEventSelfTest.java | 12 +-
...ridFailFastNodeFailureDetectionSelfTest.java | 17 +-
.../internal/GridProjectionAbstractTest.java | 784 -------------------
.../ignite/internal/GridProjectionSelfTest.java | 251 ------
.../apache/ignite/internal/GridSelfTest.java | 2 +-
.../IgniteSlowClientDetectionSelfTest.java | 187 +++++
.../IgniteTopologyPrintFormatSelfTest.java | 289 +++++++
.../CacheReadThroughAtomicRestartSelfTest.java | 32 +
...heReadThroughLocalAtomicRestartSelfTest.java | 32 +
.../CacheReadThroughLocalRestartSelfTest.java | 32 +
...dThroughReplicatedAtomicRestartSelfTest.java | 32 +
...cheReadThroughReplicatedRestartSelfTest.java | 32 +
.../cache/CacheReadThroughRestartSelfTest.java | 133 ++++
.../cache/GridCacheAbstractSelfTest.java | 2 +-
.../IgniteDaemonNodeMarshallerCacheTest.java | 192 +++++
...eDynamicCacheStartNoExchangeTimeoutTest.java | 466 +++++++++++
.../cache/IgniteDynamicCacheStartSelfTest.java | 37 +
...GridCacheQueueMultiNodeAbstractSelfTest.java | 4 +-
.../GridCacheSetAbstractSelfTest.java | 22 +-
.../IgniteDataStructureWithJobTest.java | 111 +++
.../distributed/IgniteCache150ClientsTest.java | 189 +++++
...teCacheClientNodePartitionsExchangeTest.java | 1 +
.../distributed/IgniteCacheManyClientsTest.java | 1 +
...idCacheNearOnlyMultiNodeFullApiSelfTest.java | 5 -
...achePartitionedMultiNodeFullApiSelfTest.java | 53 +-
.../GridCacheReplicatedFailoverSelfTest.java | 5 +
.../IgniteCacheTxStoreSessionTest.java | 4 +
.../internal/util/IgniteUtilsSelfTest.java | 22 +
.../GridP2PContinuousDeploymentSelfTest.java | 2 -
.../GridTcpCommunicationSpiConfigSelfTest.java | 1 -
.../tcp/TcpClientDiscoverySpiSelfTest.java | 265 ++++++-
.../testframework/GridSpiTestContext.java | 7 +-
.../testframework/junits/GridAbstractTest.java | 2 +-
.../ignite/testsuites/IgniteBasicTestSuite.java | 8 +-
.../IgniteCacheDataStructuresSelfTestSuite.java | 1 +
.../testsuites/IgniteCacheTestSuite4.java | 8 +
.../testsuites/IgniteClientTestSuite.java | 38 +
.../testsuites/IgniteKernalSelfTestSuite.java | 1 +
modules/core/src/test/resources/helloworld.gar | Bin 6092 -> 0 bytes
modules/core/src/test/resources/helloworld1.gar | Bin 6092 -> 0 bytes
modules/core/src/test/resources/readme.txt | 6 -
modules/docker/Dockerfile | 55 ++
modules/docker/README.txt | 11 +
modules/docker/build_users_libs.sh | 39 +
modules/docker/download_ignite.sh | 49 ++
modules/docker/execute.sh | 62 ++
modules/docker/run.sh | 34 +
modules/extdata/p2p/pom.xml | 4 +-
.../p2p/GridP2PContinuousDeploymentTask1.java | 2 +-
modules/extdata/uri/META-INF/ignite.xml | 38 +
.../extdata/uri/modules/uri-dependency/pom.xml | 42 +
.../deployment/uri/tasks/GarHelloWorldBean.java | 60 ++
.../src/main/resources/gar-example.properties | 18 +
modules/extdata/uri/pom.xml | 62 +-
.../deployment/uri/tasks/GarHelloWorldTask.java | 81 ++
.../deployment/uri/tasks/gar-spring-bean.xml | 29 +
modules/gce/pom.xml | 2 +-
modules/geospatial/pom.xml | 2 +-
modules/hadoop/pom.xml | 80 +-
.../fs/IgniteHadoopFileSystemCounterWriter.java | 9 +-
.../processors/hadoop/HadoopClassLoader.java | 29 +
.../processors/hadoop/HadoopDefaultJobInfo.java | 27 +-
.../internal/processors/hadoop/HadoopUtils.java | 237 ------
.../hadoop/SecondaryFileSystemProvider.java | 3 +-
.../hadoop/fs/HadoopFileSystemCacheUtils.java | 241 ++++++
.../hadoop/fs/HadoopFileSystemsUtils.java | 11 +
.../hadoop/fs/HadoopLazyConcurrentMap.java | 5 +
.../hadoop/jobtracker/HadoopJobTracker.java | 25 +-
.../child/HadoopChildProcessRunner.java | 3 +-
.../processors/hadoop/v2/HadoopV2Job.java | 84 +-
.../hadoop/v2/HadoopV2JobResourceManager.java | 22 +-
.../hadoop/v2/HadoopV2TaskContext.java | 37 +-
.../apache/ignite/igfs/IgfsEventsTestSuite.java | 5 +-
.../processors/hadoop/HadoopMapReduceTest.java | 2 +-
.../processors/hadoop/HadoopTasksV1Test.java | 7 +-
.../processors/hadoop/HadoopTasksV2Test.java | 7 +-
.../processors/hadoop/HadoopV2JobSelfTest.java | 6 +-
.../collections/HadoopAbstractMapTest.java | 3 +-
.../testsuites/IgniteHadoopTestSuite.java | 2 +-
.../IgniteIgfsLinuxAndMacOSTestSuite.java | 3 +-
modules/hibernate/pom.xml | 2 +-
modules/indexing/pom.xml | 2 +-
.../processors/query/h2/IgniteH2Indexing.java | 2 +
.../query/h2/twostep/GridMapQueryExecutor.java | 23 +-
.../cache/IgniteCacheOffheapEvictQueryTest.java | 196 +++++
.../IgniteCacheQuerySelfTestSuite.java | 1 +
modules/jcl/pom.xml | 2 +-
modules/jta/pom.xml | 2 +-
.../cache/jta/GridCacheXAResource.java | 18 +-
.../processors/cache/GridCacheJtaSelfTest.java | 2 +-
modules/log4j/pom.xml | 2 +-
modules/mesos/pom.xml | 2 +-
modules/rest-http/pom.xml | 2 +-
modules/scalar-2.10/pom.xml | 2 +-
modules/scalar/pom.xml | 2 +-
modules/schedule/pom.xml | 2 +-
modules/schema-import/pom.xml | 2 +-
.../ignite/schema/model/PojoDescriptor.java | 2 +
.../apache/ignite/schema/model/PojoField.java | 1 +
.../parser/dialect/OracleMetadataDialect.java | 2 +-
modules/slf4j/pom.xml | 2 +-
modules/spark-2.10/pom.xml | 2 +-
modules/spark/pom.xml | 2 +-
.../org/apache/ignite/spark/IgniteContext.scala | 50 +-
.../org/apache/ignite/spark/IgniteRddSpec.scala | 18 +
modules/spring/pom.xml | 2 +-
modules/ssh/pom.xml | 2 +-
modules/tools/pom.xml | 2 +-
modules/urideploy/pom.xml | 2 +-
.../GridTaskUriDeploymentDeadlockSelfTest.java | 13 +-
.../ignite/p2p/GridP2PDisabledSelfTest.java | 2 +-
modules/visor-console-2.10/pom.xml | 2 +-
modules/visor-console/pom.xml | 2 +-
.../commands/cache/VisorCacheCommand.scala | 7 +-
modules/visor-plugins/pom.xml | 2 +-
modules/web/pom.xml | 2 +-
modules/webconfig/nodejs/views/error.jade | 22 -
.../ignite/webconfig/server/HelloServlet.java | 12 +
.../main/webapp/WEB-INF/applicationContext.xml | 53 --
.../src/main/webapp/WEB-INF/main-servlet.xml | 10 -
modules/webconfig/src/main/webapp/caches.html | 491 ++++++++++++
modules/webconfig/src/main/webapp/clients.html | 86 ++
modules/webconfig/src/main/webapp/clusters.html | 493 ++++++++++++
modules/webconfig/src/main/webapp/css/home.css | 34 -
modules/webconfig/src/main/webapp/css/login.css | 217 -----
modules/webconfig/src/main/webapp/home.html | 26 -
.../webconfig/src/main/webapp/images/docker.png | Bin 0 -> 994 bytes
.../webconfig/src/main/webapp/images/java.png | Bin 0 -> 170 bytes
.../webconfig/src/main/webapp/images/logo.png | Bin 0 -> 8148 bytes
.../webconfig/src/main/webapp/images/xml.png | Bin 0 -> 232 bytes
modules/webconfig/src/main/webapp/index.html | 76 ++
modules/webconfig/src/main/webapp/js/home.js | 20 -
modules/webconfig/src/main/webapp/js/login.js | 170 ----
.../src/main/webapp/layout-sidebar.html | 80 ++
modules/webconfig/src/main/webapp/layout.html | 61 ++
modules/webconfig/src/main/webapp/login.html | 74 +-
.../webconfig/src/main/webapp/persistence.html | 377 +++++++++
modules/webconfig/src/main/webapp/sql.html | 66 ++
.../src/main/webapp/stylesheets/style.css | 1 +
modules/webconfig/src/main/webapp/summary.html | 142 ++++
modules/yardstick/pom.xml | 2 +-
pom.xml | 14 +-
scripts/git-patch-prop.sh | 2 +-
215 files changed, 8013 insertions(+), 2558 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/92c06985/modules/webconfig/src/main/java/org/apache/ignite/webconfig/server/HelloServlet.java
----------------------------------------------------------------------
diff --cc modules/webconfig/src/main/java/org/apache/ignite/webconfig/server/HelloServlet.java
index 0000000,0000000..efc7ef5
new file mode 100644
--- /dev/null
+++ b/modules/webconfig/src/main/java/org/apache/ignite/webconfig/server/HelloServlet.java
@@@ -1,0 -1,0 +1,12 @@@
++package org.apache.ignite.webconfig.server;
++
++public class HelloServlet extends HttpServlet
++{
++ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
++ {
++ response.setContentType("text/html");
++ response.setStatus(HttpServletResponse.SC_OK);
++ response.getWriter().println("<h1>Hello Servlet</h1>");
++ response.getWriter().println("session=" + request.getSession(true).getId());
++ }
++}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/92c06985/modules/webconfig/src/main/webapp/caches.html
----------------------------------------------------------------------
diff --cc modules/webconfig/src/main/webapp/caches.html
index 0000000,0000000..150e5a6
new file mode 100644
--- /dev/null
+++ b/modules/webconfig/src/main/webapp/caches.html
@@@ -1,0 -1,0 +1,491 @@@
++<!DOCTYPE html>
++<html ng-app="ignite-web-configurator">
++ <head>
++ <title></title>
++ <!-- Bootstrap-->
++ <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css">
++ <!-- Font Awesome Icons-->
++ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css">
++ <!-- Font-->
++ <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif">
++ <link rel="stylesheet" href="/stylesheets/style.css">
++ <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
++ <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-sanitize.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.2.2/angular-strap.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.2.2/angular-strap.tpl.min.js"></script>
++ <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js"></script>
++ <script src="/javascripts/controllers/common.js"></script>
++ <script src="/javascripts/dataStructures.js"></script>
++ <script src="/javascripts/bundle.js"></script>
++ <script src="/javascripts/controllers/caches.js"></script>
++ </head>
++ <body class="theme-line body-overlap">
++ <div class="wrapper">
++ <header id="header" class="header">
++ <div class="container">
++ <h1 class="navbar-brand"><a href="/">Apache Ignite Web Configurator</a></h1>
++ <div ng-controller="auth" class="navbar-collapse collapse">
++ <ul ng-controller="activeLink" class="nav navbar-nav">
++ <li><a ng-class="{active: isActive('/clusters')}" href="/clusters">Configuration</a></li>
++ <li><a ng-class="{active: isActive('/sql')}" href="/sql">SQL</a></li>
++ </ul>
++ <ul ng-init="user = undefined" class="nav navbar-nav pull-right">
++ <li ng-show="user"><a data-toggle="dropdown" aria-expanded="true" bs-dropdown data-template="user-dropdown" data-placement="bottom-right" class="dropdown-toggle">{{user.username}}<span class="caret"></span></a>
++ <script id="user-dropdown" type="text/ng-template">
++ <ul class="dropdown-menu">
++ <li><a href="/rest/auth/logout">Log Out</a></li>
++ </ul>
++ </script>
++ </li>
++ <li ng-show="!user" class="nav-login"><a ng-click="login()" href="#">Log In</a></li>
++ </ul>
++ </div>
++ </div>
++ </header>
++ <div class="container body-container">
++ <div class="main-content">
++ <div class="main-head">
++ <div class="row">
++ <div class="col-sm-2 border-right section-left greedy">
++ <div class="sidebar-nav">
++ <ul ng-controller="activeLink" class="menu">
++ <li><a ng-class="{active: isActive('/clusters')}" href="/clusters">Clusters</a></li>
++ <li><a ng-class="{active: isActive('/caches')}" href="/caches">Caches</a></li>
++ <li><a ng-class="{active: isActive('/persistence')}" href="/persistence">Persistence</a></li>
++ <li><a ng-class="{active: isActive('/clients')}" href="/clients">Clients</a></li>
++ <li>
++ <p></p><a ng-class="{active: isActive('/summary')}" href="/summary">Summary</a>
++ </li>
++ </ul>
++ </div>
++ </div>
++ <div class="col-sm-10 border-left section-right">
++ <div class="docs-content">
++ <div class="docs-header">
++ <h1>Caches</h1>
++ <p>Create and configure Ignite caches.</p>
++ <hr>
++ </div>
++ <div ng-controller="cachesController" class="docs-body">
++ <div ng-hide="caches.length == 0" class="links">
++ <table st-table="caches" class="col-sm-12">
++ <tbody>
++ <tr ng-repeat="row in caches track by row._id">
++ <td ng-class="{active: row._id == selectedItem._id}" class="col-sm-6"><a ng-click="selectItem(row)">{{$index + 1}}. {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}}, {{row.atomicityMode | displayValue:atomicities:'Cache atomicity not set'}}</a></td>
++ </tr>
++ </tbody>
++ </table>
++ </div>
++ <button ng-click="createItem()" class="btn btn-primary">Add cache</button>
++ <hr>
++ <form name="inputForm" ng-if="backupItem" novalidate class="form-horizontal">
++ <div bs-collapse data-start-collapsed="false">
++ <div class="panel panel-default">
++ <div class="panel-heading">
++ <h3><a bs-collapse-toggle>General</a></h3>
++ </div>
++ <div bs-collapse-target class="panel-collapse">
++ <div class="panel-body">
++ <div ng-repeat="field in general" class="settings-row">
++ <div ng-switch="field.type">
++ <div ng-switch-when="check" class="checkbox col-sm-6">
++ <label>
++ <input type="checkbox" ng-model="getModel(backupItem, field.path)[field.model]"/>{{field.label}}<i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!field.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </label>
++ </div>
++ <div ng-switch-when="text">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" placeholder="{{field.placeholder}}" ng-required="field.required" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="password">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="password" placeholder="{{field.placeholder}}" ng-required="field.required" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="number">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input name="{{field.model}}" type="number" placeholder="{{field.placeholder}}" min="{{field.min ? field.min : 0}}" max="{{field.max ? field.max : Number.MAX_VALUE}}" ng-required="field.required" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"/><i ng-show="inputForm["{{field.model}}"].$error.min" bs-tooltip="bs-tooltip" data-title="Value is less than allowable minimum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{field.model}}"].$error.max" bs-tooltip="bs-tooltip" data-title="Value is more than allowable maximum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{field.model}}"].$error.number" bs-tooltip="bs-tooltip" data-title="Invalid value. Only numbers allowed." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" ng-required="field.required" data-placeholder="{{field.placeholder}}" bs-options="item.value as item.label for item in {{field.items}}" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"></button>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown-multiple">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" ng-disabled="{{field.items}}.length == 0" data-multiple="1" data-placeholder="{{field.placeholder}}" bs-options="item.value as item.label for item in {{field.items}}" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"></button>
++ </div>
++ </div><a ng-show="field.addLink" ng-href="{{field.addLink.ref}}" class="customize">{{field.addLink.label}}</a>
++ </div>
++ <div ng-switch-when="dropdown-details">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" ng-required="field.required" data-placeholder="{{field.placeholder}}" bs-options="item.value as item.label for item in {{field.items}}" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"></button>
++ </div>
++ </div><a ng-show="getModel(backupItem, field.path)[field.model] && field.details[getModel(backupItem, field.path)[field.model]].fields" ng-click="field.details[getModel(backupItem, field.path)[field.model]].expanded = !field.details[getModel(backupItem, field.path)[field.model]].expanded" class="customize">{{field.details[getModel(backupItem, field.path)[field.model]].expanded ? "Hide settings" : "Show settings"}}</a>
++ <div ng-show="field.details[getModel(backupItem, field.path)[field.model]].expanded && getModel(backupItem, field.path)[field.model]" class="col-sm-6 panel-details">
++ <div ng-repeat="detail in field.details[getModel(backupItem, field.path)[field.model]].fields" class="details-row">
++ <div ng-switch="detail.type">
++ <div ng-switch-when="check" class="checkbox">
++ <label>
++ <input type="checkbox" ng-model="getModel(backupItem, detail.path)[detail.model]"/>{{detail.label}}<i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </label>
++ </div>
++ <div ng-switch-when="text">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8"><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" placeholder="{{detail.placeholder}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="number">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8"><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input name="{{detail.model}}" type="number" placeholder="{{detail.placeholder}}" min="{{detail.min ? detail.min : 0}}" max="{{detail.max ? detail.max : Number.MAX_VALUE}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"/><i ng-show="inputForm["{{detail.model}}"].$error.min" bs-tooltip="bs-tooltip" data-title="Value is less than allowable minimum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{detail.model}}"].$error.max" bs-tooltip="bs-tooltip" data-title="Value is more than allowable maximum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{detail.model}}"].$error.number" bs-tooltip="bs-tooltip" data-title="Invalid value. Only numbers allowed." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8"><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" data-placeholder="{{detail.placeholder}}" bs-options="item.value as item.label for item in {{detail.items}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"></button>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown-multiple">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8">
++ <button bs-select="bs-select" data-multiple="1" data-placeholder="{{detail.placeholder}}" bs-options="item.value as item.label for item in {{detail.items}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"></button>
++ </div><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ </div>
++ <div ng-switch-when="table-simple" style="margin-right: 5px; margin-top: -0.65em" ng-model="getModel(backupItem, detail.path)[detail.model]">
++ <table st-table="getModel(backupItem, detail.path)[detail.model]" ng-show="getModel(backupItem, detail.path)[detail.model].length > 0" class="col-sm-12 links-edit">
++ <tbody>
++ <tr ng-repeat="item in getModel(backupItem, detail.path)[detail.model] track by $index">
++ <td class="col-sm-11">
++ <div ng-show="detail.editIdx != {{$index}}"><a ng-click="detail.editIdx = $index; curValue = getModel(backupItem, detail.path)[detail.model][$index]">{{$index + 1}}) {{item}}</a><i ng-click="detail.editIdx = -1; getModel(backupItem, detail.path)[detail.model].splice($index, 1)" class="tipField fa fa-remove"></i></div>
++ <div ng-show="detail.editIdx == {{$index}}">
++ <label class="labelField">{{$index + 1}})</label><i ng-click="detail.editIdx = -1; getModel(backupItem, detail.path)[detail.model][$index]=curValue" class="tipField fa fa-floppy-o"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="curValue" placeholder="{{detail.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </td>
++ <td ng-if="detail.reordering" class="col-sm-1"><i ng-show="$index > 0" ng-click="swapSimpleItems(detailMdl, $index, $index - 1); detail.editIdx = -1;" class="fa fa-arrow-up"></i><i ng-show="$index < getModel(backupItem, detail.path)[detail.model].length - 1" ng-click="swapSimpleItems(getModel(backupItem, detail.path)[detail.model], $index, $index + 1); detail.editIdx = -1;" class="fa fa-arrow-down"></i></td>
++ </tr>
++ </tbody>
++ </table>
++ <button ng-disabled="!newValue || getModel(backupItem, detail.path)[detail.model].indexOf(newValue) >= 0" ng-click="detail.editIdx = -1; getModel(backupItem, detail.path)[detail.model] ? getModel(backupItem, detail.path)[detail.model].push(newValue) : getModel(backupItem, detail.path)[detail.model] = [newValue];" class="btn btn-primary fieldButton">Add</button><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="newValue" ng-focus="detail.editIdx = -1" placeholder="{{detail.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="table-simple" ng-model="getModel(backupItem, field.path)[field.model]">
++ <div>
++ <label>{{field.tableLabel}}: {{getModel(backupItem, field.path)[field.model].length}}</label><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!field.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </div>
++ <table st-table="getModel(backupItem, field.path)[field.model]" ng-show="getModel(backupItem, field.path)[field.model].length > 0" class="links-edit col-sm-12">
++ <tbody>
++ <tr ng-repeat="item in getModel(backupItem, field.path)[field.model] track by $index" class="col-sm-12">
++ <td class="col-sm-6">
++ <div ng-show="field.editIdx != {{$index}}"><a ng-click="field.editIdx = $index; curValue = getModel(backupItem, field.path)[field.model][$index]">{{$index + 1}}) {{item | compact}}</a><i ng-click="field.editIdx = -1; getModel(backupItem, field.path)[field.model].splice($index, 1)" class="tipField fa fa-remove"></i></div>
++ <div ng-show="field.editIdx == {{$index}}">
++ <label class="labelField">{{$index + 1}})</label><i ng-click="field.editIdx = -1; getModel(backupItem, field.path)[field.model][$index]=curValue" class="tipField fa fa-floppy-o"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="curValue" placeholder="{{field.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </td>
++ <td ng-if="field.reordering" class="col-sm-1"><i ng-show="$index > 0" ng-click="swapSimpleItems(fieldMdl, $index, $index - 1); field.editIdx = -1;" class="fa fa-arrow-up"></i><i ng-show="$index < getModel(backupItem, field.path)[field.model].length - 1" ng-click="swapSimpleItems(getModel(backupItem, field.path)[field.model], $index, $index + 1); field.editIdx = -1;" class="fa fa-arrow-down"></i></td>
++ </tr>
++ </tbody>
++ </table>
++ <div class="col-sm-6">
++ <button ng-disabled="!newValue || getModel(backupItem, field.path)[field.model].indexOf(newValue) >= 0" ng-click="field.editIdx = -1; getModel(backupItem, field.path)[field.model] ? getModel(backupItem, field.path)[field.model].push(newValue) : getModel(backupItem, field.path)[field.model] = [newValue];" class="btn btn-primary fieldButton">Add</button><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="newValue" ng-focus="field.editIdx = -1" placeholder="{{field.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="indexedTypes">
++ <div>
++ <label>Indexed types: {{backupItem.indexedTypes.length}}</label><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!field.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </div>
++ <table st-table="backupItem.indexedTypes" ng-show="backupItem.indexedTypes.length > 0" class="links-edit col-sm-12">
++ <tbody>
++ <tr ng-repeat="item in backupItem.indexedTypes" class="col-sm-12">
++ <td class="col-sm-6">
++ <div ng-show="field.editIdx != {{$index}}"><a ng-click="field.editIdx = $index; curKeyClass = backupItem.indexedTypes[$index].keyClass; curValueClass = backupItem.indexedTypes[$index].valueClass">{{$index + 1}}) {{item.keyClass}} / {{item.valueClass}}</a><i ng-click="field.editIdx = -1; backupItem.indexedTypes.splice($index, 1)" class="tipField fa fa-remove"></i></div>
++ <div ng-show="field.editIdx == {{$index}}">
++ <label class="labelField">{{$index + 1}})</label><i ng-click="field.editIdx = -1; backupItem.indexedTypes[$index]={keyClass: curKeyClass, valueClass: curValueClass}" class="tipField fa fa-floppy-o"></i>
++ <div class="input-tip">
++ <div class="col-sm-12">
++ <input type="text" ng-model="curKeyClass" placeholder="Key class full name" class="form-control table-form-control"/>
++ <label> / </label>
++ <input type="text" ng-model="curValueClass" placeholder="Value class full name" class="form-control table-form-control"/>
++ </div>
++ </div>
++ </div>
++ </td>
++ </tr>
++ </tbody>
++ </table>
++ <div class="col-sm-6">
++ <input type="text" ng-model="newKeyClass" ng-focus="field.editIdx = -1" placeholder="Key class full name" class="form-control"/>
++ <div class="settings-row">
++ <input type="text" ng-model="newValueClass" ng-focus="field.editIdx = -1" placeholder="Value class full name" class="form-control"/>
++ </div>
++ <button ng-click="field.editIdx = -1; addIndexedTypes(newKeyClass, newValueClass)" class="btn btn-primary fieldButton">Add</button>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ <div bs-collapse data-start-collapsed="true">
++ <div ng-show="expanded" class="panel-title">
++ <h3><a bs-collapse-toggle="0" ng-click="expanded = !expanded;">{{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}</a></h3>
++ </div>
++ <div bs-collapse-target class="panel-collapse">
++ <div bs-collapse data-start-collapsed="true" data-allow-multiple="true" class="span">
++ <div ng-repeat="group in advanced" class="panel panel-default">
++ <div class="panel-heading">
++ <h3><a bs-collapse-toggle>{{group.label}}</a><i ng-if="group.tip" bs-tooltip="joinTip(group.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!group.tip" class="tipLabel fa fa-question-circle blank"></i></h3>
++ </div>
++ <div bs-collapse-target class="panel-collapse">
++ <div class="panel-body">
++ <div ng-repeat="field in group.fields" class="settings-row">
++ <div ng-switch="field.type">
++ <div ng-switch-when="check" class="checkbox col-sm-6">
++ <label>
++ <input type="checkbox" ng-model="getModel(backupItem, field.path)[field.model]"/>{{field.label}}<i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!field.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </label>
++ </div>
++ <div ng-switch-when="text">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" placeholder="{{field.placeholder}}" ng-required="field.required" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="password">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="password" placeholder="{{field.placeholder}}" ng-required="field.required" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="number">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input name="{{field.model}}" type="number" placeholder="{{field.placeholder}}" min="{{field.min ? field.min : 0}}" max="{{field.max ? field.max : Number.MAX_VALUE}}" ng-required="field.required" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"/><i ng-show="inputForm["{{field.model}}"].$error.min" bs-tooltip="bs-tooltip" data-title="Value is less than allowable minimum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{field.model}}"].$error.max" bs-tooltip="bs-tooltip" data-title="Value is more than allowable maximum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{field.model}}"].$error.number" bs-tooltip="bs-tooltip" data-title="Invalid value. Only numbers allowed." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" ng-required="field.required" data-placeholder="{{field.placeholder}}" bs-options="item.value as item.label for item in {{field.items}}" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"></button>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown-multiple">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" ng-disabled="{{field.items}}.length == 0" data-multiple="1" data-placeholder="{{field.placeholder}}" bs-options="item.value as item.label for item in {{field.items}}" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"></button>
++ </div>
++ </div><a ng-show="field.addLink" ng-href="{{field.addLink.ref}}" class="customize">{{field.addLink.label}}</a>
++ </div>
++ <div ng-switch-when="dropdown-details">
++ <label ng-class="{required: field.required}" class="col-sm-2">{{field.label}}:</label>
++ <div class="col-sm-4"><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" ng-required="field.required" data-placeholder="{{field.placeholder}}" bs-options="item.value as item.label for item in {{field.items}}" class="form-control" ng-model="getModel(backupItem, field.path)[field.model]"></button>
++ </div>
++ </div><a ng-show="getModel(backupItem, field.path)[field.model] && field.details[getModel(backupItem, field.path)[field.model]].fields" ng-click="field.details[getModel(backupItem, field.path)[field.model]].expanded = !field.details[getModel(backupItem, field.path)[field.model]].expanded" class="customize">{{field.details[getModel(backupItem, field.path)[field.model]].expanded ? "Hide settings" : "Show settings"}}</a>
++ <div ng-show="field.details[getModel(backupItem, field.path)[field.model]].expanded && getModel(backupItem, field.path)[field.model]" class="col-sm-6 panel-details">
++ <div ng-repeat="detail in field.details[getModel(backupItem, field.path)[field.model]].fields" class="details-row">
++ <div ng-switch="detail.type">
++ <div ng-switch-when="check" class="checkbox">
++ <label>
++ <input type="checkbox" ng-model="getModel(backupItem, detail.path)[detail.model]"/>{{detail.label}}<i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </label>
++ </div>
++ <div ng-switch-when="text">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8"><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" placeholder="{{detail.placeholder}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="number">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8"><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input name="{{detail.model}}" type="number" placeholder="{{detail.placeholder}}" min="{{detail.min ? detail.min : 0}}" max="{{detail.max ? detail.max : Number.MAX_VALUE}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"/><i ng-show="inputForm["{{detail.model}}"].$error.min" bs-tooltip="bs-tooltip" data-title="Value is less than allowable minimum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{detail.model}}"].$error.max" bs-tooltip="bs-tooltip" data-title="Value is more than allowable maximum." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i><i ng-show="inputForm["{{detail.model}}"].$error.number" bs-tooltip="bs-tooltip" data-title="Invalid value. Only numbers allowed." type="button" class="fa fa-exclamation-triangle form-control-feedback"></i>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8"><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <button bs-select="bs-select" data-placeholder="{{detail.placeholder}}" bs-options="item.value as item.label for item in {{detail.items}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"></button>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="dropdown-multiple">
++ <label class="col-sm-4 details-label">{{detail.label}}:</label>
++ <div class="col-sm-8">
++ <button bs-select="bs-select" data-multiple="1" data-placeholder="{{detail.placeholder}}" bs-options="item.value as item.label for item in {{detail.items}}" class="form-control" ng-model="getModel(backupItem, detail.path)[detail.model]"></button>
++ </div><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ </div>
++ <div ng-switch-when="table-simple" style="margin-right: 5px; margin-top: -0.65em" ng-model="getModel(backupItem, detail.path)[detail.model]">
++ <table st-table="getModel(backupItem, detail.path)[detail.model]" ng-show="getModel(backupItem, detail.path)[detail.model].length > 0" class="col-sm-12 links-edit">
++ <tbody>
++ <tr ng-repeat="item in getModel(backupItem, detail.path)[detail.model] track by $index">
++ <td class="col-sm-11">
++ <div ng-show="detail.editIdx != {{$index}}"><a ng-click="detail.editIdx = $index; curValue = getModel(backupItem, detail.path)[detail.model][$index]">{{$index + 1}}) {{item}}</a><i ng-click="detail.editIdx = -1; getModel(backupItem, detail.path)[detail.model].splice($index, 1)" class="tipField fa fa-remove"></i></div>
++ <div ng-show="detail.editIdx == {{$index}}">
++ <label class="labelField">{{$index + 1}})</label><i ng-click="detail.editIdx = -1; getModel(backupItem, detail.path)[detail.model][$index]=curValue" class="tipField fa fa-floppy-o"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="curValue" placeholder="{{detail.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </td>
++ <td ng-if="detail.reordering" class="col-sm-1"><i ng-show="$index > 0" ng-click="swapSimpleItems(detailMdl, $index, $index - 1); detail.editIdx = -1;" class="fa fa-arrow-up"></i><i ng-show="$index < getModel(backupItem, detail.path)[detail.model].length - 1" ng-click="swapSimpleItems(getModel(backupItem, detail.path)[detail.model], $index, $index + 1); detail.editIdx = -1;" class="fa fa-arrow-down"></i></td>
++ </tr>
++ </tbody>
++ </table>
++ <button ng-disabled="!newValue || getModel(backupItem, detail.path)[detail.model].indexOf(newValue) >= 0" ng-click="detail.editIdx = -1; getModel(backupItem, detail.path)[detail.model] ? getModel(backupItem, detail.path)[detail.model].push(newValue) : getModel(backupItem, detail.path)[detail.model] = [newValue];" class="btn btn-primary fieldButton">Add</button><i ng-if="detail.tip" bs-tooltip="joinTip(detail.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!detail.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="newValue" ng-focus="detail.editIdx = -1" placeholder="{{detail.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="table-simple" ng-model="getModel(backupItem, field.path)[field.model]">
++ <div>
++ <label>{{field.tableLabel}}: {{getModel(backupItem, field.path)[field.model].length}}</label><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!field.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </div>
++ <table st-table="getModel(backupItem, field.path)[field.model]" ng-show="getModel(backupItem, field.path)[field.model].length > 0" class="links-edit col-sm-12">
++ <tbody>
++ <tr ng-repeat="item in getModel(backupItem, field.path)[field.model] track by $index" class="col-sm-12">
++ <td class="col-sm-6">
++ <div ng-show="field.editIdx != {{$index}}"><a ng-click="field.editIdx = $index; curValue = getModel(backupItem, field.path)[field.model][$index]">{{$index + 1}}) {{item | compact}}</a><i ng-click="field.editIdx = -1; getModel(backupItem, field.path)[field.model].splice($index, 1)" class="tipField fa fa-remove"></i></div>
++ <div ng-show="field.editIdx == {{$index}}">
++ <label class="labelField">{{$index + 1}})</label><i ng-click="field.editIdx = -1; getModel(backupItem, field.path)[field.model][$index]=curValue" class="tipField fa fa-floppy-o"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="curValue" placeholder="{{field.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </td>
++ <td ng-if="field.reordering" class="col-sm-1"><i ng-show="$index > 0" ng-click="swapSimpleItems(fieldMdl, $index, $index - 1); field.editIdx = -1;" class="fa fa-arrow-up"></i><i ng-show="$index < getModel(backupItem, field.path)[field.model].length - 1" ng-click="swapSimpleItems(getModel(backupItem, field.path)[field.model], $index, $index + 1); field.editIdx = -1;" class="fa fa-arrow-down"></i></td>
++ </tr>
++ </tbody>
++ </table>
++ <div class="col-sm-6">
++ <button ng-disabled="!newValue || getModel(backupItem, field.path)[field.model].indexOf(newValue) >= 0" ng-click="field.editIdx = -1; getModel(backupItem, field.path)[field.model] ? getModel(backupItem, field.path)[field.model].push(newValue) : getModel(backupItem, field.path)[field.model] = [newValue];" class="btn btn-primary fieldButton">Add</button><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipField fa fa-question-circle"></i><i ng-if="!field.tip" class="tipField fa fa-question-circle blank"></i>
++ <div class="input-tip">
++ <input type="text" ng-model="newValue" ng-focus="field.editIdx = -1" placeholder="{{field.placeholder}}" class="form-control"/>
++ </div>
++ </div>
++ </div>
++ <div ng-switch-when="indexedTypes">
++ <div>
++ <label>Indexed types: {{backupItem.indexedTypes.length}}</label><i ng-if="field.tip" bs-tooltip="joinTip(field.tip)" type="button" class="tipLabel fa fa-question-circle"></i><i ng-if="!field.tip" class="tipLabel fa fa-question-circle blank"></i>
++ </div>
++ <table st-table="backupItem.indexedTypes" ng-show="backupItem.indexedTypes.length > 0" class="links-edit col-sm-12">
++ <tbody>
++ <tr ng-repeat="item in backupItem.indexedTypes" class="col-sm-12">
++ <td class="col-sm-6">
++ <div ng-show="field.editIdx != {{$index}}"><a ng-click="field.editIdx = $index; curKeyClass = backupItem.indexedTypes[$index].keyClass; curValueClass = backupItem.indexedTypes[$index].valueClass">{{$index + 1}}) {{item.keyClass}} / {{item.valueClass}}</a><i ng-click="field.editIdx = -1; backupItem.indexedTypes.splice($index, 1)" class="tipField fa fa-remove"></i></div>
++ <div ng-show="field.editIdx == {{$index}}">
++ <label class="labelField">{{$index + 1}})</label><i ng-click="field.editIdx = -1; backupItem.indexedTypes[$index]={keyClass: curKeyClass, valueClass: curValueClass}" class="tipField fa fa-floppy-o"></i>
++ <div class="input-tip">
++ <div class="col-sm-12">
++ <input type="text" ng-model="curKeyClass" placeholder="Key class full name" class="form-control table-form-control"/>
++ <label> / </label>
++ <input type="text" ng-model="curValueClass" placeholder="Value class full name" class="form-control table-form-control"/>
++ </div>
++ </div>
++ </div>
++ </td>
++ </tr>
++ </tbody>
++ </table>
++ <div class="col-sm-6">
++ <input type="text" ng-model="newKeyClass" ng-focus="field.editIdx = -1" placeholder="Key class full name" class="form-control"/>
++ <div class="settings-row">
++ <input type="text" ng-model="newValueClass" ng-focus="field.editIdx = -1" placeholder="Value class full name" class="form-control"/>
++ </div>
++ <button ng-click="field.editIdx = -1; addIndexedTypes(newKeyClass, newValueClass)" class="btn btn-primary fieldButton">Add</button>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ <div class="panel-title">
++ <h3><a bs-collapse-toggle="0" ng-click="expanded = !expanded;">{{expanded ? 'Hide advanced settings...' : 'Show advanced settings...'}}</a></h3>
++ </div>
++ </div>
++ <button id="save-btn" ng-disabled="inputForm.$invalid" ng-click="saveItem()" class="btn btn-primary">Save</button>
++ <button ng-show="backupItem._id" ng-click="removeItem()" class="btn btn-primary btn-second">Remove</button>
++ </form>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ <div class="container container-footer">
++ <footer>
++ <center>
++ <p>Powered by<a href="http://ignite.incubator.apache.org"> Apache Ignite</a>, version 1.1.0</p>
++ </center>
++ </footer>
++ </div>
++ </div>
++ </body>
++</html>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/92c06985/modules/webconfig/src/main/webapp/clients.html
----------------------------------------------------------------------
diff --cc modules/webconfig/src/main/webapp/clients.html
index 0000000,0000000..05daf87
new file mode 100644
--- /dev/null
+++ b/modules/webconfig/src/main/webapp/clients.html
@@@ -1,0 -1,0 +1,86 @@@
++<!DOCTYPE html>
++<html ng-app="ignite-web-configurator">
++ <head>
++ <title></title>
++ <!-- Bootstrap-->
++ <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.css">
++ <!-- Font Awesome Icons-->
++ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css">
++ <!-- Font-->
++ <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto+Slab:700:serif|Roboto+Slab:400:serif">
++ <link rel="stylesheet" href="/stylesheets/style.css">
++ <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
++ <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-sanitize.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.2.2/angular-strap.js"></script>
++ <script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.2.2/angular-strap.tpl.min.js"></script>
++ <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js"></script>
++ <script src="/javascripts/controllers/common.js"></script>
++ <script src="/javascripts/dataStructures.js"></script>
++ <script src="/javascripts/bundle.js"></script>
++ </head>
++ <body class="theme-line body-overlap">
++ <div class="wrapper">
++ <header id="header" class="header">
++ <div class="container">
++ <h1 class="navbar-brand"><a href="/">Apache Ignite Web Configurator</a></h1>
++ <div ng-controller="auth" class="navbar-collapse collapse">
++ <ul ng-controller="activeLink" class="nav navbar-nav">
++ <li><a ng-class="{active: isActive('/clusters')}" href="/clusters">Configuration</a></li>
++ <li><a ng-class="{active: isActive('/sql')}" href="/sql">SQL</a></li>
++ </ul>
++ <ul ng-init="user = undefined" class="nav navbar-nav pull-right">
++ <li ng-show="user"><a data-toggle="dropdown" aria-expanded="true" bs-dropdown data-template="user-dropdown" data-placement="bottom-right" class="dropdown-toggle">{{user.username}}<span class="caret"></span></a>
++ <script id="user-dropdown" type="text/ng-template">
++ <ul class="dropdown-menu">
++ <li><a href="/rest/auth/logout">Log Out</a></li>
++ </ul>
++ </script>
++ </li>
++ <li ng-show="!user" class="nav-login"><a ng-click="login()" href="#">Log In</a></li>
++ </ul>
++ </div>
++ </div>
++ </header>
++ <div class="container body-container">
++ <div class="main-content">
++ <div class="main-head">
++ <div class="row">
++ <div class="col-sm-2 border-right section-left greedy">
++ <div class="sidebar-nav">
++ <ul ng-controller="activeLink" class="menu">
++ <li><a ng-class="{active: isActive('/clusters')}" href="/clusters">Clusters</a></li>
++ <li><a ng-class="{active: isActive('/caches')}" href="/caches">Caches</a></li>
++ <li><a ng-class="{active: isActive('/persistence')}" href="/persistence">Persistence</a></li>
++ <li><a ng-class="{active: isActive('/clients')}" href="/clients">Clients</a></li>
++ <li>
++ <p></p><a ng-class="{active: isActive('/summary')}" href="/summary">Summary</a>
++ </li>
++ </ul>
++ </div>
++ </div>
++ <div class="col-sm-10 border-left section-right">
++ <div class="docs-content">
++ <div class="docs-header">
++ <h1>Clients</h1>
++ <p>Create and configure Ignite clients.</p>
++ <hr>
++ </div>
++ <div ng-controller="clientsRouter" class="docs-body"></div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ </div>
++ <div class="container container-footer">
++ <footer>
++ <center>
++ <p>Powered by<a href="http://ignite.incubator.apache.org"> Apache Ignite</a>, version 1.1.0</p>
++ </center>
++ </footer>
++ </div>
++ </div>
++ </body>
++</html>