Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-843 725654931 -> 9cce93e87


# ignite-843 WIP refactoring.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/475f4757
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/475f4757
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/475f4757

Branch: refs/heads/ignite-843
Commit: 475f475703879ffb2b92681ec4c43351b15eaadb
Parents: c873d98
Author: Andrey <anovi...@gridgain.com>
Authored: Fri Jun 26 14:16:37 2015 +0700
Committer: Andrey <anovi...@gridgain.com>
Committed: Fri Jun 26 14:16:37 2015 +0700

----------------------------------------------------------------------
 modules/webconfig/nodejs/package.json           |   3 +-
 .../nodejs/public/form-models/caches.json       |  78 +++++++------
 .../nodejs/public/form-models/clusters.json     |  77 ++++++-------
 .../public/javascripts/controllers/caches.js    |   2 +
 .../public/javascripts/controllers/clusters.js  |   2 +
 .../public/javascripts/controllers/common.js    | 109 ++++++++++++++-----
 modules/webconfig/nodejs/routes/persistences.js |  12 +-
 .../webconfig/nodejs/test/routes/persistence.js |  10 +-
 .../nodejs/views/includes/controls.jade         |  86 +++++++--------
 9 files changed, 218 insertions(+), 161 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/package.json
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/package.json 
b/modules/webconfig/nodejs/package.json
index 2c1d6dd..cdf51ac 100644
--- a/modules/webconfig/nodejs/package.json
+++ b/modules/webconfig/nodejs/package.json
@@ -25,7 +25,8 @@
     "passport-local": "^1.0.0",
     "passport-local-mongoose": "^1.0.0",
     "pg": "^4.4.0",
