You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2015/10/02 23:12:36 UTC
[32/32] ambari git commit: AMBARI-13280. Enhanced Configs work to add
Ranger User Info tab. (Andrii Babiichuk via Jaimin)
AMBARI-13280. Enhanced Configs work to add Ranger User Info tab. (Andrii Babiichuk via Jaimin)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ccd64811
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ccd64811
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ccd64811
Branch: refs/heads/branch-dev-patch-upgrade
Commit: ccd64811d87dfd9ccb3c814285c8cf082270d237
Parents: 321d57b
Author: Jaimin Jetly <ja...@hortonworks.com>
Authored: Fri Oct 2 12:33:39 2015 -0700
Committer: Jaimin Jetly <ja...@hortonworks.com>
Committed: Fri Oct 2 12:35:15 2015 -0700
----------------------------------------------------------------------
.../server/state/theme/ConfigPlacement.java | 12 +-
.../ambari/server/state/theme/Subsection.java | 40 +-
.../RANGER/configuration/ranger-admin-site.xml | 20 +
.../RANGER/configuration/ranger-env.xml | 23 +
.../RANGER/configuration/ranger-ugsync-site.xml | 122 ++++
.../HDP/2.3/services/RANGER/themes/theme.json | 554 +++++++++++++++++++
ambari-web/app/controllers/installer.js | 1 +
ambari-web/app/data/HDP2.3/site_properties.js | 2 +-
ambari-web/app/mappers/configs/themes_mapper.js | 41 +-
ambari-web/app/models.js | 7 +-
ambari-web/app/models/configs/section.js | 138 -----
.../app/models/configs/stack_config_property.js | 6 +
ambari-web/app/models/configs/sub_section.js | 176 ------
ambari-web/app/models/configs/tab.js | 73 ---
ambari-web/app/models/configs/theme/section.js | 138 +++++
.../app/models/configs/theme/sub_section.js | 189 +++++++
.../app/models/configs/theme/sub_section_tab.js | 89 +++
ambari-web/app/models/configs/theme/tab.js | 73 +++
.../configs/service_config_layout_tab.hbs | 24 +
.../configs/service_config_layout_tab_view.js | 112 ++--
.../test/mappers/configs/themes_mapper_test.js | 6 +-
21 files changed, 1402 insertions(+), 444 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-server/src/main/java/org/apache/ambari/server/state/theme/ConfigPlacement.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/theme/ConfigPlacement.java b/ambari-server/src/main/java/org/apache/ambari/server/state/theme/ConfigPlacement.java
index 56d2ea2..af12dc0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/theme/ConfigPlacement.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/theme/ConfigPlacement.java
@@ -32,6 +32,8 @@ public class ConfigPlacement {
private String config;
@JsonProperty("subsection-name")
private String subsectionName;
+ @JsonProperty("subsection-tab-name")
+ private String subsectionTabName;
@JsonProperty("property_value_attributes")
private ValueAttributesInfo propertyValueAttributes;
@@ -56,6 +58,14 @@ public class ConfigPlacement {
this.subsectionName = subsectionName;
}
+ public String getSubsectionTabName() {
+ return subsectionTabName;
+ }
+
+ public void setSubsectionTabName(String subsectionTabName) {
+ this.subsectionTabName = subsectionTabName;
+ }
+
public ValueAttributesInfo getPropertyValueAttributes() {
return propertyValueAttributes;
}
@@ -81,4 +91,4 @@ public class ConfigPlacement {
subsectionName = parent.subsectionName;
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-server/src/main/java/org/apache/ambari/server/state/theme/Subsection.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/theme/Subsection.java b/ambari-server/src/main/java/org/apache/ambari/server/state/theme/Subsection.java
index 0397545..c9f9019 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/theme/Subsection.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/theme/Subsection.java
@@ -47,6 +47,8 @@ public class Subsection {
private Boolean leftVerticalSplitter;
@JsonProperty("depends-on")
private List<ConfigCondition> dependsOn;
+ @JsonProperty("subsection-tabs")
+ private List<SubsectionTab> subsectionTabs;
public String getRowIndex() {
@@ -121,8 +123,16 @@ public class Subsection {
this.dependsOn = dependsOn;
}
+ public List<SubsectionTab> getSubsectionTabs() {
+ return subsectionTabs;
+ }
+
+ public void setSubsectionTabs(List<SubsectionTab> subsectionTabs) {
+ this.subsectionTabs = subsectionTabs;
+ }
+
public boolean isRemoved() {
- return rowIndex == null && rowSpan == null && columnIndex == null && columnSpan == null;
+ return rowIndex == null && rowSpan == null && columnIndex == null && columnSpan == null && dependsOn == null && subsectionTabs == null;
}
public void mergeWithParent(Subsection parent) {
@@ -150,5 +160,33 @@ public class Subsection {
if (dependsOn == null) {
dependsOn = parent.dependsOn;
}
+ if (subsectionTabs == null) {
+ subsectionTabs = parent.subsectionTabs;
+ }
+ }
+
+ @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ private static class SubsectionTab {
+ @JsonProperty("name")
+ private String name;
+ @JsonProperty("display-name")
+ private String displayName;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-admin-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-admin-site.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-admin-site.xml
index 97ba241..d93d758 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-admin-site.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-admin-site.xml
@@ -178,6 +178,7 @@
<property>
<name>ranger.ldap.url</name>
+ <display-name>LDAP URL</display-name>
<value>ldap://71.127.43.33:389</value>
<description>LDAP Server URL, only used if Authentication method is LDAP</description>
<value-attributes>
@@ -196,18 +197,21 @@
<property>
<name>ranger.ldap.group.searchbase</name>
+ <display-name>Group Search Base</display-name>
<value>ou=groups,dc=xasecure,dc=net</value>
<description>LDAP group searchbase, only used if Authentication method is LDAP</description>
</property>
<property>
<name>ranger.ldap.group.searchfilter</name>
+ <display-name>Group Search Filter</display-name>
<value>(member=uid={0},ou=users,dc=xasecure,dc=net)</value>
<description>LDAP group search filter, only used if Authentication method is LDAP</description>
</property>
<property>
<name>ranger.ldap.user.searchfilter</name>
+ <display-name>User Search Filter</display-name>
<value>(uid={0})</value>
<description>Search filter used for Bind Authentication</description>
<value-attributes>
@@ -235,6 +239,7 @@
<property>
<name>ranger.ldap.bind.dn</name>
+ <display-name>Bind User</display-name>
<value>cn=adadmin,cn=Users,dc=example,dc=com</value>
<description>Full distinguished name (DN), including common name (CN), of an LDAP user account that has privileges to search for users. </description>
<value-attributes>
@@ -244,6 +249,7 @@
<property>
<name>ranger.ldap.bind.password</name>
+ <display-name>Bind User Password</display-name>
<value></value>
<property-type>PASSWORD</property-type>
<description>Password for the account that can search for users</description>
@@ -263,6 +269,7 @@
<property>
<name>ranger.ldap.ad.domain</name>
+ <display-name>Domain Name</display-name>
<value>localhost</value>
<description>AD domain, only used if Authentication method is AD</description>
<value-attributes>
@@ -362,7 +369,20 @@
<display-name>Allow remote Login</display-name>
<description>Remote login enabled? - only used if Authentication method is UNIX</description>
<value-attributes>
+ <empty-value-valid>true</empty-value-valid>
+ <type>value-list</type>
<overridable>false</overridable>
+ <entries>
+ <entry>
+ <value>true</value>
+ <label>Yes</label>
+ </entry>
+ <entry>
+ <value>false</value>
+ <label>No</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
</value-attributes>
</property>
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-env.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-env.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-env.xml
index 7f3e6e0..a8ad1b6 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-env.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-env.xml
@@ -53,4 +53,27 @@
<deleted>true</deleted>
</property>
+ <property>
+ <name>bind_anonymous</name>
+ <display-name>Bind Anonymous</display-name>
+ <value>false</value>
+ <value-attributes>
+ <type>value-list</type>
+ <overridable>false</overridable>
+ <entries>
+ <entry>
+ <value>true</value>
+ <label>Yes</label>
+ </entry>
+ <entry>
+ <value>false</value>
+ <label>No</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
+ <empty-value-valid>true</empty-value-valid>
+ </value-attributes>
+ </property>
+
+
</configuration>
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-ugsync-site.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-ugsync-site.xml b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-ugsync-site.xml
index de63dd6..c73c592 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-ugsync-site.xml
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/configuration/ranger-ugsync-site.xml
@@ -64,8 +64,25 @@
<property>
<name>ranger.usersync.enabled</name>
+ <display-name>Enable User Sync</display-name>
<value>true</value>
<description>Usersync enabled?</description>
+ <value-attributes>
+ <empty-value-valid>true</empty-value-valid>
+ <type>value-list</type>
+ <overridable>false</overridable>
+ <entries>
+ <entry>
+ <value>true</value>
+ <label>Yes</label>
+ </entry>
+ <entry>
+ <value>false</value>
+ <label>No</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
+ </value-attributes>
</property>
<property>
@@ -94,11 +111,30 @@
<property>
<name>ranger.usersync.unix.minUserId</name>
+ <display-name>Minimum User ID</display-name>
<value>500</value>
<description>Only sync users above this user id (applicable for UNIX)</description>
</property>
<property>
+ <name>ranger.usersync.unix.group.file</name>
+ <display-name>Group File</display-name>
+ <value></value>
+ <value-attributes>
+ <empty-value-valid>true</empty-value-valid>
+ </value-attributes>
+ </property>
+
+ <property>
+ <name>ranger.usersync.unix.password.file</name>
+ <display-name>Password File</display-name>
+ <value></value>
+ <value-attributes>
+ <empty-value-valid>true</empty-value-valid>
+ </value-attributes>
+ </property>
+
+ <property>
<name>ranger.usersync.sleeptimeinmillisbetweensynccycle</name>
<value>5</value>
<description>Sleeptime interval in milliseconds, if < 1000 then default to 30 sec</description>
@@ -107,38 +143,69 @@
<property>
<name>ranger.usersync.source.impl.class</name>
<value>org.apache.ranger.unixusersync.process.UnixUserGroupBuilder</value>
+ <display-name>Sync Source</display-name>
<description>For Ldap: org.apache.ranger.ldapusersync.process.LdapUserGroupBuilder, For Unix: org.apache.ranger.unixusersync.process.UnixUserGroupBuilder, org.apache.ranger.unixusersync.process.FileSourceUserGroupBuilder</description>
<value-attributes>
+ <type>value-list</type>
<empty-value-valid>true</empty-value-valid>
+ <overridable>false</overridable>
+ <entries>
+ <entry>
+ <value></value>
+ <label>NONE</label>
+ </entry>
+ <entry>
+ <value>org.apache.ranger.unixusersync.process.UnixUserGroupBuilder</value>
+ <label>UNIX</label>
+ </entry>
+ <entry>
+ <value>org.apache.ranger.unixusersync.process.FileSourceUserGroupBuilder</value>
+ <label>FILE</label>
+ </entry>
+ <entry>
+ <value>org.apache.ranger.ldapusersync.process.LdapUserGroupBuilder</value>
+ <label>LDAP</label>
+ </entry>
+ <entry>
+ <value>org.apache.ranger.ldapusersync.process.LdapUserGroupBuilder</value>
+ <label>AD</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
</value-attributes>
</property>
<property>
<name>ranger.usersync.filesource.file</name>
+ <display-name>File Name</display-name>
<value>/tmp/usergroup.txt</value>
<description>/tmp/usergroup.json or /tmp/usergroup.csv or /tmp/usergroup.txt</description>
</property>
<property>
<name>ranger.usersync.filesource.text.delimiter</name>
+ <display-name>Delimeter</display-name>
<value>,</value>
<description>Delimiter used in file, if File based user sync is used</description>
</property>
<property>
<name>ranger.usersync.ldap.url</name>
+ <display-name>LDAP (AD) URL</display-name>
<value>ldap://localhost:389</value>
<description>LDAP server URL</description>
</property>
<property>
<name>ranger.usersync.ldap.binddn</name>
+ <display-name>Bind User</display-name>
<value>cn=admin,dc=xasecure,dc=net</value>
<description>Full distinguished name (DN), including common name (CN), of an LDAP user account that has privileges to search for users. </description>
</property>
<property>
<name>ranger.usersync.ldap.ldapbindpassword</name>
+ <display-name>Bind User Password</display-name>
<value></value>
<property-type>PASSWORD</property-type>
<description>Password for the account that can search for users.</description>
@@ -174,6 +241,7 @@
<property>
<name>ranger.usersync.ldap.user.searchbase</name>
+ <display-name>User Search Base</display-name>
<value>ou=users,dc=xasecure,dc=net</value>
<description>"# search base for users
# sample value would be ou=users,dc=hadoop,dc=apache,dc=org
@@ -182,6 +250,7 @@
<property>
<name>ranger.usersync.ldap.user.searchscope</name>
+ <display-name>User Search Scope</display-name>
<value>sub</value>
<description>"# search scope for the users, only base, one and sub are supported values
# please customize the value to suit your deployment
@@ -190,12 +259,14 @@
<property>
<name>ranger.usersync.ldap.user.objectclass</name>
+ <display-name>User Object Class</display-name>
<value>person</value>
<description>LDAP User Object Class</description>
</property>
<property>
<name>ranger.usersync.ldap.user.searchfilter</name>
+ <display-name>User Search Filter</display-name>
<value>empty</value>
<description>"optional additional filter constraining the users selected for syncing
# a sample value would be (dept=eng)
@@ -205,6 +276,7 @@
<property>
<name>ranger.usersync.ldap.user.nameattribute</name>
+ <display-name>Username Attribute</display-name>
<value>cn</value>
<description>LDAP user name attribute</description>
</property>
@@ -220,6 +292,7 @@
<property>
<name>ranger.usersync.ldap.user.groupnameattribute</name>
+ <display-name>User Group Name Attribute</display-name>
<value>memberof, ismemberof</value>
<description>LDAP user group name attribute</description>
</property>
@@ -244,6 +317,7 @@
<property>
<name>ranger.usersync.group.searchenabled</name>
+ <display-name>Enable Group Sync (Group Search Filter)</display-name>
<value>false</value>
<description>"# do we want to do ldapsearch to find groups instead of relying on user entry attributes
# valid values: true, false
@@ -251,20 +325,48 @@
# default value: false"</description>
<value-attributes>
<empty-value-valid>true</empty-value-valid>
+ <type>value-list</type>
+ <overridable>false</overridable>
+ <entries>
+ <entry>
+ <value>true</value>
+ <label>Yes</label>
+ </entry>
+ <entry>
+ <value>false</value>
+ <label>No</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
</value-attributes>
</property>
<property>
<name>ranger.usersync.group.usermapsyncenabled</name>
<value>false</value>
+ <display-name>Group User Map Sync</display-name>
<description>User map sync enabled?</description>
<value-attributes>
<empty-value-valid>true</empty-value-valid>
+ <type>value-list</type>
+ <overridable>false</overridable>
+ <entries>
+ <entry>
+ <value>true</value>
+ <label>Yes</label>
+ </entry>
+ <entry>
+ <value>false</value>
+ <label>No</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
</value-attributes>
</property>
<property>
<name>ranger.usersync.group.searchbase</name>
+ <display-name>Group Search Base</display-name>
<value> </value>
<description>"# search base for groups
# sample value would be ou=groups,dc=hadoop,dc=apache,dc=org
@@ -289,6 +391,7 @@
<property>
<name>ranger.usersync.group.objectclass</name>
+ <display-name>Group Object Class</display-name>
<value> </value>
<description></description>
<value-attributes>
@@ -299,6 +402,7 @@
<property>
<name>ranger.usersync.group.searchfilter</name>
<value> </value>
+ <display-name>Group Search Filter</display-name>
<description>"# optional additional filter constraining the groups selected for syncing
# a sample value would be (dept=eng)
# please customize the value to suit your deployment
@@ -310,6 +414,7 @@
<property>
<name>ranger.usersync.group.nameattribute</name>
+ <display-name>Group Name Attribute</display-name>
<value> </value>
<description>LDAP group name attribute</description>
<value-attributes>
@@ -319,6 +424,7 @@
<property>
<name>ranger.usersync.group.memberattributename</name>
+ <display-name>Group Member Attribute</display-name>
<value> </value>
<description>LDAP group member attribute name</description>
<value-attributes>
@@ -330,6 +436,22 @@
<name>ranger.usersync.pagedresultsenabled</name>
<value>true</value>
<description>Results can be paged?</description>
+ <value-attributes>
+ <empty-value-valid>true</empty-value-valid>
+ <type>value-list</type>
+ <overridable>false</overridable>
+ <entries>
+ <entry>
+ <value>true</value>
+ <label>Yes</label>
+ </entry>
+ <entry>
+ <value>false</value>
+ <label>No</label>
+ </entry>
+ </entries>
+ <selection-cardinality>1</selection-cardinality>
+ </value-attributes>
</property>
<property>
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/themes/theme.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/themes/theme.json b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/themes/theme.json
index 7160a4f..b398a3b 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/themes/theme.json
+++ b/ambari-server/src/main/resources/stacks/HDP/2.3/services/RANGER/themes/theme.json
@@ -114,6 +114,49 @@
}
]
}
+ },
+ {
+ "name": "ranger_user_info",
+ "display-name": "Ranger User Info",
+ "layout": {
+ "tab-columns": "1",
+ "tab-rows": "1",
+ "sections": [
+ {
+ "name": "section-user-info",
+ "display-name": "Ranger User Info",
+ "row-index": "0",
+ "column-index": "0",
+ "row-span": "1",
+ "column-span": "1",
+ "section-columns": "1",
+ "section-rows": "1",
+ "subsections": [
+ {
+ "name": "subsection-ranger-user-row1-col1",
+ "row-index": "0",
+ "column-index": "0",
+ "row-span": "1",
+ "column-span": "1",
+ "subsection-tabs": [
+ {
+ "name": "ldap-common-configs",
+ "display-name": "Common Configs"
+ },
+ {
+ "name": "ldap-user-configs",
+ "display-name": "User Configs"
+ },
+ {
+ "name": "ldap-group-configs",
+ "display-name": "Group Configs"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
}
]
}
@@ -192,6 +235,363 @@
"property_value_attributes": {
"ui_only_property": true
}
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.source.impl.class",
+ "subsection-name": "subsection-ranger-user-row1-col1"
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.unix.minUserId",
+ "subsection-name": "subsection-ranger-user-row1-col1"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.unix.password.file",
+ "subsection-name": "subsection-ranger-user-row1-col1"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.unix.group.file",
+ "subsection-name": "subsection-ranger-user-row1-col1"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.filesource.file",
+ "subsection-name": "subsection-ranger-user-row1-col1"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.filesource.text.delimiter",
+ "subsection-name": "subsection-ranger-user-row1-col1"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.url",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-common-configs"
+ },
+ {
+ "config": "ranger-admin-site/ranger.ldap.ad.domain",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-common-configs"
+ },
+ {
+ "config": "ranger-env/bind_anonymous",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-common-configs"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.binddn",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-common-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-env/bind_anonymous"
+ ],
+ "if": "${ranger-env/bind_anonymous}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.ldapbindpassword",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-common-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-env/bind_anonymous"
+ ],
+ "if": "${ranger-env/bind_anonymous}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.enabled",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.nameattribute",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.enabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.enabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.objectclass",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.enabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.enabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.searchbase",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.enabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.enabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.searchfilter",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.enabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.enabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.searchscope",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.enabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.enabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.groupnameattribute",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-user-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.enabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.enabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.usermapsyncenabled",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.searchenabled",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs"
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.memberattributename",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.group.searchenabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.group.searchenabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.nameattribute",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.group.searchenabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.group.searchenabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.objectclass",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.group.searchenabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.group.searchenabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.searchbase",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.group.searchenabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.group.searchenabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.searchfilter",
+ "subsection-name": "subsection-ranger-user-row1-col1",
+ "subsection-tab-name": "ldap-group-configs",
+ "depends-on": [
+ {
+ "configs":[
+ "ranger-ugsync-site/ranger.usersync.group.searchenabled"
+ ],
+ "if": "${ranger-ugsync-site/ranger.usersync.group.searchenabled}",
+ "then": {
+ "property_value_attributes": {
+ "visible": true
+ }
+ },
+ "else": {
+ "property_value_attributes": {
+ "visible": false
+ }
+ }
+ }
+ ]
}
]
},
@@ -287,6 +687,160 @@
"db.connection.password": "admin-properties/db_root_password"
}
}
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.source.impl.class",
+ "widget": {
+ "type": "combo"
+ }
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.url",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-env/bind_anonymous",
+ "widget": {
+ "type": "toggle"
+ }
+ },
+ {
+ "config": "ranger-admin-site/ranger.ldap.ad.domain",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.binddn",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.ldapbindpassword",
+ "widget": {
+ "type": "password"
+ }
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.enabled",
+ "widget": {
+ "type": "toggle"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.usermapsyncenabled",
+ "widget": {
+ "type": "toggle"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.nameattribute",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.objectclass",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.searchbase",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.searchfilter",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.searchscope",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.ldap.user.groupnameattribute",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.searchenabled",
+ "widget": {
+ "type": "toggle"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.memberattributename",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.nameattribute",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.objectclass",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.searchbase",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.group.searchfilter",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.unix.minUserId",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.unix.password.file",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.unix.group.file",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.filesource.file",
+ "widget": {
+ "type": "text-field"
+ }
+ },
+ {
+ "config": "ranger-ugsync-site/ranger.usersync.filesource.text.delimiter",
+ "widget": {
+ "type": "text-field"
+ }
}
]
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/controllers/installer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/installer.js b/ambari-web/app/controllers/installer.js
index 811f858..013f318 100644
--- a/ambari-web/app/controllers/installer.js
+++ b/ambari-web/app/controllers/installer.js
@@ -236,6 +236,7 @@ App.InstallerController = App.WizardController.extend({
App.StackConfigProperty.find().clear();
App.Section.find().clear();
App.SubSection.find().clear();
+ App.SubSectionTab.find().clear();
App.Tab.find().clear();
this.set('stackConfigsLoaded', false);
if (stacks && stacks.get('length')) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/data/HDP2.3/site_properties.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/HDP2.3/site_properties.js b/ambari-web/app/data/HDP2.3/site_properties.js
index 8495dee..12d1b9a 100644
--- a/ambari-web/app/data/HDP2.3/site_properties.js
+++ b/ambari-web/app/data/HDP2.3/site_properties.js
@@ -112,7 +112,7 @@ hdp23properties.push({
},
{
displayName: 'ACTIVE_DIRECTORY',
- foreignKeys: ['ranger.ldap.ad.domain', 'ranger.ldap.ad.url','ranger.ldap.ad.base.dn','ranger.ldap.ad.bind.dn','ranger.ldap.ad.bind.password','ranger.ldap.ad.referral','ranger.ldap.ad.user.searchfilter']
+ foreignKeys: ['ranger.ldap.ad.url','ranger.ldap.ad.base.dn','ranger.ldap.ad.bind.dn','ranger.ldap.ad.bind.password','ranger.ldap.ad.referral','ranger.ldap.ad.user.searchfilter']
},
{
displayName: 'UNIX',
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/mappers/configs/themes_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/configs/themes_mapper.js b/ambari-web/app/mappers/configs/themes_mapper.js
index b55a695..c296713 100644
--- a/ambari-web/app/mappers/configs/themes_mapper.js
+++ b/ambari-web/app/mappers/configs/themes_mapper.js
@@ -21,6 +21,7 @@ App.themesMapper = App.QuickDataMapper.create({
tabModel: App.Tab,
sectionModel: App.Section,
subSectionModel: App.SubSection,
+ subSectionTabModel: App.SubSectionTab,
configConditionModel: App.ConfigCondition,
tabConfig: {
@@ -61,6 +62,13 @@ App.themesMapper = App.QuickDataMapper.create({
"left_vertical_splitter": "left-vertical-splitter"
},
+ subSectionTabConfig: {
+ "id": "name",
+ "name": "name",
+ "display_name": "display-name",
+ "sub_section_id": "sub_section_id"
+ },
+
map: function (json) {
var tabs = [];
json.items.forEach(function(item) {
@@ -100,6 +108,21 @@ App.themesMapper = App.QuickDataMapper.create({
var parsedSubSection = this.parseIt(subSection, this.get("subSectionConfig"));
parsedSubSection.section_id = parsedSection.id;
+ if (subSection['subsection-tabs']) {
+ var subSectionTabs = [];
+
+ subSection['subsection-tabs'].forEach(function (subSectionTab) {
+ var parsedSubSectionTab = this.parseIt(subSectionTab, this.get("subSectionTabConfig"));
+ parsedSubSectionTab.sub_section_id = parsedSubSection.id;
+
+ subSectionTabs.push(parsedSubSectionTab);
+ }, this);
+ subSectionTabs[0].is_active = true;
+
+ App.store.loadMany(this.get("subSectionTabModel"), subSectionTabs);
+ parsedSubSection.sub_section_tabs = subSectionTabs.mapProperty("id");
+ }
+
subSections.push(parsedSubSection);
}, this);
App.store.loadMany(this.get("subSectionModel"), subSections);
@@ -130,15 +153,25 @@ App.themesMapper = App.QuickDataMapper.create({
Em.getWithDefault(json, "ThemeInfo.theme_data.Theme.configuration.placement.configs", []).forEach(function(configLink) {
var configId = this.getConfigId(configLink);
var subSectionId = configLink["subsection-name"];
- var subSection = App.SubSection.find(subSectionId);
+ var subSectionTabId = configLink["subsection-tab-name"];
+ if (subSectionTabId) {
+ var subSectionTab = App.SubSectionTab.find(subSectionTabId);
+ var subSectionTabDependsOnConfigs = subSectionTab.get('dependsOn');
+ } else if (subSectionId) {
+ var subSection = App.SubSection.find(subSectionId);
+ var subSectionDependsOnConfigs = subSection.get('dependsOn');
+ }
var configProperty = App.StackConfigProperty.find(configId);
- var subSectionDependsOnConfigs = subSection.get('dependsOn');
- var configDependsOnOtherConfigs = configLink["depends-on"] || [];
- var dependsOnConfigs = configDependsOnOtherConfigs.concat(subSectionDependsOnConfigs);
+
+ var configDependsOnOtherConfigs = configLink["depends-on"] || [];
+ var dependsOnConfigs = configDependsOnOtherConfigs.concat(subSectionDependsOnConfigs || []).concat(subSectionTabDependsOnConfigs || []);
if (configProperty.get('id') && subSection) {
subSection.get('configProperties').pushObject(configProperty);
configProperty.set('subSection', subSection);
+ } else if (configProperty.get('id') && subSectionTab) {
+ subSectionTab.get('configProperties').pushObject(configProperty);
+ configProperty.set('subSectionTab', subSectionTab);
} else {
console.log('there is no such property: ' + configId + '. Or subsection: ' + subSectionId);
var valueAttributes = configLink["property_value_attributes"];
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models.js b/ambari-web/app/models.js
index 1b34b0c..8117f62 100644
--- a/ambari-web/app/models.js
+++ b/ambari-web/app/models.js
@@ -66,9 +66,10 @@ require('models/configs/stack_config_property');
require('models/configs/config_group');
require('models/configs/config_version');
require('models/configs/config_property');
-require('models/configs/tab');
-require('models/configs/section');
-require('models/configs/sub_section');
+require('models/configs/theme/tab');
+require('models/configs/theme/section');
+require('models/configs/theme/sub_section');
+require('models/configs/theme/sub_section_tab');
require('models/configs/objects/service_config');
require('models/configs/objects/service_config_category');
require('models/configs/objects/service_config_property');
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/section.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/section.js b/ambari-web/app/models/configs/section.js
deleted file mode 100644
index c04665e..0000000
--- a/ambari-web/app/models/configs/section.js
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var App = require('app');
-
-App.Section = DS.Model.extend({
-
- id: DS.attr('string'),
-
- /**
- * @type {string}
- */
- name: DS.attr('string'),
-
- /**
- * @type {string}
- */
- displayName: DS.attr('string'),
-
- /**
- * @type {number}
- */
- rowIndex: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- rowSpan: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- columnIndex: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- columnSpan: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- sectionColumns: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- sectionRows: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {App.SubSection[]}
- */
- subSections: DS.hasMany('App.SubSection'),
-
- /**
- * @type {App.Tab}
- */
- tab: DS.belongsTo('App.Tab'),
-
- /**
- * Number of the errors in all subsections in the current section
- * @type {number}
- */
- errorsCount: function () {
- var errors = this.get('subSections').filterProperty('isSectionVisible').mapProperty('errorsCount');
- return errors.length ? errors.reduce(Em.sum) : 0;
- }.property('subSections.@each.errorsCount', 'subSections.@each.isSectionVisible'),
-
- /**
- * @type {boolean}
- */
- isFirstRow: function () {
- return this.get('rowIndex') == 0;
- }.property('rowIndex'),
-
- /**
- * @type {boolean}
- */
- isMiddleRow: function () {
- return this.get('rowIndex') != 0 && (this.get('rowIndex') + this.get('rowSpan') < this.get('tab.rows'));
- }.property('rowIndex', 'rowSpan', 'tab.rows'),
-
- /**
- * @type {boolean}
- */
- isLastRow: function () {
- return this.get('rowIndex') + this.get('rowSpan') == this.get('tab.rows');
- }.property('rowIndex', 'rowSpan', 'tab.rows'),
-
- /**
- * @type {boolean}
- */
- isFirstColumn: function () {
- return this.get('columnIndex') == 0;
- }.property('columnIndex'),
-
- /**
- * @type {boolean}
- */
- isMiddleColumn: function () {
- return this.get('columnIndex') != 0 && (this.get('columnIndex') + this.get('columnSpan') < this.get('tab.columns'));
- }.property('columnIndex', 'columnSpan', 'tab.columns'),
-
- /**
- * @type {boolean}
- */
- isLastColumn: function () {
- return this.get('columnIndex') + this.get('columnSpan') == this.get('tab.columns');
- }.property('columnIndex', 'columnSpan', 'tab.columns'),
-
- /**
- * Determines if section is filtered out (all it's subsections should be hidden)
- * @type {boolean}
- */
- isHiddenByFilter: function () {
- return !this.get('subSections').someProperty('isSectionVisible', true);
- }.property('subSections.@each.isHiddenByFilter')
-
-});
-
-
-App.Section.FIXTURES = [];
-
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/stack_config_property.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/stack_config_property.js b/ambari-web/app/models/configs/stack_config_property.js
index 76e3b5f..a02c8df 100644
--- a/ambari-web/app/models/configs/stack_config_property.js
+++ b/ambari-web/app/models/configs/stack_config_property.js
@@ -156,6 +156,12 @@ App.StackConfigProperty = DS.Model.extend({
*/
subSection: DS.belongsTo('App.SubSection'),
+ /**
+ * sub section tab to which belongs this property
+ * @property {App.SubSectionTab}
+ */
+ subSectionTab: DS.belongsTo('App.SubSectionTab'),
+
/******************************* UI properties ****************************************/
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/sub_section.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/sub_section.js b/ambari-web/app/models/configs/sub_section.js
deleted file mode 100644
index b7abb4f..0000000
--- a/ambari-web/app/models/configs/sub_section.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var App = require('app');
-
-App.SubSection = DS.Model.extend({
-
- id: DS.attr('string'),
-
- /**
- * @type {string}
- */
- name: DS.attr('string'),
-
- /**
- * @type {string}
- */
- displayName: DS.attr('string'),
-
- /**
- * @type {boolean}
- */
- border: DS.attr('boolean', {defaultValue: false}),
-
- /**
- * @type {number}
- */
- rowIndex: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- columnIndex: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- rowSpan: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {number}
- */
- columnSpan: DS.attr('number', {defaultValue: 1}),
-
- /**
- * @type {App.Section}
- */
- section: DS.belongsTo('App.Section'),
-
- /**
- * @type {App.StackConfigProperty[]}
- */
- configProperties: DS.hasMany('App.StackConfigProperty'),
-
- dependsOn: DS.attr('array', {defaultValue: []}),
-
- /**
- * @type {boolean}
- */
- leftVerticalSplitter: DS.attr('boolean', {defaultValue: true}),
-
- /**
- * @type {App.ServiceConfigProperty[]}
- */
- configs: [],
-
- /**
- * Number of the errors in all configs
- * @type {number}
- */
- errorsCount: function () {
- return this.get('configs').filter(function(config) {
- return !config.get('isValid') || (config.get('overrides') || []).someProperty('isValid', false);
- }).length;
- }.property('configs.@each.isValid', 'configs.@each.overrideErrorTrigger'),
-
- /**
- * @type {boolean}
- */
- addLeftVerticalSplitter: function() {
- return !this.get('isFirstColumn') && this.get('leftVerticalSplitter');
- }.property('isFirstColumn', 'leftVerticalSplitter'),
-
- /**
- * @type {boolean}
- */
- addRightVerticalSplitter: function() {
- return !this.get('isLastColumn');
- }.property('isLastColumn'),
-
- /**
- * @type {boolean}
- */
- showTopSplitter: function() {
- return !this.get('isFirstRow') && !this.get('border');
- }.property('isFirstRow', 'border'),
-
- /**
- * @type {boolean}
- */
- isFirstRow: function () {
- return this.get('rowIndex') == 0;
- }.property('rowIndex'),
-
- /**
- * @type {boolean}
- */
- isMiddleRow: function () {
- return this.get('rowIndex') != 0 && (this.get('rowIndex') + this.get('rowSpan') < this.get('section.sectionRows'));
- }.property('rowIndex', 'rowSpan', 'section.sectionRows'),
-
- /**
- * @type {boolean}
- */
- isLastRow: function () {
- return this.get('rowIndex') + this.get('rowSpan') == this.get('section.sectionRows');
- }.property('rowIndex', 'rowSpan', 'section.sectionRows'),
-
- /**
- * @type {boolean}
- */
- isFirstColumn: function () {
- return this.get('columnIndex') == 0;
- }.property('columnIndex'),
-
- /**
- * @type {boolean}
- */
- isMiddleColumn: function () {
- return this.get('columnIndex') != 0 && (this.get('columnIndex') + this.get('columnSpan') < this.get('section.sectionColumns'));
- }.property('columnIndex', 'columnSpan', 'section.sectionColumns'),
-
- /**
- * @type {boolean}
- */
- isLastColumn: function () {
- return this.get('columnIndex') + this.get('columnSpan') == this.get('section.sectionColumns');
- }.property('columnIndex', 'columnSpan', 'section.sectionColumns'),
-
- /**
- * Determines if subsection is filtered by checking it own configs
- * If there is no configs, subsection can't be hidden
- * @type {boolean}
- */
- isHiddenByFilter: function () {
- var configs = this.get('configs');
- return configs.length ? configs.everyProperty('isHiddenByFilter', true) : false;
- }.property('configs.@each.isHiddenByFilter'),
-
- /**
- * Determines if subsection is visible
- * @type {boolean}
- */
- isSectionVisible: function () {
- return !this.get('isHiddenByFilter') && this.get('configs').someProperty('isVisible', true);
- }.property('isHiddenByFilter', 'configs.@each.isVisible')
-});
-
-
-App.SubSection.FIXTURES = [];
-
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/tab.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/tab.js b/ambari-web/app/models/configs/tab.js
deleted file mode 100644
index 0940022..0000000
--- a/ambari-web/app/models/configs/tab.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var App = require('app');
-
-App.Tab = DS.Model.extend({
- id: DS.attr('string'),
- name: DS.attr('string'),
- displayName: DS.attr('string'),
- columns: DS.attr('number', {defaultValue: 1}),
- rows: DS.attr('number', {defaultValue: 1}),
- isAdvanced: DS.attr('boolean', {defaultValue: false}),
- serviceName: DS.attr('string'),
- sections: DS.hasMany('App.Section'),
- isAdvancedHidden: DS.attr('boolean', {defaultValue: false}),
- isRendered: DS.attr('boolean', {defaultValue: false}),
-
- /**
- * Number of the errors in all sections in the current tab
- * @type {number}
- */
- errorsCount: function () {
- var errors = this.get('sections').mapProperty('errorsCount');
- return errors.length ? errors.reduce(Em.sum) : 0;
- }.property('sections.@each.errorsCount'),
-
- /**
- * Class name used for tab switching
- *
- * @type {String}
- * @property headingClass
- */
- headingClass: function() {
- return '.' + this.get('id');
- }.property('id'),
-
- /**
- * tooltip message.
- * for now used when tab is disabled
- * @type {String}
- */
- tooltipMsg: function() {
- return this.get('isHiddenByFilter') ? Em.I18n.t('services.service.config.nothing.to.display') : '';
- }.property('isHiddenByFilter'),
-
- /**
- * Determines if tab is filtered out (all it's sections should be hidden)
- * If it's an Advanced Tab it can't be hidden
- * @type {boolean}
- */
- isHiddenByFilter: function () {
- return this.get('isAdvanced') ? this.get('isAdvancedHidden') : this.get('sections').everyProperty('isHiddenByFilter', true);
- }.property('isAdvanced', 'sections.@each.isHiddenByFilter', 'isAdvancedHidden')
-
-});
-
-
-App.Tab.FIXTURES = [];
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/theme/section.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/theme/section.js b/ambari-web/app/models/configs/theme/section.js
new file mode 100644
index 0000000..c04665e
--- /dev/null
+++ b/ambari-web/app/models/configs/theme/section.js
@@ -0,0 +1,138 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.Section = DS.Model.extend({
+
+ id: DS.attr('string'),
+
+ /**
+ * @type {string}
+ */
+ name: DS.attr('string'),
+
+ /**
+ * @type {string}
+ */
+ displayName: DS.attr('string'),
+
+ /**
+ * @type {number}
+ */
+ rowIndex: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ rowSpan: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ columnIndex: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ columnSpan: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ sectionColumns: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ sectionRows: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {App.SubSection[]}
+ */
+ subSections: DS.hasMany('App.SubSection'),
+
+ /**
+ * @type {App.Tab}
+ */
+ tab: DS.belongsTo('App.Tab'),
+
+ /**
+ * Number of the errors in all subsections in the current section
+ * @type {number}
+ */
+ errorsCount: function () {
+ var errors = this.get('subSections').filterProperty('isSectionVisible').mapProperty('errorsCount');
+ return errors.length ? errors.reduce(Em.sum) : 0;
+ }.property('subSections.@each.errorsCount', 'subSections.@each.isSectionVisible'),
+
+ /**
+ * @type {boolean}
+ */
+ isFirstRow: function () {
+ return this.get('rowIndex') == 0;
+ }.property('rowIndex'),
+
+ /**
+ * @type {boolean}
+ */
+ isMiddleRow: function () {
+ return this.get('rowIndex') != 0 && (this.get('rowIndex') + this.get('rowSpan') < this.get('tab.rows'));
+ }.property('rowIndex', 'rowSpan', 'tab.rows'),
+
+ /**
+ * @type {boolean}
+ */
+ isLastRow: function () {
+ return this.get('rowIndex') + this.get('rowSpan') == this.get('tab.rows');
+ }.property('rowIndex', 'rowSpan', 'tab.rows'),
+
+ /**
+ * @type {boolean}
+ */
+ isFirstColumn: function () {
+ return this.get('columnIndex') == 0;
+ }.property('columnIndex'),
+
+ /**
+ * @type {boolean}
+ */
+ isMiddleColumn: function () {
+ return this.get('columnIndex') != 0 && (this.get('columnIndex') + this.get('columnSpan') < this.get('tab.columns'));
+ }.property('columnIndex', 'columnSpan', 'tab.columns'),
+
+ /**
+ * @type {boolean}
+ */
+ isLastColumn: function () {
+ return this.get('columnIndex') + this.get('columnSpan') == this.get('tab.columns');
+ }.property('columnIndex', 'columnSpan', 'tab.columns'),
+
+ /**
+ * Determines if section is filtered out (all it's subsections should be hidden)
+ * @type {boolean}
+ */
+ isHiddenByFilter: function () {
+ return !this.get('subSections').someProperty('isSectionVisible', true);
+ }.property('subSections.@each.isHiddenByFilter')
+
+});
+
+
+App.Section.FIXTURES = [];
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/theme/sub_section.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/theme/sub_section.js b/ambari-web/app/models/configs/theme/sub_section.js
new file mode 100644
index 0000000..ba6cc99
--- /dev/null
+++ b/ambari-web/app/models/configs/theme/sub_section.js
@@ -0,0 +1,189 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.SubSection = DS.Model.extend({
+
+ id: DS.attr('string'),
+
+ /**
+ * @type {string}
+ */
+ name: DS.attr('string'),
+
+ /**
+ * @type {string}
+ */
+ displayName: DS.attr('string'),
+
+ /**
+ * @type {boolean}
+ */
+ border: DS.attr('boolean', {defaultValue: false}),
+
+ /**
+ * @type {number}
+ */
+ rowIndex: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ columnIndex: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ rowSpan: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {number}
+ */
+ columnSpan: DS.attr('number', {defaultValue: 1}),
+
+ /**
+ * @type {App.Section}
+ */
+ section: DS.belongsTo('App.Section'),
+
+ /**
+ * @type {App.StackConfigProperty[]}
+ */
+ configProperties: DS.hasMany('App.StackConfigProperty'),
+
+ /**
+ * @type {App.SubSectionTab[]}
+ */
+ subSectionTabs: DS.hasMany('App.SubSectionTab'),
+
+
+ dependsOn: DS.attr('array', {defaultValue: []}),
+
+ /**
+ * @type {boolean}
+ */
+ leftVerticalSplitter: DS.attr('boolean', {defaultValue: true}),
+
+ /**
+ * @type {App.ServiceConfigProperty[]}
+ */
+ configs: [],
+
+ /**
+ * @type {boolean}
+ */
+ hasTabs: function() {
+ return this.get('subSectionTabs.length');
+ }.property('subSectionTabs.length'),
+
+ /**
+ * Number of the errors in all configs
+ * @type {number}
+ */
+ errorsCount: function () {
+ return this.get('configs').filter(function(config) {
+ return !config.get('isValid') || (config.get('overrides') || []).someProperty('isValid', false);
+ }).length;
+ }.property('configs.@each.isValid', 'configs.@each.overrideErrorTrigger'),
+
+ /**
+ * @type {boolean}
+ */
+ addLeftVerticalSplitter: function() {
+ return !this.get('isFirstColumn') && this.get('leftVerticalSplitter');
+ }.property('isFirstColumn', 'leftVerticalSplitter'),
+
+ /**
+ * @type {boolean}
+ */
+ addRightVerticalSplitter: function() {
+ return !this.get('isLastColumn');
+ }.property('isLastColumn'),
+
+ /**
+ * @type {boolean}
+ */
+ showTopSplitter: function() {
+ return !this.get('isFirstRow') && !this.get('border');
+ }.property('isFirstRow', 'border'),
+
+ /**
+ * @type {boolean}
+ */
+ isFirstRow: function () {
+ return this.get('rowIndex') == 0;
+ }.property('rowIndex'),
+
+ /**
+ * @type {boolean}
+ */
+ isMiddleRow: function () {
+ return this.get('rowIndex') != 0 && (this.get('rowIndex') + this.get('rowSpan') < this.get('section.sectionRows'));
+ }.property('rowIndex', 'rowSpan', 'section.sectionRows'),
+
+ /**
+ * @type {boolean}
+ */
+ isLastRow: function () {
+ return this.get('rowIndex') + this.get('rowSpan') == this.get('section.sectionRows');
+ }.property('rowIndex', 'rowSpan', 'section.sectionRows'),
+
+ /**
+ * @type {boolean}
+ */
+ isFirstColumn: function () {
+ return this.get('columnIndex') == 0;
+ }.property('columnIndex'),
+
+ /**
+ * @type {boolean}
+ */
+ isMiddleColumn: function () {
+ return this.get('columnIndex') != 0 && (this.get('columnIndex') + this.get('columnSpan') < this.get('section.sectionColumns'));
+ }.property('columnIndex', 'columnSpan', 'section.sectionColumns'),
+
+ /**
+ * @type {boolean}
+ */
+ isLastColumn: function () {
+ return this.get('columnIndex') + this.get('columnSpan') == this.get('section.sectionColumns');
+ }.property('columnIndex', 'columnSpan', 'section.sectionColumns'),
+
+ /**
+ * Determines if subsection is filtered by checking it own configs
+ * If there is no configs, subsection can't be hidden
+ * @type {boolean}
+ */
+ isHiddenByFilter: function () {
+ var configs = this.get('configs');
+ return configs.length ? configs.everyProperty('isHiddenByFilter', true) : false;
+ }.property('configs.@each.isHiddenByFilter'),
+
+ /**
+ * Determines if subsection is visible
+ * @type {boolean}
+ */
+ isSectionVisible: function () {
+ return !this.get('isHiddenByFilter') && this.get('configs').someProperty('isVisible', true);
+ }.property('isHiddenByFilter', 'configs.@each.isVisible')
+});
+
+
+App.SubSection.FIXTURES = [];
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/theme/sub_section_tab.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/theme/sub_section_tab.js b/ambari-web/app/models/configs/theme/sub_section_tab.js
new file mode 100644
index 0000000..1d6eedf
--- /dev/null
+++ b/ambari-web/app/models/configs/theme/sub_section_tab.js
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.SubSectionTab = DS.Model.extend({
+
+ id: DS.attr('string'),
+
+ /**
+ * @type {string}
+ */
+ name: DS.attr('string'),
+
+ /**
+ * @type {string}
+ */
+ displayName: DS.attr('string'),
+
+ /**
+ * @type {App.Section}
+ */
+ subSection: DS.belongsTo('App.SubSection'),
+
+ /**
+ * @type {App.StackConfigProperty[]}
+ */
+ configProperties: DS.hasMany('App.StackConfigProperty'),
+
+ /**
+ * @type {App.ServiceConfigProperty[]}
+ */
+ configs: [],
+
+
+ dependsOn: DS.attr('array', {defaultValue: []}),
+
+ /**
+ * @type {boolean}
+ */
+ isActive: DS.attr('boolean', {defaultValue: false}),
+
+ /**
+ * Number of the errors in all configs
+ * @type {number}
+ */
+ errorsCount: function () {
+ return this.get('configs').filter(function(config) {
+ return !config.get('isValid') || (config.get('overrides') || []).someProperty('isValid', false);
+ }).length;
+ }.property('configs.@each.isValid', 'configs.@each.overrideErrorTrigger'),
+
+ /**
+ * Determines if subsection is filtered by checking it own configs
+ * If there is no configs, subsection can't be hidden
+ * @type {boolean}
+ */
+ isHiddenByFilter: function () {
+ var configs = this.get('configs');
+ return configs.length ? configs.everyProperty('isHiddenByFilter', true) : false;
+ }.property('configs.@each.isHiddenByFilter'),
+
+ /**
+ * Determines if subsection is visible
+ * @type {boolean}
+ */
+ isVisible: function () {
+ return !this.get('isHiddenByFilter') && this.get('configs').someProperty('isVisible', true);
+ }.property('isHiddenByFilter', 'configs.@each.isVisible')
+});
+
+
+App.SubSectionTab.FIXTURES = [];
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/models/configs/theme/tab.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/configs/theme/tab.js b/ambari-web/app/models/configs/theme/tab.js
new file mode 100644
index 0000000..0940022
--- /dev/null
+++ b/ambari-web/app/models/configs/theme/tab.js
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.Tab = DS.Model.extend({
+ id: DS.attr('string'),
+ name: DS.attr('string'),
+ displayName: DS.attr('string'),
+ columns: DS.attr('number', {defaultValue: 1}),
+ rows: DS.attr('number', {defaultValue: 1}),
+ isAdvanced: DS.attr('boolean', {defaultValue: false}),
+ serviceName: DS.attr('string'),
+ sections: DS.hasMany('App.Section'),
+ isAdvancedHidden: DS.attr('boolean', {defaultValue: false}),
+ isRendered: DS.attr('boolean', {defaultValue: false}),
+
+ /**
+ * Number of the errors in all sections in the current tab
+ * @type {number}
+ */
+ errorsCount: function () {
+ var errors = this.get('sections').mapProperty('errorsCount');
+ return errors.length ? errors.reduce(Em.sum) : 0;
+ }.property('sections.@each.errorsCount'),
+
+ /**
+ * Class name used for tab switching
+ *
+ * @type {String}
+ * @property headingClass
+ */
+ headingClass: function() {
+ return '.' + this.get('id');
+ }.property('id'),
+
+ /**
+ * tooltip message.
+ * for now used when tab is disabled
+ * @type {String}
+ */
+ tooltipMsg: function() {
+ return this.get('isHiddenByFilter') ? Em.I18n.t('services.service.config.nothing.to.display') : '';
+ }.property('isHiddenByFilter'),
+
+ /**
+ * Determines if tab is filtered out (all it's sections should be hidden)
+ * If it's an Advanced Tab it can't be hidden
+ * @type {boolean}
+ */
+ isHiddenByFilter: function () {
+ return this.get('isAdvanced') ? this.get('isAdvancedHidden') : this.get('sections').everyProperty('isHiddenByFilter', true);
+ }.property('isAdvanced', 'sections.@each.isHiddenByFilter', 'isAdvancedHidden')
+
+});
+
+
+App.Tab.FIXTURES = [];
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs b/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
index 69de315..0afe6ac 100644
--- a/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
+++ b/ambari-web/app/templates/common/configs/service_config_layout_tab.hbs
@@ -47,6 +47,30 @@
{{/if}}
{{/if}}
{{/each}}
+ {{#if subsection.hasTabs}}
+ <ul class="nav nav-tabs mbm config-tabs">
+ {{#each subSectionTab in subsection.subSectionTabs}}
+ <li rel='tooltip' {{bindAttr class="subSectionTab.isActive:active subSectionTab.isHiddenByFilter:disabled" data-original-title="tab.tooltipMsg"}}>
+ <a href="#" {{action setActiveSubTab subSectionTab target="view"}}{{bindAttr data-target="subSectionTab.id"}} data-toggle="tab">
+ {{subSectionTab.displayName}}
+ </a>
+ </li>
+ {{/each}}
+ </ul>
+ <div class="tab-content service-config-tab-content">
+ {{#each subSectionTab in subsection.subSectionTabs}}
+ {{#each config in subSectionTab.configs}}
+ <div {{bindAttr class=":tab-pane subSectionTab.isActive:active subSectionTab.id"}}>
+ {{#if config.isVisible}}
+ {{#unless config.isHiddenByFilter}}
+ {{view config.widget configBinding="config" canEditBinding="view.canEdit" sectionBinding="section" subSectionBinding="subsection" tabBinding="tab"}}
+ {{/unless}}
+ {{/if}}
+ </div>
+ {{/each}}
+ {{/each}}
+ </div>
+ {{/if}}
</div>
</div>
</td>
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/service_config_layout_tab_view.js b/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
index 6815a0d..5cce947 100644
--- a/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
+++ b/ambari-web/app/views/common/configs/service_config_layout_tab_view.js
@@ -72,58 +72,18 @@ App.ServiceConfigLayoutTabView = Em.View.extend(App.ConfigOverridable, {
* Prepare configs for render
* <code>subsection.configs</code> is an array of App.StackConfigProperty, but not App.ConfigProperty,
* so proper config-properties should be linked to the subsections.
- * Also correct widget should be used for each config (it's selected according to <code>widget.type</code> and
- * <code>widgetTypeMap</code>). It may throw an error if needed widget can't be found in the <code>widgetTypeMap</code>
* @method prepareConfigProperties
*/
prepareConfigProperties: function () {
- var widgetTypeMap = this.get('widgetTypeMap');
var self = this;
- var serviceName = self.get('controller.selectedService.serviceName');
this.get('content.sectionRows').forEach(function (row) {
row.forEach(function (section) {
section.get('subsectionRows').forEach(function (subRow) {
subRow.forEach(function (subsection) {
- var subsectionName = subsection.get('name');
- var uiOnlyConfigs = App.uiOnlyConfigDerivedFromTheme.filterProperty('subSection.name', subsectionName);
-
- subsection.set('configs', []);
- subsection.get('configProperties').toArray().concat(uiOnlyConfigs).forEach(function (config) {
-
- var service = self.get('controller.stepConfigs').findProperty('serviceName', serviceName);
- if (!service) return;
- var configProperty = service.get('configs').findProperty('name', config.get('name'));
- if (!configProperty) return;
-
- subsection.get('configs').pushObject(configProperty);
- var configWidgetType = config.get('widget.type');
- var widget = widgetTypeMap[configWidgetType];
- Em.assert('Unknown config widget view for config ' + configProperty.get('id') + ' with type ' + configWidgetType, widget);
-
- var additionalProperties = {
- widget: widget,
- stackConfigProperty: config
- };
-
- var configConditions = App.ConfigCondition.find().filter(function(_configCondition){
- var conditionalConfigs = _configCondition.get('configs').filterProperty('fileName', config.get('filename')).filterProperty('configName', config.get('name'));
- return (conditionalConfigs && conditionalConfigs.length);
- }, this);
-
- if (configConditions && configConditions.length) {
- additionalProperties.configConditions = configConditions;
- }
- configProperty.setProperties(additionalProperties);
-
- if (configProperty.get('overrides')) {
- configProperty.get('overrides').setEach('stackConfigProperty', config);
- }
- if (configProperty.get('compareConfigs')) {
- configProperty.get('compareConfigs').invoke('setProperties', {
- isComparison: false,
- stackConfigProperty: config
- });
- }
+ var uiOnlyConfigs = App.uiOnlyConfigDerivedFromTheme.filterProperty('subSection.name', subsection.get('name'));
+ self.setConfigsToContainer(subsection, uiOnlyConfigs);
+ subsection.get('subSectionTabs').forEach(function (subSectionTab) {
+ self.setConfigsToContainer(subSectionTab);
});
});
});
@@ -131,6 +91,70 @@ App.ServiceConfigLayoutTabView = Em.View.extend(App.ConfigOverridable, {
});
},
+ /**
+ * set {code} configs {code} array of subsection or subsection tab.
+ * Also correct widget should be used for each config (it's selected according to <code>widget.type</code> and
+ * <code>widgetTypeMap</code>). It may throw an error if needed widget can't be found in the <code>widgetTypeMap</code>
+ * @param containerObject
+ * @param [uiOnlyConfigs]
+ */
+ setConfigsToContainer: function(containerObject, uiOnlyConfigs) {
+ var self = this;
+ var service = this.get('controller.stepConfigs').findProperty('serviceName', this.get('controller.selectedService.serviceName'));
+ if (!service) return;
+ containerObject.set('configs', []);
+
+ containerObject.get('configProperties').toArray().concat(uiOnlyConfigs || []).forEach(function (config) {
+
+ var configProperty = service.get('configs').findProperty('name', config.get('name'));
+ if (!configProperty) return;
+
+ containerObject.get('configs').pushObject(configProperty);
+ var configWidgetType = config.get('widget.type');
+ var widget = self.get('widgetTypeMap')[configWidgetType];
+ Em.assert('Unknown config widget view for config ' + configProperty.get('id') + ' with type ' + configWidgetType, widget);
+
+ var additionalProperties = {
+ widget: widget,
+ stackConfigProperty: config
+ };
+
+ var configConditions = App.ConfigCondition.find().filter(function (_configCondition) {
+ var conditionalConfigs = _configCondition.get('configs').filterProperty('fileName', config.get('filename')).filterProperty('configName', config.get('name'));
+ return (conditionalConfigs && conditionalConfigs.length);
+ }, this);
+
+ if (configConditions && configConditions.length) {
+ additionalProperties.configConditions = configConditions;
+ }
+ configProperty.setProperties(additionalProperties);
+
+ if (configProperty.get('overrides')) {
+ configProperty.get('overrides').setEach('stackConfigProperty', config);
+ }
+ if (configProperty.get('compareConfigs')) {
+ configProperty.get('compareConfigs').invoke('setProperties', {
+ isComparison: false,
+ stackConfigProperty: config
+ });
+ }
+ });
+ },
+
+ /**
+ * changes active subsection tab
+ * @param event
+ */
+ setActiveSubTab: function(event) {
+ if (!event.context) return;
+ try {
+ event.context.get('subSection.subSectionTabs').setEach('isActive', false);
+ event.context.set('isActive', true);
+ } catch (e) {
+ console.error('Can\'t update active subsection tab');
+ }
+ },
+
didInsertElement: function () {
this.set('dataIsReady', false);
this._super();
http://git-wip-us.apache.org/repos/asf/ambari/blob/ccd64811/ambari-web/test/mappers/configs/themes_mapper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mappers/configs/themes_mapper_test.js b/ambari-web/test/mappers/configs/themes_mapper_test.js
index 99456e0..d3d6e2e 100644
--- a/ambari-web/test/mappers/configs/themes_mapper_test.js
+++ b/ambari-web/test/mappers/configs/themes_mapper_test.js
@@ -18,9 +18,9 @@
var App = require('app');
require('mappers/configs/themes_mapper');
-require('models/configs/tab');
-require('models/configs/section');
-require('models/configs/sub_section');
+require('models/configs/theme/tab');
+require('models/configs/theme/section');
+require('models/configs/theme/sub_section');
require('models/configs/stack_config_property');
describe('App.themeMapper', function () {