-    "serve-favicon": "~2.2.0"
+    "serve-favicon": "~2.2.0",
+    "util": "^0.10.3"
   },
   "devDependencies": {
     "supertest": "^1.0.1",

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/public/form-models/caches.json
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/public/form-models/caches.json 
b/modules/webconfig/nodejs/public/form-models/caches.json
index 102fae4..f988153 100644
--- a/modules/webconfig/nodejs/public/form-models/caches.json
+++ b/modules/webconfig/nodejs/public/form-models/caches.json
@@ -89,8 +89,7 @@
         {
           "label": "Eviction policy",
           "type": "dropdown-details",
-          "group": "evictionPolicy",
-          "model": "kind",
+          "model": "evictionPolicy.kind",
           "placeholder": "Choose eviction policy",
           "items": "evictionPolicies",
           "tip": [
@@ -103,13 +102,13 @@
                 {
                   "label": "Batch size",
                   "type": "number",
-                  "model": "batchSize",
+                  "model": "evictionPolicy.LRU.batchSize",
                   "placeholder": "1"
                 },
                 {
                   "label": "Max memory size",
                   "type": "number",
-                  "model": "maxMemorySize",
+                  "model": "evictionPolicy.LRU.maxMemorySize",
                   "placeholder": "0",
                   "tip": [
                     "Maximum allowed cache size in bytes."
@@ -118,7 +117,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "evictionPolicy.LRU.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -132,7 +131,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "evictionPolicy.RND.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -146,13 +145,13 @@
                 {
                   "label": "Batch size",
                   "type": "number",
-                  "model": "batchSize",
+                  "model": "evictionPolicy.FIFO.batchSize",
                   "placeholder": "1"
                 },
                 {
                   "label": "Max memory size",
                   "type": "number",
-                  "model": "maxMemorySize",
+                  "model": "evictionPolicy.FIFO.maxMemorySize",
                   "placeholder": "0",
                   "tip": [
                     "Maximum allowed cache size in bytes."
@@ -161,7 +160,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "evictionPolicy.FIFO.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -175,13 +174,13 @@
                 {
                   "label": "Batch size",
                   "type": "number",
-                  "model": "batchSize",
+                  "model": "evictionPolicy.SORTED.batchSize",
                   "placeholder": "1"
                 },
                 {
                   "label": "Max memory size",
                   "type": "number",
-                  "model": "maxMemorySize",
+                  "model": "evictionPolicy.SORTED.maxMemorySize",
                   "placeholder": "0",
                   "tip": [
                     "Maximum allowed cache size in bytes."
@@ -190,7 +189,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "evictionPolicy.SORTED.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -212,12 +211,11 @@
     },
     {
       "label": "Near cache",
-      "model": "nearConfiguration",
       "fields": [
         {
           "label": "Start size",
           "type": "number",
-          "model": "nearStartSize",
+          "model": "nearConfiguration.nearStartSize",
           "placeholder": "375000",
           "tip": [
             "Initial cache size for near cache which will be used to 
pre-create internal hash table after start."
@@ -226,8 +224,7 @@
         {
           "label": "Eviction policy",
           "type": "dropdown-details",
-          "group": "nearEvictionPolicy",
-          "model": "kind",
+          "model": "nearConfiguration.nearEvictionPolicy.kind",
           "placeholder": "Choose eviction policy",
           "items": "evictionPolicies",
           "tip": [
@@ -240,13 +237,13 @@
                 {
                   "label": "Batch size",
                   "type": "number",
-                  "model": "batchSize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.LRU.batchSize",
                   "placeholder": "1"
                 },
                 {
                   "label": "Max memory size",
                   "type": "number",
-                  "model": "maxMemorySize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.LRU.maxMemorySize",
                   "placeholder": "0",
                   "tip": [
                     "Maximum allowed cache size in bytes."
@@ -255,7 +252,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "nearConfiguration.nearEvictionPolicy.LRU.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -269,7 +266,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "nearConfiguration.nearEvictionPolicy.RND.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -283,13 +280,13 @@
                 {
                   "label": "Batch size",
                   "type": "number",
-                  "model": "batchSize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.FIFO.batchSize",
                   "placeholder": "1"
                 },
                 {
                   "label": "Max memory size",
                   "type": "number",
-                  "model": "maxMemorySize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.FIFO.maxMemorySize",
                   "placeholder": "0",
                   "tip": [
                     "Maximum allowed cache size in bytes."
@@ -298,7 +295,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": "nearConfiguration.nearEvictionPolicy.FIFO.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -312,13 +309,13 @@
                 {
                   "label": "Batch size",
                   "type": "number",
-                  "model": "batchSize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.SORTED.batchSize",
                   "placeholder": "1"
                 },
                 {
                   "label": "Max memory size",
                   "type": "number",
-                  "model": "maxMemorySize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.SORTED.maxMemorySize",
                   "placeholder": "0",
                   "tip": [
                     "Maximum allowed cache size in bytes."
@@ -327,7 +324,7 @@
                 {
                   "label": "Max size",
                   "type": "number",
-                  "model": "maxSize",
+                  "model": 
"nearConfiguration.nearEvictionPolicy.SORTED.maxSize",
                   "placeholder": "100000",
                   "tip": [
                     "Maximum allowed size of cache before entry will start 
getting evicted."
@@ -433,8 +430,7 @@
           "model": "rebalanceOrder",
           "placeholder": "0",
           "tip": [
-            "If cache rebalance order is positive, rebalancing for this cache 
will be started only when rebalancing ",
-            "for all caches with smaller rebalance order (except caches with 
rebalance order 0) will be completed."
+            "If cache rebalance order is positive, rebalancing for this cache 
will be started only when rebalancing for all caches with smaller rebalance 
order (except caches with rebalance order 0) will be completed."
           ]
         },
         {
@@ -452,7 +448,7 @@
           "model": "rebalanceTimeout",
           "placeholder": "10000",
           "tip": [
-            "Rebalance timeout (ms)."
+            "Rebalance timeout in milliseconds."
           ]
         },
         {
@@ -473,7 +469,7 @@
           "label": "Store factory",
           "type": "dropdown-details",
           "group": "cacheStoreFactory",
-          "model": "kind",
+          "model": "store.kind",
           "placeholder": "Choose store factory",
           "items": "cacheStoreFactories",
           "tip": [
@@ -486,7 +482,7 @@
                 {
                   "label": "Data source bean",
                   "type": "text",
-                  "model": "dataSourceBean",
+                  "model": "store.CacheJdbcPojoStoreFactory.dataSourceBean",
                   "required": true,
                   "placeholder": "Bean name in Spring context",
                   "tip": [
@@ -498,7 +494,7 @@
                   "type": "dropdown",
                   "model": "dialect",
                   "placeholder": "Choose JDBC dialect",
-                  "items": "cacheStoreJdbcDialects",
+                  "items": 
"store.CacheJdbcPojoStoreFactory.cacheStoreJdbcDialects",
                   "tip": [
                     "Dialect of SQL implemented by a particular RDBMS:",
                     "<ul>",
@@ -519,7 +515,7 @@
                 {
                   "label": "user",
                   "type": "text",
-                  "model": "user",
+                  "model": "store.CacheJdbcBlobStoreFactory.user",
                   "tip": [
                     "User name for database access."
                   ]
@@ -527,7 +523,7 @@
                 {
                   "label": "Data source bean",
                   "type": "text",
-                  "model": "dataSourceBean",
+                  "model": "store.CacheJdbcBlobStoreFactory.dataSourceBean",
                   "placeholder": "Bean name in Spring context",
                   "tip": [
                     "Name of the data source bean in Spring context."
@@ -536,7 +532,7 @@
                 {
                   "label": "Init schema",
                   "type": "check",
-                  "model": "initSchema",
+                  "model": "store.CacheJdbcBlobStoreFactory.initSchema",
                   "tip": [
                     "Flag indicating whether DB schema should be initialized 
by Ignite (default behaviour) or was explicitly created by user."
                   ]
@@ -544,7 +540,7 @@
                 {
                   "label": "Create query",
                   "type": "text",
-                  "model": "createTableQuery",
+                  "model": "store.CacheJdbcBlobStoreFactory.createTableQuery",
                   "placeholder": "SQL for table creation",
                   "tip": [
                     "Query for table creation in underlying database.",
@@ -554,7 +550,7 @@
                 {
                   "label": "Load query",
                   "type": "text",
-                  "model": "loadQuery",
+                  "model": "store.CacheJdbcBlobStoreFactory.loadQuery",
                   "placeholder": "SQL for load entry",
                   "tip": [
                     "Query for entry load from underlying database.",
@@ -564,7 +560,7 @@
                 {
                   "label": "insert query",
                   "type": "text",
-                  "model": "insertQuery",
+                  "model": "store.CacheJdbcBlobStoreFactory.insertQuery",
                   "placeholder": "SQL for insert entry",
                   "tip": [
                     "Query for insert entry into underlying database.",
@@ -574,7 +570,7 @@
                 {
                   "label": "Update query",
                   "type": "text",
-                  "model": "updateQuery",
+                  "model": "store.CacheJdbcBlobStoreFactory.updateQuery",
                   "placeholder": "SQL for update entry",
                   "tip": [
                     "Query fpr update entry in underlying database.",
@@ -584,7 +580,7 @@
                 {
                   "label": "Delete query",
                   "type": "text",
-                  "model": "deleteQuery",
+                  "model": "store.CacheJdbcBlobStoreFactory.deleteQuery",
                   "placeholder": "SQL for delete entry",
                   "tip": [
                     "Query for delete entry from underlying database.",
@@ -600,7 +596,7 @@
                   "tableLabel": "Hibernate properties",
                   "label": "Hibernate property",
                   "type": "table-simple",
-                  "model": "hibernateProperties",
+                  "model": 
"store.CacheHibernateBlobStoreFactory.hibernateProperties",
                   "editIdx": -1,
                   "placeholder": "key=value",
                   "tip": [

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/public/form-models/clusters.json
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/public/form-models/clusters.json 
b/modules/webconfig/nodejs/public/form-models/clusters.json
index 03d7d3e..6463d0a 100644
--- a/modules/webconfig/nodejs/public/form-models/clusters.json
+++ b/modules/webconfig/nodejs/public/form-models/clusters.json
@@ -32,8 +32,7 @@
     {
       "label": "Discovery",
       "type": "dropdown-details",
-      "group": "discovery",
-      "model": "kind",
+      "model": "discovery.kind",
       "required": true,
       "placeholder": "Choose discovery",
       "items": "discoveries",
@@ -48,7 +47,7 @@
               "tableLabel": "Addresses",
               "label": "address",
               "type": "table-simple",
-              "model": "addresses",
+              "model": "discovery.Vm.addresses",
               "editIdx": -1,
               "reordering": true,
               "placeholder": "IP address:port",
@@ -78,7 +77,7 @@
             {
               "label": "IP address",
               "type": "text",
-              "model": "multicastGroup",
+              "model": "discovery.Multicast.multicastGroup",
               "placeholder": "228.1.2.4",
               "tip": [
                 "IP address of multicast group."
@@ -87,7 +86,7 @@
             {
               "label": "Port number",
               "type": "number",
-              "model": "multicastPort",
+              "model": "discovery.Multicast.multicastPort",
               "max": 65535,
               "placeholder": "47400",
               "tip": [
@@ -97,7 +96,7 @@
             {
               "label": "Waits for reply",
               "type": "number",
-              "model": "responseWaitTime",
+              "model": "discovery.Multicast.responseWaitTime",
               "placeholder": "500",
               "tip": [
                 "Time in milliseconds IP finder waits for reply to multicast 
address request."
@@ -106,7 +105,7 @@
             {
               "label": "Attempts count",
               "type": "number",
-              "model": "addressRequestAttempts",
+              "model": "discovery.Multicast.addressRequestAttempts",
               "placeholder": "2",
               "tip": [
                 "Number of attempts to send multicast address request.",
@@ -116,7 +115,7 @@
             {
               "label": "Local address",
               "type": "text",
-              "model": "localAddress",
+              "model": "discovery.Multicast.localAddress",
               "tip": [
                 "Local host address used by this IP finder.",
                 "If provided address is non-loopback then multicast socket is 
bound to this interface.",
@@ -131,7 +130,7 @@
             {
               "label": "Bucket name",
               "type": "text",
-              "model": "bucketName",
+              "model": "discovery.S3.bucketName",
               "placeholder": ""
             }
           ]
@@ -142,7 +141,7 @@
             {
               "label": "Credential",
               "type": "text",
-              "model": "credential",
+              "model": "discovery.Cloud.credential",
               "placeholder": "",
               "tip": [
                 "Credential that is used during authentication on the cloud.",
@@ -152,7 +151,7 @@
             {
               "label": "Path to credential",
               "type": "text",
-              "model": "credentialPath",
+              "model": "discovery.Cloud.credentialPath",
               "placeholder": "",
               "tip": [
                 "Path to a credential that is used during authentication on 
the cloud.",
@@ -162,7 +161,7 @@
             {
               "label": "Identity",
               "type": "text",
-              "model": "identity",
+              "model": "discovery.Cloud.identity",
               "placeholder": "",
               "tip": [
                 "Identity that is used as a user name during a connection to 
the cloud.",
@@ -172,7 +171,7 @@
             {
               "label": "Provider",
               "type": "text",
-              "model": "provider",
+              "model": "discovery.Cloud.provider",
               "placeholder": "",
               "tip": [
                 "Cloud provider to use."
@@ -186,7 +185,7 @@
             {
               "label": "Project name",
               "type": "text",
-              "model": "projectName",
+              "model": "discovery.GoogleStorage.projectName",
               "placeholder": "",
               "tip": [
                 "Google Cloud Platforms project name.",
@@ -196,7 +195,7 @@
             {
               "label": "Bucket name",
               "type": "text",
-              "model": "bucketName",
+              "model": "discovery.GoogleStorage.bucketName",
               "placeholder": "",
               "tip": [
                 "Google Cloud Storage bucket name.",
@@ -207,7 +206,7 @@
             {
               "label": "Private key path",
               "type": "text",
-              "model": "serviceAccountP12FilePath",
+              "model": "discovery.GoogleStorage.serviceAccountP12FilePath",
               "placeholder": "",
               "tip": [
                 "Full path to the private key in PKCS12 format of the Service 
Account."
@@ -216,7 +215,7 @@
             {
               "label": "Account id",
               "type": "text",
-              "model": "accountId",
+              "model": "discovery.GoogleStorage.accountId",
               "placeholder": "",
               "tip": [
                 "Service account ID (typically an e-mail address)."
@@ -230,7 +229,7 @@
             {
               "label": "DB schema should be initialized by Ignite",
               "type": "check",
-              "model": "initSchema",
+              "model": "discovery.Jdbc.initSchema",
               "tip": [
                 "Flag indicating whether DB schema should be initialized by 
Ignite or was explicitly created by user."
               ]
@@ -243,7 +242,7 @@
             {
               "label": "File path",
               "type": "text",
-              "model": "path",
+              "model": "discovery.SharedFs.path",
               "placeholder": "disco/tcp"
             }
           ]
@@ -254,12 +253,11 @@
   "advanced": [
     {
       "label": "Atomic configuration",
-      "model": "atomicConfiguration",
       "fields": [
         {
           "label": "Backups",
           "type": "number",
-          "model": "backups",
+          "model": "atomicConfiguration.backups",
           "placeholder": "0",
           "tip": [
             "Number of backup nodes."
@@ -268,7 +266,7 @@
         {
           "label": "Cache mode",
           "type": "dropdown",
-          "model": "cacheMode",
+          "model": "atomicConfiguration.cacheMode",
           "placeholder": "PARTITIONED",
           "items": "cacheModes",
           "tip": [
@@ -283,7 +281,7 @@
         {
           "label": "Sequence reserve",
           "type": "number",
-          "model": "atomicSequenceReserveSize",
+          "model": "atomicConfiguration.atomicSequenceReserveSize",
           "placeholder": "1,000",
           "tip": [
             "Default number of sequence values reserved for 
IgniteAtomicSequence instances.",
@@ -393,8 +391,7 @@
         {
           "label": "Marshaller",
           "type": "dropdown-details",
-          "group": "marshaller",
-          "model": "kind",
+          "model": "marshaller.kind",
           "placeholder": "Choose marshaller",
           "items": "marshallers",
           "tip": [
@@ -407,7 +404,7 @@
                 {
                   "label": "Streams pool size",
                   "type": "number",
-                  "model": "poolSize",
+                  "model": "marshaller.OptimizedMarshaller.poolSize",
                   "placeholder": "0",
                   "tip": [
                     "Specifies size of cached object streams used by 
marshaller.",
@@ -421,7 +418,7 @@
                 {
                   "label": "Require serializable",
                   "type": "check",
-                  "model": "requireSerializable",
+                  "model": 
"marshaller.OptimizedMarshaller.requireSerializable",
                   "tip": [
                     "Whether marshaller should require Serializable interface 
or not."
                   ]
@@ -553,8 +550,7 @@
         {
           "label": "Swap space SPI",
           "type": "dropdown-details",
-          "group": "swapSpaceSpi",
-          "model": "kind",
+          "model": "swapSpaceSpi.kind",
           "items": "swapSpaceSpis",
           "placeholder": "Choose swap SPI",
           "tip": [
@@ -567,7 +563,7 @@
                 {
                   "label": "Base directory",
                   "type": "text",
-                  "model": "baseDirectory",
+                  "model": "swapSpaceSpi.baseDirectory",
                   "placeholder": "swapspace",
                   "tip": [
                     "Base directory where to write files."
@@ -576,7 +572,7 @@
                 {
                   "label": "Read stripe size",
                   "type": "number",
-                  "model": "readStripesNumber",
+                  "model": "swapSpaceSpi.readStripesNumber",
                   "placeholder": "available CPU cores",
                   "tip": [
                     "Read stripe size defines number of file channels to be 
used concurrently."
@@ -585,7 +581,7 @@
                 {
                   "label": "Maximum sparsity",
                   "type": "number",
-                  "model": "maximumSparsity",
+                  "model": "swapSpaceSpi.maximumSparsity",
                   "placeholder": "0.5",
                   "tip": [
                     "This property defines maximum acceptable wasted file 
space to whole file size ratio.",
@@ -595,7 +591,7 @@
                 {
                   "label": "Max write queue size",
                   "type": "number",
-                  "model": "maxWriteQueueSize",
+                  "model": "swapSpaceSpi.maxWriteQueueSize",
                   "placeholder": "1024 * 1024",
                   "tip": [
                     "Max write queue size in bytes.",
@@ -605,7 +601,7 @@
                 {
                   "label": "Write buffer size",
                   "type": "number",
-                  "model": "writeBufferSize",
+                  "model": "swapSpaceSpi.writeBufferSize",
                   "placeholder": "Available CPU cores",
                   "tip": [
                     "Write buffer size in bytes.",
@@ -706,12 +702,11 @@
     },
     {
       "label": "Transactions",
-      "model": "transactionConfiguration",
       "fields": [
         {
           "label": "Cache concurrency",
           "type": "dropdown",
-          "model": "defaultTxConcurrency",
+          "model": "transactionConfiguration.defaultTxConcurrency",
           "placeholder": "PESSIMISTIC",
           "items": "transactionConcurrency",
           "tip": [
@@ -721,7 +716,7 @@
         {
           "label": "Isolation",
           "type": "dropdown",
-          "model": "transactionIsolation",
+          "model": "transactionConfiguration.transactionIsolation",
           "placeholder": "REPEATABLE_READ",
           "items": "transactionIsolation",
           "tip": [
@@ -731,7 +726,7 @@
         {
           "label": "Default timeout",
           "type": "number",
-          "model": "defaultTxTimeout",
+          "model": "transactionConfiguration.defaultTxTimeout",
           "placeholder": "0",
           "tip": [
             "Default transaction timeout."
@@ -740,7 +735,7 @@
         {
           "label": "Pessimistic log cleanup delay",
           "type": "number",
-          "model": "pessimisticTxLogLinger",
+          "model": "transactionConfiguration.pessimisticTxLogLinger",
           "placeholder": "10,000",
           "tip": [
             "Cache transaction concurrency to use when one is not explicitly 
specified."
@@ -749,7 +744,7 @@
         {
           "label": "Pessimistic log size",
           "type": "number",
-          "model": "pessimisticTxLogSize",
+          "model": "transactionConfiguration.pessimisticTxLogSize",
           "placeholder": "0",
           "tip": [
             "Cache transaction concurrency to use when one is not explicitly 
specified."
@@ -758,7 +753,7 @@
         {
           "label": "Enable serializable cache transactions",
           "type": "check",
-          "model": "txSerializableEnabled",
+          "model": "transactionConfiguration.txSerializableEnabled",
           "tip": [
             "Flag to enable/disable isolation level for cache transactions.",
             "Serializable level does carry certain overhead and if not used, 
should be disabled."

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/public/javascripts/controllers/caches.js
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/public/javascripts/controllers/caches.js 
b/modules/webconfig/nodejs/public/javascripts/controllers/caches.js
index 741365a..4a58fe3 100644
--- a/modules/webconfig/nodejs/public/javascripts/controllers/caches.js
+++ b/modules/webconfig/nodejs/public/javascripts/controllers/caches.js
@@ -20,6 +20,8 @@ configuratorModule.controller('cachesController', ['$scope', 
'$alert', '$http',
         $scope.addDetailSimpleItem = commonFunctions.addDetailSimpleItem;
         $scope.swapSimpleItems = commonFunctions.swapSimpleItems;
         $scope.joinTip = commonFunctions.joinTip;
+        $scope.getFldMdl = commonFunctions.getFldMdl;
+        $scope.setFldMdl = commonFunctions.setFldMdl;
 
         $scope.atomicities = [
             {value: 'ATOMIC', label: 'ATOMIC'},

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/public/javascripts/controllers/clusters.js
----------------------------------------------------------------------
diff --git 
a/modules/webconfig/nodejs/public/javascripts/controllers/clusters.js 
b/modules/webconfig/nodejs/public/javascripts/controllers/clusters.js
index 438a67c..89af516 100644
--- a/modules/webconfig/nodejs/public/javascripts/controllers/clusters.js
+++ b/modules/webconfig/nodejs/public/javascripts/controllers/clusters.js
@@ -20,6 +20,8 @@ configuratorModule.controller('clustersController', 
['$scope', '$alert', '$http'
         $scope.addDetailSimpleItem = commonFunctions.addDetailSimpleItem;
         $scope.swapSimpleItems = commonFunctions.swapSimpleItems;
         $scope.joinTip = commonFunctions.joinTip;
+        $scope.getFldMdl = commonFunctions.getFldMdl;
+        $scope.setFldMdl = commonFunctions.setFldMdl;
 
         $scope.templates = [
             {value: {}, label: 'blank'},

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/public/javascripts/controllers/common.js
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/public/javascripts/controllers/common.js 
b/modules/webconfig/nodejs/public/javascripts/controllers/common.js
index abc1289..0284d51 100644
--- a/modules/webconfig/nodejs/public/javascripts/controllers/common.js
+++ b/modules/webconfig/nodejs/public/javascripts/controllers/common.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-var configuratorModule =  angular.module('ignite-web-configurator', 
['smart-table', 'mgcrea.ngStrap', 'ngSanitize']);
+var configuratorModule = angular.module('ignite-web-configurator', 
['smart-table', 'mgcrea.ngStrap', 'ngSanitize']);
 
 configuratorModule.service('commonFunctions', function() {
    return {
@@ -32,7 +32,7 @@ configuratorModule.service('commonFunctions', function() {
 
            if (!master) {
                backupItem[fldGrp][backupItem[fldGrp][fldMdl]] = {};
-               
+
                master = backupItem[fldGrp][backupItem[fldGrp][fldMdl]];
            }
 
@@ -46,28 +46,81 @@ configuratorModule.service('commonFunctions', function() {
        swapSimpleItems: function(a, ix1, ix2) {
            var tmp = a[ix1];
 
-           a[ix1] = a[ix2];
-           a[ix2] = tmp;
-       },
-       joinTip: function(arr) {
-           if (!arr)
-            return arr;
+            a[ix1] = a[ix2];
+            a[ix2] = tmp;
+        },
+        joinTip: function (arr) {
+            if (!arr) {
+                return arr;
+            }
 
-           var lines = arr.map(function(line) {
-               var rtrimmed = line.replace(/\s+$/g, '');
+            var lines = arr.map(function (line) {
+                var rtrimmed = line.replace(/\s+$/g, '');
 
-               if(rtrimmed.indexOf('>', this.length - 1) == -1)
-                   rtrimmed = rtrimmed + '<br/>';
+                if (rtrimmed.indexOf('>', this.length - 1) == -1) {
+                    rtrimmed = rtrimmed + '<br/>';
+                }
 
-               return rtrimmed;
-           });
+                return rtrimmed;
+            });
 
-           return lines.join("");
-       }
-   }
+            return lines.join("");
+        },
+        getFldMdl: function (obj, path) {
+            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to 
properties
+            path = path.replace(/^\./, '');           // strip a leading dot
+
+            var a = path.split('.');
+
+            for (var i = 0; i < a.length; ++i) {
+                var k = a[i];
+
+                if (k in obj)
+                    obj = obj[k];
+                else
+                    return;
+            }
+
+            return obj;
+        },
+        setFldMdl: function (obj, path, value) {
+            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to 
properties
+            path = path.replace(/^\./, '');           // strip a leading dot
+
+            var a = path.split('.');
+
+            for (var i = 0; i < a.length - 1; ++i) {
+                var k = a[i];
+
+                if (k in obj) {
+                    if (!obj[k])
+                        obj[k] = {};
+                }
+                else
+                    obj[k] = {};
+
+                obj = obj[k];
+            }
+
+            if (value)
+                obj[a[a.length - 1]] = value;
+            else
+                delete obj[a[a.length - 1]];
+
+            //
+            //if (group && group.model && field.group)
+            //    backupItem[group.model][field.group][field.model] = value;
+            //else if (group && group.model)
+            //    backupItem[group.model][field.model] = value;
+            //else if (field.group)
+            //    backupItem[field.group][field.model] = value;
+            //else
+            //    backupItem[field.model] = value;
+        }
+    }
 });
 
-configuratorModule.config(function($tooltipProvider) {
+configuratorModule.config(function ($tooltipProvider) {
     angular.extend($tooltipProvider.defaults, {
         container: 'body',
         placement: 'right',
@@ -77,7 +130,7 @@ configuratorModule.config(function($tooltipProvider) {
     });
 });
 
-configuratorModule.config(function($selectProvider) {
+configuratorModule.config(function ($selectProvider) {
     angular.extend($selectProvider.defaults, {
         maxLength: '1',
         allText: 'Select All',
@@ -87,7 +140,7 @@ configuratorModule.config(function($selectProvider) {
 });
 
 // Alert settings
-configuratorModule.config(function($alertProvider) {
+configuratorModule.config(function ($alertProvider) {
     angular.extend($alertProvider.defaults, {
         container: 'body',
         placement: 'top-right',
@@ -99,7 +152,7 @@ configuratorModule.config(function($alertProvider) {
 // Decode name using map(value, label).
 configuratorModule.filter('displayValue', function () {
     return function (v, m, dflt) {
-        var i = _.findIndex(m, function(item) {
+        var i = _.findIndex(m, function (item) {
             return item.value == v;
         });
 
@@ -131,13 +184,13 @@ configuratorModule.filter('compact', function () {
     }
 });
 
-configuratorModule.controller('activeLink', ['$scope', function($scope) {
-    $scope.isActive = function(path) {
+configuratorModule.controller('activeLink', ['$scope', function ($scope) {
+    $scope.isActive = function (path) {
         return window.location.pathname.substr(0, path.length) == path;
     };
 }]);
 
-configuratorModule.controller('auth', ['$scope', '$modal', '$alert', '$http', 
'$window', function($scope, $modal, $alert, $http, $window) {
+configuratorModule.controller('auth', ['$scope', '$modal', '$alert', '$http', 
'$window', function ($scope, $modal, $alert, $http, $window) {
     $scope.action = 'login';
 
     $scope.errorMessage = '';
@@ -147,14 +200,14 @@ configuratorModule.controller('auth', ['$scope', 
'$modal', '$alert', '$http', '$
     // Pre-fetch an external template populated with a custom scope
     var authModal = $modal({scope: $scope, template: '/login', show: false});
 
-    $scope.login = function() {
+    $scope.login = function () {
         // Show when some event occurs (use $promise property to ensure the 
template has been loaded)
         authModal.$promise.then(authModal.show);
     };
 
-    $scope.auth = function(action, user_info) {
+    $scope.auth = function (action, user_info) {
         $http.post('/rest/auth/' + action, user_info)
-            .success(function(data) {
+            .success(function (data) {
                 authModal.hide();
 
                 $window.location = '/clusters';
@@ -162,7 +215,7 @@ configuratorModule.controller('auth', ['$scope', '$modal', 
'$alert', '$http', '$
             .error(function (data) {
                 console.log(data);
 
-                $alert({placement: 'top', container:'#errors-container', 
title: data});
+                $alert({placement: 'top', container: '#errors-container', 
title: data});
             });
     };
 }]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/routes/persistences.js
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/routes/persistences.js 
b/modules/webconfig/nodejs/routes/persistences.js
index d891b04..e1f726d 100644
--- a/modules/webconfig/nodejs/routes/persistences.js
+++ b/modules/webconfig/nodejs/routes/persistences.js
@@ -92,9 +92,17 @@ router.post('/remove', function(req, res) {
 router.post('/pg', function(req, res) {
     var pg = require('pg');
 
-    //var connectionString = process.env.DATABASE_URL || 
'postgres://localhost:5432/ggmonitor';
+    var host = req.body.host;
+    var port = req.body.port;
 
-    pg.connect(req.body.connectionString, function(err, client, done) {
+    var username = req.body.username;
+    var password = req.body.password;
+
+    var dbName = req.body.dbName;
+
+    var connectionString = sprintf('postgres://%s:%s@%s:%d/%s', username, 
password, host, port, dbName);
+
+    pg.connect(connectionString, function(err, client, done) {
         if(err)
             res.status(500).send(err.message);
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/test/routes/persistence.js
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/test/routes/persistence.js 
b/modules/webconfig/nodejs/test/routes/persistence.js
index 5d86d83..e5d8390 100644
--- a/modules/webconfig/nodejs/test/routes/persistence.js
+++ b/modules/webconfig/nodejs/test/routes/persistence.js
@@ -1,7 +1,7 @@
 var request = require('supertest'),
     should = require('should'),
     express = require('express'),
-    persistenceRouter = require('../../routes/persistence');
+    persistenceRouter = require('../../routes/persistences');
 
 var app = express();
 
@@ -15,7 +15,13 @@ describe('request.persistence', function(){
     it('should return 200', function(done){
         agent
             .post('/rest/persistence/pg')
-            .send({ connectionString: 'postgres://localhost:5432/ggmonitor' })
+            .send({
+                    username: 'nva',
+                    password: 'nva.141',
+                    host: 'localhost',
+                    port: '5432',
+                    dbName: 'ggmonitor'
+                })
             .end(function(err, res) {
                 if (err)
                     throw err;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/475f4757/modules/webconfig/nodejs/views/includes/controls.jade
----------------------------------------------------------------------
diff --git a/modules/webconfig/nodejs/views/includes/controls.jade 
b/modules/webconfig/nodejs/views/includes/controls.jade
index abc87fd..b3c4812 100644
--- a/modules/webconfig/nodejs/views/includes/controls.jade
+++ b/modules/webconfig/nodejs/views/includes/controls.jade
@@ -23,17 +23,17 @@ mixin tipLabel(lines)
     i.tipLabel.fa.fa-question-circle.blank(ng-if='!#{lines}')
 
 mixin exclamation(mdl, err, msg)
-    
i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm[#{mdl}].$error.#{err}'
 bs-tooltip data-title='#{msg}' type='button')
+    
i.fa.fa-exclamation-triangle.form-control-feedback(ng-show='inputForm["#{mdl}"].$error.#{err}'
 bs-tooltip data-title='#{msg}' type='button')
 
 mixin details-row
     - var lblDetailClasses = ['col-sm-4', 'details-label']
 
-    - var detailMdl = 
'backupItem[field.group][backupItem[field.group][field.model]][detail.model]'
+    - var detailModel = {'ng-init': 'detailMdl=getFldMdl(backupItem, 
detail.model)', 'ng-change': 'setFldMdl(backupItem, detail.model, detailMdl)', 
'ng-model': 'detailMdl'};
 
     div(ng-switch='detail.type')
         div.checkbox(ng-switch-when='check')
             label
-                input(type='checkbox' ng-model=detailMdl)
+                input(type='checkbox')&attributes(detailModel)
                 |{{detail.label}}
                 +tipLabel('detail.tip')
         div(ng-switch-when='text')
@@ -41,13 +41,13 @@ mixin details-row
             .col-sm-8
                 +tipField('detail.tip')
                 .input-tip
-                    input.form-control(type='text' ng-model=detailMdl 
placeholder='{{detail.placeholder}}')
+                    input.form-control(type='text' 
placeholder='{{detail.placeholder}}')&attributes(detailModel)
         div(ng-switch-when='number' )
             label(class=lblDetailClasses) {{detail.label}}:
             .col-sm-8
                 +tipField('detail.tip')
                 .input-tip
-                    input.form-control(name='{{detail.model}}' type='number' 
ng-model=detailMdl min='{{detail.min ? detail.min : 0}}' max='{{detail.max ? 
detail.max : Number.MAX_VALUE}}' placeholder='{{detail.placeholder}}')
+                    input.form-control(name='{{detail.model}}' type='number' 
placeholder='{{detail.placeholder}}' min='{{field.min ? field.min : 0}}' 
max='field.max ? field.max : Number.MAX_VALUE')&attributes(detailModel)
                     +exclamation('detail.model', 'min', 'Value is less than 
allowable minimum.')
                     +exclamation('detail.model', 'max', 'Value is more than 
allowable maximum.')
                     +exclamation('detail.model', 'number', 'Invalid value. 
Only numbers allowed.')
@@ -56,29 +56,29 @@ mixin details-row
             .col-sm-8
                 +tipField('detail.tip')
                 .input-tip
-                    button.form-control(bs-select ng-model=detailMdl 
data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label 
for item in {{detail.items}}')
+                    button.form-control(bs-select 
data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label 
for item in {{detail.items}}')&attributes(detailModel)
         div(ng-switch-when='dropdown-multiple')
             label(class=lblDetailClasses) {{detail.label}}:
             .col-sm-8
-                button.form-control(bs-select ng-model=detailMdl 
data-multiple='1' data-placeholder='{{detail.placeholder}}' 
bs-options='item.value as item.label for item in {{detail.items}}')
+                button.form-control(bs-select data-multiple='1' 
data-placeholder='{{detail.placeholder}}' bs-options='item.value as item.label 
for item in {{detail.items}}')&attributes(detailModel)
             +tipField('detail.tip')
-        div(ng-switch-when='table-simple' style='margin-right: 5px; 
margin-top: -0.65em')
-            table.col-sm-12.links-edit(st-table=detailMdl)
+        div(ng-switch-when='table-simple' style='margin-right: 5px; 
margin-top: -0.65em')&attributes(detailModel)
+            table.col-sm-12.links-edit(st-table='detailMdl')
                 tbody
-                    tr(ng-repeat='item in #{detailMdl} track by $index')
+                    tr(ng-repeat='item in detailMdl track by $index')
                         td.col-sm-11
                             div(ng-show='detail.editIdx != {{$index}}')
-                                a(ng-click='detail.editIdx = $index; curValue 
= #{detailMdl}[$index]') {{$index + 1}}) {{item}}
-                                
i.tipField.fa.fa-remove(ng-click='detail.editIdx = -1; 
#{detailMdl}.splice($index, 1)')
+                                a(ng-click='detail.editIdx = $index; curValue 
= detailMdl[$index]') {{$index + 1}}) {{item}}
+                                
i.tipField.fa.fa-remove(ng-click='detail.editIdx = -1; detailMdl.splice($index, 
1)')
                             div(ng-show='detail.editIdx == {{$index}}')
                                 label.labelField {{$index + 1}})
-                                
i.tipField.fa.fa-floppy-o(ng-click='detail.editIdx = -1; 
#{detailMdl}[$index]=curValue')
+                                
i.tipField.fa.fa-floppy-o(ng-click='detail.editIdx = -1; 
detailMdl[$index]=curValue')
                                 .input-tip
                                     input.form-control(type='text' 
ng-model='curValue' placeholder='{{detail.placeholder}}')
                         td.col-sm-1(ng-if='detail.reordering')
-                            i.fa.fa-arrow-up(ng-show='$index > 0' 
ng-click='swapSimpleItems(#{detailMdl}, $index, $index - 1); detail.editIdx = 
-1;')
-                            i.fa.fa-arrow-down(ng-show='$index < 
#{detailMdl}.length - 1' ng-click='swapSimpleItems(#{detailMdl}, $index, $index 
+ 1); detail.editIdx = -1;')
-            button.btn.btn-primary.fieldButton(ng-disabled='!newValue || 
#{detailMdl}.indexOf(newValue) >= 0' ng-click='detail.editIdx = -1; 
addDetailSimpleItem(backupItem, field, detail.model, newValue)') Add
+                            i.fa.fa-arrow-up(ng-show='$index > 0' 
ng-click='swapSimpleItems(detailMdl, $index, $index - 1); detail.editIdx = -1;')
+                            i.fa.fa-arrow-down(ng-show='$index < 
detailMdl.length - 1' ng-click='swapSimpleItems(detailMdl, $index, $index + 1); 
detail.editIdx = -1;')
+            button.btn.btn-primary.fieldButton(ng-disabled='!newValue || 
detailMdl.indexOf(newValue) >= 0' ng-click='detail.editIdx = -1; detailMdl ? 
detailMdl.push(newValue) : detailMdl = [newValue]; setFldMdl(backupItem, 
detail.model, detailMdl);') Add
             +tipField('detail.tip')
             .input-tip
                 input.form-control(type='text' ng-model='newValue' 
ng-focus='detail.editIdx = -1' placeholder='{{detail.placeholder}}')
@@ -86,13 +86,12 @@ mixin details-row
 mixin form-row
     - var lblClasses = ['col-sm-2']
 
-    - var masterMdl = 'backupItem[field.group][field.model]'
+    - var fieldModel = {'ng-init': 'fieldMdl=getFldMdl(backupItem, 
field.model)', 'ng-change': 'setFldMdl(backupItem, field.model, fieldMdl)', 
'ng-model': 'fieldMdl'};
 
     div(ng-switch='field.type')
         div.checkbox.col-sm-6(ng-switch-when='check')
             label
-                input(type='checkbox' ng-if='!group.model' 
ng-model='backupItem[field.model]')
-                input(type='checkbox' ng-if='group.model' 
ng-model='backupItem[group.model][field.model]')
+                input(type='checkbox')&attributes(fieldModel)
                 | {{field.label}}
                 +tipLabel('field.tip')
         div(ng-switch-when='text')
@@ -100,38 +99,34 @@ mixin form-row
             .col-sm-4
                 +tipField('field.tip')
                 .input-tip
-                    input.form-control(type='text' ng-if='!group.model' 
ng-model='backupItem[field.model]' placeholder='{{field.placeholder}}' 
ng-required='field.required')
-                    input.form-control(type='text' ng-if='group.model' 
ng-model='backupItem[group.model][field.model]' 
placeholder='{{field.placeholder}}' ng-required='field.required')
+                    input.form-control(type='text' 
placeholder='{{field.placeholder}}' 
ng-required='field.required')&attributes(fieldModel)
         div(ng-switch-when='password')
             label(class=lblClasses ng-class='{required: field.required}') 
{{field.label}}:
             .col-sm-4
                 +tipField('field.tip')
                 .input-tip
-                    input.form-control(type='password' ng-if='!group.model' 
ng-model='backupItem[field.model]' placeholder='{{field.placeholder}}' 
ng-required='field.required')
-                    input.form-control(type='password' ng-if='group.model' 
ng-model='backupItem[group.model][field.model]' 
placeholder='{{field.placeholder}}' ng-required='field.required')
+                    input.form-control(type='password' 
placeholder='{{field.placeholder}}' 
ng-required='field.required')&attributes(fieldModel)
         div(ng-switch-when='number')
             label(class=lblClasses ng-class='{required: field.required}') 
{{field.label}}:
             .col-sm-4
                 +tipField('field.tip')
                 .input-tip
-                    input.form-control(name='{{field.model}}' type='number' 
ng-if='!group.model' ng-model='backupItem[field.model]' min='{{field.min ? 
field.min : 0}}' max='field.max ? field.max : Number.MAX_VALUE' 
placeholder='{{field.placeholder}}' ng-required='field.required')
-                    input.form-control(name='{{field.model}}' type='number' 
ng-if='group.model' ng-model='backupItem[group.model][field.model]' 
min='{{field.min ? field.min : 0}}' max='{{field.max ? field.max : 
Number.MAX_VALUE}}' placeholder='{{field.placeholder}}' 
ng-required='field.required')
-                    +exclamation('field.model', 'min', 'Value is less than 
allowable minimum.')
-                    +exclamation('field.model', 'max', 'Value is more than 
allowable maximum.')
-                    +exclamation('field.model', 'number', 'Invalid value. Only 
numbers allowed.')
+                    input.form-control(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')&attributes(fieldModel)
+                    +exclamation('{{field.model}}', 'min', 'Value is less than 
allowable minimum.')
+                    +exclamation('{{field.model}}', 'max', 'Value is more than 
allowable maximum.')
+                    +exclamation('{{field.model}}', 'number', 'Invalid value. 
Only numbers allowed.')
         div(ng-switch-when='dropdown')
             label(class=lblClasses ng-class='{required: field.required}') 
{{field.label}}:
             .col-sm-4
                 +tipField('field.tip')
                 .input-tip
-                    button.form-control(bs-select ng-if='!group.model' 
ng-model='backupItem[field.model]' ng-required='field.required' 
data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label 
for item in {{field.items}}' )
-                    button.form-control(bs-select ng-if='group.model' 
ng-model='backupItem[group.model][field.model]' ng-required='field.required' 
data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label 
for item in {{field.items}}')
+                    button.form-control(bs-select ng-required='field.required' 
data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label 
for item in {{field.items}}')&attributes(fieldModel)
         div(ng-switch-when='dropdown-multiple')
             label(class=lblClasses ng-class='{required: field.required}') 
{{field.label}}:
             .col-sm-4
                 +tipField('field.tip')
                 .input-tip
-                    button.form-control(ng-disabled='{{field.items}}.length == 
0' bs-select ng-model='backupItem[field.model]' data-multiple='1' 
data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label 
for item in {{field.items}}')
+                    button.form-control(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}}')&attributes(fieldModel)
             a.customize(ng-show='field.addLink' 
ng-href='{{field.addLink.ref}}') {{field.addLink.label}}
         div(ng-switch-when='dropdown-details')
             - var expanded = 
'field.details[backupItem[field.group][field.model]].expanded'
@@ -140,33 +135,32 @@ mixin form-row
             .col-sm-4
                 +tipField('field.tip')
                 .input-tip
-                    button.form-control(bs-select ng-model=masterMdl 
ng-required='field.required' data-placeholder='{{field.placeholder}}' 
bs-options='item.value as item.label for item in {{field.items}}')
-            a.customize(ng-show='#{masterMdl} && 
field.details[#{masterMdl}].fields' ng-click='#{expanded} = !#{expanded}') 
{{#{expanded} ? "Hide settings" : "Show settings"}}
-            .col-sm-6.panel-details(ng-show='#{expanded} && #{masterMdl}')
-                .details-row(ng-repeat='detail in 
field.details[#{masterMdl}].fields')
+                    button.form-control(bs-select ng-required='field.required' 
data-placeholder='{{field.placeholder}}' bs-options='item.value as item.label 
for item in {{field.items}}')&attributes(fieldModel)
+            a.customize(ng-show='fieldMdl && field.details[fieldMdl].fields' 
ng-click='#{expanded} = !#{expanded}') {{#{expanded} ? "Hide settings" : "Show 
settings"}}
+            .col-sm-6.panel-details(ng-show='#{expanded} && fieldMdl')
+                .details-row(ng-repeat='detail in 
field.details[fieldMdl].fields')
                     +details-row
-        div(ng-switch-when='table-simple')
-            - var tblMdl = 'backupItem[field.model]'
+        div(ng-switch-when='table-simple')&attributes(fieldModel)
             div
-                label {{field.tableLabel}}: {{#{tblMdl}.length}}
+                label {{field.tableLabel}}: {{fieldMdl.length}}
                 +tipLabel('field.tip')
-            table.links-edit.col-sm-12(st-table=tblMdl 
ng-show='#{tblMdl}.length > 0')
+            table.links-edit.col-sm-12(st-table='fieldMdl' 
ng-show='fieldMdl.length > 0')
                 tbody
-                    tr.col-sm-12(ng-repeat='item in #{tblMdl} track by $index')
+                    tr.col-sm-12(ng-repeat='item in fieldMdl track by $index')
                         td.col-sm-6
                             div(ng-show='field.editIdx != {{$index}}')
-                                a(ng-click='field.editIdx = $index; curValue = 
#{tblMdl}[$index]') {{$index + 1}}) {{item | compact}}
-                                
i.tipField.fa.fa-remove(ng-click='field.editIdx = -1; #{tblMdl}.splice($index, 
1)')
+                                a(ng-click='field.editIdx = $index; curValue = 
fieldMdl[$index]') {{$index + 1}}) {{item | compact}}
+                                
i.tipField.fa.fa-remove(ng-click='field.editIdx = -1; fieldMdl.splice($index, 
1)')
                             div(ng-show='field.editIdx == {{$index}}')
                                 label.labelField {{$index + 1}})
-                                
i.tipField.fa.fa-floppy-o(ng-click='field.editIdx = -1; 
#{tblMdl}[$index]=curValue')
+                                
i.tipField.fa.fa-floppy-o(ng-click='field.editIdx = -1; 
fieldMdl[$index]=curValue')
                                 .input-tip
                                     input.form-control(type='text' 
ng-model='curValue' placeholder='{{field.placeholder}}')
                         td.col-sm-1(ng-if='field.reordering')
-                            i.fa.fa-arrow-up(ng-show='$index > 0' 
ng-click='swapSimpleItems(#{tblMdl}, $index, $index - 1); field.editIdx = -1;')
-                            i.fa.fa-arrow-down(ng-show='$index < 
#{tblMdl}.length - 1' ng-click='swapSimpleItems(#{tblMdl}, $index, $index + 1); 
field.editIdx = -1;')
+                            i.fa.fa-arrow-up(ng-show='$index > 0' 
ng-click='swapSimpleItems(fieldMdl, $index, $index - 1); field.editIdx = -1;')
+                            i.fa.fa-arrow-down(ng-show='$index < 
fieldMdl.length - 1' ng-click='swapSimpleItems(fieldMdl, $index, $index + 1); 
field.editIdx = -1;')
             .col-sm-6
-                button.btn.btn-primary.fieldButton(ng-disabled='!newValue || 
#{tblMdl}.indexOf(newValue) >= 0' ng-click='field.editIdx = -1; 
addSimpleItem(backupItem, field.model, newValue)') Add
+                button.btn.btn-primary.fieldButton(ng-disabled='!newValue || 
fieldMdl.indexOf(newValue) >= 0' ng-click='field.editIdx = -1; 
addSimpleItem(backupItem, field.model, newValue)') Add
                 +tipField('field.tip')
                 .input-tip
                     input.form-control(type='text' ng-model='newValue' 
ng-focus='field.editIdx = -1'  placeholder='{{field.placeholder}}')

Reply via email to