Index: /branches/rel_apv_10_7/usr/click/lib/libca_snmp/snmp_cadmin.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libca_snmp/snmp_cadmin.c	(revision 39870)
+++ /branches/rel_apv_10_7/usr/click/lib/libca_snmp/snmp_cadmin.c	(working copy)
@@ -1861,6 +1861,11 @@
 		snmp_server_unlock();
 		return CA_ERR_SNMP_INVAL;
 	}
+	if (port != 161 && port != 162) {
+		printf("Invalid port number. It can only be 161 or 162.\n");
+		snmp_server_unlock();
+		return CA_ERR_SNMP_INVAL;
+	}
 	trap_ver = pInfo->host[i].snmp_version;
 	if (trap_ver == 3) {
 		if (engine_id_len < 1) {
@@ -2002,7 +2007,9 @@
 		}
 	} else {
 		/* snmpv1 or snmpv2c update auth_protocol and priv_protocol */
-		printf("Warning: This command only applicable for SNMP trap version v3!");
+		if (strcmp(engine_id, pInfo->host[i].auth_eng_id) != 0) {
+			printf("Warning: Only SNMPv3 traps support changing the Engine ID.");
+		}
 		strncpy(auth_protocol, "", ENCRYPTSTR_LEN);
 		strncpy(priv_protocol, "", ENCRYPTSTR_LEN);
 	}
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/models/admintools/snmp/__init__.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/models/admintools/snmp/__init__.py	(revision 39870)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/models/admintools/snmp/__init__.py	(working copy)
@@ -243,6 +243,7 @@
                     ('v3','V3'),
                     ), primary_key=True)
     ip = IPAddressField(verbose_name='IP', primary_key=True)
+    port = PortField(verbose_name=_('Host Port'), default=162, optional=True, editable=True)
 
     class Meta:
         abstract = True
@@ -393,17 +394,18 @@
                 # version 1 or 2
                 data['engine_id'] = ''
                 data['auth_password'] = ''
-                data['level'] = ''
+                data['level'] = '""'
                 data['priv_password'] = ''
             auth_param = " ".join(auth_data)
             result = cli.cmd('snmp auth {cli_param}'.format(cli_param=auth_param).strip() % data,
                             RegexParser("the length of authoritative engine id for SNMPv3 can't be odd number", match_msg=__("The length of Authoritative Engine ID for SNMPv3 cannot be an odd number."), match_exception=CLICmdWarning, exclusive=True),
-                            BlankParser(nonblank_exception=CLICmdError, supplement=True, ignore_msg=["Warning: This command only applicable for SNMP trap version v3!"]))
+                            BlankParser(nonblank_exception=CLICmdError, supplement=True, ignore_msg=[
+                                "Warning: This command only applicable for SNMP trap version v3!",
+                                "Warning: Only SNMPv3 traps support changing the Engine ID."]))
             return result
 
 class SNMPV1V2Servers(Server):
     type = DerivedField(value='v1v2')
-    port = PortField(verbose_name=_('Host Port'), default=162, optional=True)
     version_id = EnumField(verbose_name='Version ID',values=(
                         ('1', '1'),
                         ('2', '2'),
@@ -427,12 +429,15 @@
             result = server_manager.insert_by_version(self.cli, instance)
             return result
 
-
+        def _update(self, instance):
+            self.cli.set_config()
+            server_manager = Server.get_manager(self._session)
+            result = server_manager.update_by_version(self.cli, instance)
+            return result
 
 
 class SNMPV3Servers(Server):
     type = DerivedField(value='v3')
-    port = PortField(verbose_name=_('Host Port'), default=162, optional=True, editable=True)
     engine_id = CharField(verbose_name='Engine ID', length='0..32', optional=True, editable=True)
     username = CharField(verbose_name='User Name')
     level = EnumField(verbose_name='Security Level',values=(
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/SNMPV1V2Servers/box_instance_config.html
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/SNMPV1V2Servers/box_instance_config.html	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/SNMPV1V2Servers/box_instance_config.html	(working copy)
@@ -0,0 +1,384 @@
+{# Required Context Variables: MODEL, MANAGER, OBJECT #}
+{% extends "box.html" %}
+
+{% block box_content %}
+{% import "widgets/form.html" as form %}
+{% import "widgets/action.html" as Action %}
+{% set field_group=MODEL._meta.field_groups[PARAMS['group_name']] %}
+    <div class="box-header my-header">
+        <div class="box-icon-title">
+            <i class="fa fa-cogs"></i>
+        </div>
+        <h2>
+            {% if MODEL._meta.profile %}
+                {% if not field_group or field_group.name == 'default' %}
+                    {{ MODEL._meta.verbose_name | truncate(30, True) }}
+                {% else %}
+                    {{ MODEL._meta.verbose_name | truncate(30, True) }} - {{ field_group.verbose_name | truncate(30, True) }}
+                {% endif %}
+            {% else %}
+                {% if field_group %}
+                    {{ OBJECT.repr() | truncate(30, True) }} - {{ field_group.verbose_name | truncate(30, True) }}
+                {% else %}
+                    {{ OBJECT.repr() | truncate(30, True) }}
+                {% endif %}
+            {% endif %}
+        </h2>
+    </div>
+    <div class="box-content">
+    <form class="form-horizontal main-form">
+            <script type="text/javascript">
+            var js_hook_{{ id|jsvar }} = new Object();
+            js_hook_{{ id|jsvar }}.id = "{{ id|jsvar}}";
+            js_hook_{{ id|jsvar }}.form_fields = {};
+            js_hook_{{ id|jsvar }}.ready_total = 0;
+            js_hook_{{ id|jsvar }}.ready_count = 0;
+            </script>
+            {% if field_group %}
+            <div class="row-fluid">
+                <div class="span12 with-min-width field-group-box">
+                    <fieldset>
+                    <div class="group_actions" >
+                    {% for action in field_group.related_actions(OBJECT) if not (SESSION.is_segment_user and action.seg_hidden) %}
+                        {{ Action.ActionWidget(action.name, action) }}
+                    {% endfor %}
+                    </div>
+                    {% for field in field_group.fields if field.visible_in_edit() and not field.is_external_component() and not (SESSION.is_segment_user and field.seg_hidden) and not (field.is_unprivileged and SESSION.is_unprivileged_role) %}
+                        {% set context_of_field = (PARAMS.get("context", {})|url2obj).get(field.name, None) %}
+                        {% if context_of_field != None %}
+                            {{ field.static_widget(manager=MANAGER, context_value=context_of_field[0], context_repr=context_of_field[1]).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token}) }}
+                        {% else %}
+                            {{ field.default_widget(editable=field.editable, model_instance=OBJECT, manager=MANAGER).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token, 'session':SESSION}) }}
+                        {% endif %}
+                    {% endfor %}
+                    </fieldset>
+                </div>
+            </div><!-- row-fluid -->
+            {% else %}
+            {% set group_num=MODEL._meta.field_groups|length %}
+            {% for group_name, each_field_group in MODEL._meta.field_groups.iteritems() if each_field_group.visible_in_edit(OBJECT) and not (SESSION.is_segment_user and each_field_group.seg_hidden) %}
+            {% set has_fields={"bool":false} %}
+            {% for field in each_field_group.fields if field.visible_in_edit() and not field.hide_in_popup_edit and not field.is_external_component() and not (SESSION.is_segment_user and field.seg_hidden) %}
+                 {% if field.name %}
+                     {% if has_fields.update({"bool":true}) %}{% endif %}
+                 {% endif %}
+            {% endfor %}
+            <div class="row-fluid">
+                <div class="span12 with-min-width field-group-box">
+                    {% if each_field_group.verbose_name and group_num > 1 %}
+                    <a id="{{ each_field_group.name }}"></a>
+                    {% if has_fields.bool %}
+                        <legend>{{ each_field_group.verbose_name }}</legend>
+                    {% endif %}
+                    {% endif %}
+                    <fieldset>
+                    <div class="group_actions_{{ group_name }}" >
+                    {% for action in each_field_group.related_actions(OBJECT) %}
+                        {% if not action.edit_hidden %}
+                            {{ Action.ActionWidget(action.name, action) }}
+                        {% endif %}
+                    {% endfor %}
+                    </div>
+                    {% for field in each_field_group.fields if field.visible_in_edit() and not field.hide_in_popup_edit and not field.is_external_component() and not (SESSION.is_segment_user and field.seg_hidden) %}
+                        {% set context_of_field = (PARAMS.get("context", {})|url2obj).get(field.name, None) %}
+                        {% if context_of_field != None %}
+                            {{ field.static_widget(manager=MANAGER, context_value=context_of_field[0], context_repr=context_of_field[1]).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token}) }}
+                        {% else %}
+                            {{ field.default_widget(editable=field.editable, model_instance=OBJECT, manager=MANAGER).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token,'session':SESSION}) }}
+                        {% endif %}
+                    {% endfor %}
+                    </fieldset>
+                </div>
+            </div><!-- row-fluid -->
+            {% endfor %}
+            {% endif %}
+            <div class="btn-static" style="display:none;">
+                <div class="btn-switch">
+                    <button type="submit" class="btn btn-action">{% trans %}Save Changes{% endtrans %}</button>
+                    <button type="button" class="btn btn-default btn-cancel">{% trans %}Cancel{% endtrans %}</button>
+                </div>
+            </div>
+    </form>
+    </div><!-- box-content -->
+{% endblock box_content %}
+
+{% block box_script %}
+{% if 0 %}
+<script type="text/javascript">
+// Just make editor happy to highlight the scripts
+{% endif %}
+
+{% set field_group=MODEL._meta.field_groups[PARAMS['group_name']] %}
+
+var field_group_dict = {{ MODEL._meta.get_field_group_dict()|json_dumps }};
+var group_condition_dict = {{ MODEL._meta.get_group_condition_dict()|json_dumps }};
+var field_condition_dict = {{ MODEL._meta.get_field_condition_dict()|json_dumps }};
+// copy the hook's data into box
+var hook = js_hook_{{ id|jsvar }};
+var title_id = hook['id'].replace(/_/g,'-');
+var Title = $("#" + title_id).find(".box-header.my-header").find("h2").text();
+var sTitle = Title.trim();
+var arr = [];
+
+box.form_fields = hook.form_fields;
+require(['widget-form'], function(form){
+    form.on_ready(js_hook_{{id|jsvar}}, function(){
+        {% if field_group %}
+        var obj_data = $.parseJSON(window.atob("{{ OBJECT.get_field_dict(serialize=True, group=PARAMS["group_name"])|b64encode }}"));
+        {% else %}
+        var obj_data = $.parseJSON(window.atob("{{ OBJECT.get_field_dict(serialize=True, visible_edit_only=True)|b64encode }}"));
+        {% endif %}
+        $.each(box.form_fields, function(field_name, field_widget){
+            if (field_name in obj_data) {
+                field_widget.set_value(obj_data[field_name]);
+            } else {
+                field_widget.hide(); // CONDITIONAL_NONE
+            }
+        });
+
+        //show the title and input in hover if too long.
+        if (sTitle.length > 94) {
+            sTitle = sTitle.substring(0,92)+"...";
+            $("#" + title_id).find(".box-header.my-header").find("h2").text(sTitle);
+            $("#" + title_id).find(".box-header.my-header").find("h2").parent().popover({
+                trigger: "hover",
+                content: '<div id="title-content">'+Title.trim()+'</div>',
+                placement: "bottom",
+                html: true
+            });
+        }
+
+        try{
+            var len = $("#" + title_id).find(".box-content").find(".textinput").length;
+            for(var index = 0; index < len; index++){
+                arr[index] = index;
+            }
+            $.each(arr, function(i,val){
+                if ($("#" + title_id).find(".box-content").find(".textinput").eq(i).css('display') == 'none' || $("#" + title_id).find(".box-content").find(".textinput").eq(i).parent().hasClass("union-content")){			
+                    return true;
+                }
+                else if($("#" + title_id).find(".box-content").find(".textinput").eq(i).find("input").attr("disabled")){
+                    var idValue = $("#" + title_id).find(".box-content").find(".textinput").eq(i).find("input").attr("id");
+                    if ($("#" + title_id).find(".box-content").find(".textinput").eq(i).hasClass("style-default") || $("#" + title_id).find(".box-content").find(".textinput").eq(i).hasClass("style-None")) { 
+                        if(obj_data[idValue.split('textinput_')[1]].length > 30){
+                            $("#" + title_id).find(".box-content").find("."+idValue).popover({
+                                trigger: "hover",
+                                content: '<div id="input-content">'+obj_data[idValue.split('textinput_')[1]].trim()+'</div>',
+                                placement: "bottom",
+                                html: true
+                            });
+                        }
+                    }
+                }
+            });
+        }catch (e) {
+            console.log(e);
+        }
+
+        // XXX Listen to all the widgets' form:changed event
+        box.changed_fields = []
+        $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+        $.each(box.form_fields, function(key,value){
+            box.listenTo(value, "form:changed", function(){
+                $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+                if (_.indexOf(box.changed_fields, value) == -1) {
+                    box.changed_fields.push(value)
+                }
+                box.$el.find(".btn-static").fadeIn("slow");
+                if ($(".btn-static").is(":visible")) {
+                    var buttonH = $(".btn-static").offset().top;
+                    $(function(){
+                        $(window).scroll(function(){
+                            var scrollH = $(this).scrollTop();
+                            if (scrollH >= buttonH) {
+                                $(".btn-switch").addClass("btn-fixed");
+                            }else{
+                                $(".btn-switch").removeClass("btn-fixed");
+                            }
+                        });
+                    });
+                }
+            });
+            box.listenTo(value, "form:refreshpage", function(){
+                console.log("some widget ask refresh page");
+                box.trigger("box:switch", box.url);
+            });
+        });
+
+        (function(){
+            // Special handling for SNMP Trap Host 'port' field
+            var isEditPage = true;
+            {% include 'snmp_trap_host.html' %}
+        })();
+    });
+});
+
+// The cancel action
+box.$el.find(".btn-cancel").click(function(){
+    box.trigger("box:cancel");
+    return false
+});
+
+
+
+function isShowSNMPReminder (){
+    // return true, if this rendered view is /System/Admin Tools/SNMP and the setting is not recommand Level
+    // return false, others
+    // selected element
+    let possibleElements = $(`ul[role=menu]>li[rel].selected`).get()
+    if (possibleElements.length==0){
+        // not SNMP setting submit
+        return false
+    }
+    const snmpTrapLevelSearchKey = ":"
+    let selectedLevelE = possibleElements.filter((e)=>{
+        return e.innerText.includes(snmpTrapLevelSearchKey)
+    })
+    if (typeof(selectedLevelE[0]) == 'undefined') {
+        return false
+    }
+    // based on recommandLevel, decide pop up reminder or not
+    const recommandedLevelList = ['0', '1', '2', '3']
+    let isRecommandLevels = false
+    for (let i=0;i<recommandedLevelList.length; i++){
+        if (selectedLevelE[0].innerText.includes(recommandedLevelList[i])){
+            isRecommandLevels = true
+            break
+        }
+    }
+    return !isRecommandLevels
+}
+
+// The submit action
+box.$el.find('.main-form').submit(function(e){
+    if(isShowSNMPReminder()){
+        // based on isRecommandLevels and isConfirmChange to confirm save change
+        let reminder = 'Configuring SNMP Trap Level other than "Error" is not recommended and it might impact on the performance.'
+        let isConfirmChange = confirm(reminder);
+        if(!isConfirmChange){
+            // not save the cuurent state
+            return
+        }
+    }
+
+    if(box.changed_fields.length == 0){
+        return false;
+    }
+    {%if not SESSION.allow_config %}
+        $HIVE.alert('error','Config Mode Entrance Denied', 'You are enable user, not allowed to change the configuration of APV');
+        box.trigger("box:cancel");
+        return false;
+    {% endif%}
+    var err = false;
+    var err_msg = '';
+    var post_data = {};
+    try {
+        // only submit the changed fields
+        $.each(box.changed_fields, function(key,value){
+            if (value.is_hidden()) {
+                return; // continue
+            }
+            if (value['validate'] != undefined) {
+                validate_result = value['validate']();
+                if (!validate_result[0]) {
+                    err = true;
+                    err_msg += '<b>' + value['label'] + '</b> -- ' + validate_result[1] + '<br />';
+                }
+            }
+            if (value['validate_on_blur'] != undefined) {
+                validate_result = value['validate_on_blur']();
+                if (!validate_result[0]) {
+                    err = true;
+                    err_msg += '<b>' + value['label'] + '</b> -- ' + validate_result[1] + '<br />';
+                }
+            }
+            post_data[value['name']] = value.get_value();
+        });
+    } catch (e) {
+        console.log(e);
+        return false;
+    }
+    if (err) {
+        $HIVE.alert('warning',gettext('Please correct these errors'),err_msg,false);
+        return false;
+    }
+
+    progressDlg = $HIVE.progressDlg('{% trans %}Updating...{% endtrans %}');
+    progressDlg.showPleaseWait();
+    // AJAX post the data to submit, returns [true/false, 'info or error message']
+    var submit_url = '{{ OBJECT.get_ajax_url('update') }}';
+
+    $.post(submit_url, {'post_data':JSON.stringify(post_data),'csrfmiddlewaretoken':'{{ csrf_token }}'}, function(data){
+        try {
+            if (data[0] === true) {
+		        progressDlg.hidePleaseWait();
+                var dict_name = {'info':gettext('Info'), 'warning':gettext('Warning')}
+                if (data[2] !== []) {
+                    for (i = 0; i < data[2].length; i++) {
+                        $HIVE.alert(data[2][i][0], dict_name[data[2][i][0]], data[2][i][1])
+                    }
+                }
+                // Refresh the page
+                {% if field_group %}
+                    var group_arg = "?group_name={{ PARAMS['group_name'] }}";
+                {% else %}
+                    var group_arg = "?";
+                {% endif %}
+                {% if PARAMS and 'standalone' in PARAMS %}
+                window.location.href = "{{ REQUEST.path.split('/')[-1]|escape_url }}" + group_arg + "&standalone=True";
+                {% else %}
+                box.trigger("box:finish", "{{ OBJECT.get_ajax_url('box_instance_config')}}" + group_arg);
+                {% endif %}
+            } else {
+		        progressDlg.hidePleaseWait();
+                $HIVE.alert('error','{{ OBJECT.repr()|e }} {% trans %}Update Error{% endtrans %}', data[1]);
+                return false;
+            }
+        } catch (e) {
+            $HIVE.alert('error', 'Fatal Error', 'Invalid response from server');
+            return false;
+        }
+    }, "json").fail(function(){
+        progressDlg.hidePleaseWait();
+        if (_.has(post_data, 'enable_webui') && !(post_data.enable_webui)) {
+            $HIVE.alert('warning','warning','WebUI has been disabled. Your current WebUI session is terminated.');
+        }else{
+            $HIVE.alert('error','Fatal Error','Fail sending data to server');
+        }
+        return false
+    });
+    return false;
+});
+$HIVE.set_help_link('{{ MODEL._meta.get_help_link() }}');
+var action_functions = {
+    csrf_token:"{{ csrf_token }}",
+    allow_config:{% if not SESSION.allow_config %} false {% else %} true {% endif%},
+    popup_cb: function(args){
+        var rsp = args;
+        if (rsp[1]['config_change']) {
+            // need refresh the page
+            console.log("action finish, need refresh page");
+            box.trigger("box:switch", box.url);
+        } else {
+            //seems no need to do
+        }
+    },
+    get_data: function(){
+        data = {
+            '__pk_list':['{{ OBJECT.pk_str()|escape_url }}']
+        };
+        return data;
+    },
+};
+{% if field_group %}
+init_action('group_actions', action_functions);
+{% else %}
+    {% set group_num=MODEL._meta.field_groups|length %}
+    {% for group_name, each_field_group in MODEL._meta.field_groups.iteritems() if each_field_group.visible_in_edit(OBJECT) and not (SESSION.is_segment_user and each_field_group.seg_hidden) %}
+init_action('group_actions_{{ group_name }}' , action_functions);
+    {% endfor %}
+{% endif %}
+{% if 0 %}
+</script>
+{% endif %}
+{% endblock %}
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/SNMPV3Servers/box_instance_config.html
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/SNMPV3Servers/box_instance_config.html	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/SNMPV3Servers/box_instance_config.html	(working copy)
@@ -0,0 +1,384 @@
+{# Required Context Variables: MODEL, MANAGER, OBJECT #}
+{% extends "box.html" %}
+
+{% block box_content %}
+{% import "widgets/form.html" as form %}
+{% import "widgets/action.html" as Action %}
+{% set field_group=MODEL._meta.field_groups[PARAMS['group_name']] %}
+    <div class="box-header my-header">
+        <div class="box-icon-title">
+            <i class="fa fa-cogs"></i>
+        </div>
+        <h2>
+            {% if MODEL._meta.profile %}
+                {% if not field_group or field_group.name == 'default' %}
+                    {{ MODEL._meta.verbose_name | truncate(30, True) }}
+                {% else %}
+                    {{ MODEL._meta.verbose_name | truncate(30, True) }} - {{ field_group.verbose_name | truncate(30, True) }}
+                {% endif %}
+            {% else %}
+                {% if field_group %}
+                    {{ OBJECT.repr() | truncate(30, True) }} - {{ field_group.verbose_name | truncate(30, True) }}
+                {% else %}
+                    {{ OBJECT.repr() | truncate(30, True) }}
+                {% endif %}
+            {% endif %}
+        </h2>
+    </div>
+    <div class="box-content">
+    <form class="form-horizontal main-form">
+            <script type="text/javascript">
+            var js_hook_{{ id|jsvar }} = new Object();
+            js_hook_{{ id|jsvar }}.id = "{{ id|jsvar}}";
+            js_hook_{{ id|jsvar }}.form_fields = {};
+            js_hook_{{ id|jsvar }}.ready_total = 0;
+            js_hook_{{ id|jsvar }}.ready_count = 0;
+            </script>
+            {% if field_group %}
+            <div class="row-fluid">
+                <div class="span12 with-min-width field-group-box">
+                    <fieldset>
+                    <div class="group_actions" >
+                    {% for action in field_group.related_actions(OBJECT) if not (SESSION.is_segment_user and action.seg_hidden) %}
+                        {{ Action.ActionWidget(action.name, action) }}
+                    {% endfor %}
+                    </div>
+                    {% for field in field_group.fields if field.visible_in_edit() and not field.is_external_component() and not (SESSION.is_segment_user and field.seg_hidden) and not (field.is_unprivileged and SESSION.is_unprivileged_role) %}
+                        {% set context_of_field = (PARAMS.get("context", {})|url2obj).get(field.name, None) %}
+                        {% if context_of_field != None %}
+                            {{ field.static_widget(manager=MANAGER, context_value=context_of_field[0], context_repr=context_of_field[1]).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token}) }}
+                        {% else %}
+                            {{ field.default_widget(editable=field.editable, model_instance=OBJECT, manager=MANAGER).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token, 'session':SESSION}) }}
+                        {% endif %}
+                    {% endfor %}
+                    </fieldset>
+                </div>
+            </div><!-- row-fluid -->
+            {% else %}
+            {% set group_num=MODEL._meta.field_groups|length %}
+            {% for group_name, each_field_group in MODEL._meta.field_groups.iteritems() if each_field_group.visible_in_edit(OBJECT) and not (SESSION.is_segment_user and each_field_group.seg_hidden) %}
+            {% set has_fields={"bool":false} %}
+            {% for field in each_field_group.fields if field.visible_in_edit() and not field.hide_in_popup_edit and not field.is_external_component() and not (SESSION.is_segment_user and field.seg_hidden) %}
+                 {% if field.name %}
+                     {% if has_fields.update({"bool":true}) %}{% endif %}
+                 {% endif %}
+            {% endfor %}
+            <div class="row-fluid">
+                <div class="span12 with-min-width field-group-box">
+                    {% if each_field_group.verbose_name and group_num > 1 %}
+                    <a id="{{ each_field_group.name }}"></a>
+                    {% if has_fields.bool %}
+                        <legend>{{ each_field_group.verbose_name }}</legend>
+                    {% endif %}
+                    {% endif %}
+                    <fieldset>
+                    <div class="group_actions_{{ group_name }}" >
+                    {% for action in each_field_group.related_actions(OBJECT) %}
+                        {% if not action.edit_hidden %}
+                            {{ Action.ActionWidget(action.name, action) }}
+                        {% endif %}
+                    {% endfor %}
+                    </div>
+                    {% for field in each_field_group.fields if field.visible_in_edit() and not field.hide_in_popup_edit and not field.is_external_component() and not (SESSION.is_segment_user and field.seg_hidden) %}
+                        {% set context_of_field = (PARAMS.get("context", {})|url2obj).get(field.name, None) %}
+                        {% if context_of_field != None %}
+                            {{ field.static_widget(manager=MANAGER, context_value=context_of_field[0], context_repr=context_of_field[1]).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token}) }}
+                        {% else %}
+                            {{ field.default_widget(editable=field.editable, model_instance=OBJECT, manager=MANAGER).render(form, 'js_hook_'+id|jsvar, {'form':form, 'csrf_token':csrf_token,'session':SESSION}) }}
+                        {% endif %}
+                    {% endfor %}
+                    </fieldset>
+                </div>
+            </div><!-- row-fluid -->
+            {% endfor %}
+            {% endif %}
+            <div class="btn-static" style="display:none;">
+                <div class="btn-switch">
+                    <button type="submit" class="btn btn-action">{% trans %}Save Changes{% endtrans %}</button>
+                    <button type="button" class="btn btn-default btn-cancel">{% trans %}Cancel{% endtrans %}</button>
+                </div>
+            </div>
+    </form>
+    </div><!-- box-content -->
+{% endblock box_content %}
+
+{% block box_script %}
+{% if 0 %}
+<script type="text/javascript">
+// Just make editor happy to highlight the scripts
+{% endif %}
+
+{% set field_group=MODEL._meta.field_groups[PARAMS['group_name']] %}
+
+var field_group_dict = {{ MODEL._meta.get_field_group_dict()|json_dumps }};
+var group_condition_dict = {{ MODEL._meta.get_group_condition_dict()|json_dumps }};
+var field_condition_dict = {{ MODEL._meta.get_field_condition_dict()|json_dumps }};
+// copy the hook's data into box
+var hook = js_hook_{{ id|jsvar }};
+var title_id = hook['id'].replace(/_/g,'-');
+var Title = $("#" + title_id).find(".box-header.my-header").find("h2").text();
+var sTitle = Title.trim();
+var arr = [];
+
+box.form_fields = hook.form_fields;
+require(['widget-form'], function(form){
+    form.on_ready(js_hook_{{id|jsvar}}, function(){
+        {% if field_group %}
+        var obj_data = $.parseJSON(window.atob("{{ OBJECT.get_field_dict(serialize=True, group=PARAMS["group_name"])|b64encode }}"));
+        {% else %}
+        var obj_data = $.parseJSON(window.atob("{{ OBJECT.get_field_dict(serialize=True, visible_edit_only=True)|b64encode }}"));
+        {% endif %}
+        $.each(box.form_fields, function(field_name, field_widget){
+            if (field_name in obj_data) {
+                field_widget.set_value(obj_data[field_name]);
+            } else {
+                field_widget.hide(); // CONDITIONAL_NONE
+            }
+        });
+
+        //show the title and input in hover if too long.
+        if (sTitle.length > 94) {
+            sTitle = sTitle.substring(0,92)+"...";
+            $("#" + title_id).find(".box-header.my-header").find("h2").text(sTitle);
+            $("#" + title_id).find(".box-header.my-header").find("h2").parent().popover({
+                trigger: "hover",
+                content: '<div id="title-content">'+Title.trim()+'</div>',
+                placement: "bottom",
+                html: true
+            });
+        }
+
+        try{
+            var len = $("#" + title_id).find(".box-content").find(".textinput").length;
+            for(var index = 0; index < len; index++){
+                arr[index] = index;
+            }
+            $.each(arr, function(i,val){
+                if ($("#" + title_id).find(".box-content").find(".textinput").eq(i).css('display') == 'none' || $("#" + title_id).find(".box-content").find(".textinput").eq(i).parent().hasClass("union-content")){			
+                    return true;
+                }
+                else if($("#" + title_id).find(".box-content").find(".textinput").eq(i).find("input").attr("disabled")){
+                    var idValue = $("#" + title_id).find(".box-content").find(".textinput").eq(i).find("input").attr("id");
+                    if ($("#" + title_id).find(".box-content").find(".textinput").eq(i).hasClass("style-default") || $("#" + title_id).find(".box-content").find(".textinput").eq(i).hasClass("style-None")) { 
+                        if(obj_data[idValue.split('textinput_')[1]].length > 30){
+                            $("#" + title_id).find(".box-content").find("."+idValue).popover({
+                                trigger: "hover",
+                                content: '<div id="input-content">'+obj_data[idValue.split('textinput_')[1]].trim()+'</div>',
+                                placement: "bottom",
+                                html: true
+                            });
+                        }
+                    }
+                }
+            });
+        }catch (e) {
+            console.log(e);
+        }
+
+        // XXX Listen to all the widgets' form:changed event
+        box.changed_fields = []
+        $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+        $.each(box.form_fields, function(key,value){
+            box.listenTo(value, "form:changed", function(){
+                $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+                if (_.indexOf(box.changed_fields, value) == -1) {
+                    box.changed_fields.push(value)
+                }
+                box.$el.find(".btn-static").fadeIn("slow");
+                if ($(".btn-static").is(":visible")) {
+                    var buttonH = $(".btn-static").offset().top;
+                    $(function(){
+                        $(window).scroll(function(){
+                            var scrollH = $(this).scrollTop();
+                            if (scrollH >= buttonH) {
+                                $(".btn-switch").addClass("btn-fixed");
+                            }else{
+                                $(".btn-switch").removeClass("btn-fixed");
+                            }
+                        });
+                    });
+                }
+            });
+            box.listenTo(value, "form:refreshpage", function(){
+                console.log("some widget ask refresh page");
+                box.trigger("box:switch", box.url);
+            });
+        });
+
+        (function(){
+            // Special handling for SNMP Trap Host 'port' field
+            var isEditPage = true;
+            {% include 'snmp_trap_host.html' %}
+        })();
+    });
+});
+
+// The cancel action
+box.$el.find(".btn-cancel").click(function(){
+    box.trigger("box:cancel");
+    return false
+});
+
+
+
+function isShowSNMPReminder (){
+    // return true, if this rendered view is /System/Admin Tools/SNMP and the setting is not recommand Level
+    // return false, others
+    // selected element
+    let possibleElements = $(`ul[role=menu]>li[rel].selected`).get()
+    if (possibleElements.length==0){
+        // not SNMP setting submit
+        return false
+    }
+    const snmpTrapLevelSearchKey = ":"
+    let selectedLevelE = possibleElements.filter((e)=>{
+        return e.innerText.includes(snmpTrapLevelSearchKey)
+    })
+    if (typeof(selectedLevelE[0]) == 'undefined') {
+        return false
+    }
+    // based on recommandLevel, decide pop up reminder or not
+    const recommandedLevelList = ['0', '1', '2', '3']
+    let isRecommandLevels = false
+    for (let i=0;i<recommandedLevelList.length; i++){
+        if (selectedLevelE[0].innerText.includes(recommandedLevelList[i])){
+            isRecommandLevels = true
+            break
+        }
+    }
+    return !isRecommandLevels
+}
+
+// The submit action
+box.$el.find('.main-form').submit(function(e){
+    if(isShowSNMPReminder()){
+        // based on isRecommandLevels and isConfirmChange to confirm save change
+        let reminder = 'Configuring SNMP Trap Level other than "Error" is not recommended and it might impact on the performance.'
+        let isConfirmChange = confirm(reminder);
+        if(!isConfirmChange){
+            // not save the cuurent state
+            return
+        }
+    }
+
+    if(box.changed_fields.length == 0){
+        return false;
+    }
+    {%if not SESSION.allow_config %}
+        $HIVE.alert('error','Config Mode Entrance Denied', 'You are enable user, not allowed to change the configuration of APV');
+        box.trigger("box:cancel");
+        return false;
+    {% endif%}
+    var err = false;
+    var err_msg = '';
+    var post_data = {};
+    try {
+        // only submit the changed fields
+        $.each(box.changed_fields, function(key,value){
+            if (value.is_hidden()) {
+                return; // continue
+            }
+            if (value['validate'] != undefined) {
+                validate_result = value['validate']();
+                if (!validate_result[0]) {
+                    err = true;
+                    err_msg += '<b>' + value['label'] + '</b> -- ' + validate_result[1] + '<br />';
+                }
+            }
+            if (value['validate_on_blur'] != undefined) {
+                validate_result = value['validate_on_blur']();
+                if (!validate_result[0]) {
+                    err = true;
+                    err_msg += '<b>' + value['label'] + '</b> -- ' + validate_result[1] + '<br />';
+                }
+            }
+            post_data[value['name']] = value.get_value();
+        });
+    } catch (e) {
+        console.log(e);
+        return false;
+    }
+    if (err) {
+        $HIVE.alert('warning',gettext('Please correct these errors'),err_msg,false);
+        return false;
+    }
+
+    progressDlg = $HIVE.progressDlg('{% trans %}Updating...{% endtrans %}');
+    progressDlg.showPleaseWait();
+    // AJAX post the data to submit, returns [true/false, 'info or error message']
+    var submit_url = '{{ OBJECT.get_ajax_url('update') }}';
+
+    $.post(submit_url, {'post_data':JSON.stringify(post_data),'csrfmiddlewaretoken':'{{ csrf_token }}'}, function(data){
+        try {
+            if (data[0] === true) {
+                progressDlg.hidePleaseWait();
+                var dict_name = {'info':gettext('Info'), 'warning':gettext('Warning')}
+                if (data[2] !== []) {
+                    for (i = 0; i < data[2].length; i++) {
+                        $HIVE.alert(data[2][i][0], dict_name[data[2][i][0]], data[2][i][1])
+                    }
+                }
+                // Refresh the page
+                {% if field_group %}
+                    var group_arg = "?group_name={{ PARAMS['group_name'] }}";
+                {% else %}
+                    var group_arg = "?";
+                {% endif %}
+                {% if PARAMS and 'standalone' in PARAMS %}
+                window.location.href = "{{ REQUEST.path.split('/')[-1]|escape_url }}" + group_arg + "&standalone=True";
+                {% else %}
+                box.trigger("box:finish", "{{ OBJECT.get_ajax_url('box_instance_config')}}" + group_arg);
+                {% endif %}
+            } else {
+		        progressDlg.hidePleaseWait();
+                $HIVE.alert('error','{{ OBJECT.repr()|e }} {% trans %}Update Error{% endtrans %}', data[1]);
+                return false;
+            }
+        } catch (e) {
+            $HIVE.alert('error', 'Fatal Error', 'Invalid response from server');
+            return false;
+        }
+    }, "json").fail(function(){
+        progressDlg.hidePleaseWait();
+        if (_.has(post_data, 'enable_webui') && !(post_data.enable_webui)) {
+            $HIVE.alert('warning','warning','WebUI has been disabled. Your current WebUI session is terminated.');
+        }else{
+            $HIVE.alert('error','Fatal Error','Fail sending data to server');
+        }
+        return false
+    });
+    return false;
+});
+$HIVE.set_help_link('{{ MODEL._meta.get_help_link() }}');
+var action_functions = {
+    csrf_token:"{{ csrf_token }}",
+    allow_config:{% if not SESSION.allow_config %} false {% else %} true {% endif%},
+    popup_cb: function(args){
+        var rsp = args;
+        if (rsp[1]['config_change']) {
+            // need refresh the page
+            console.log("action finish, need refresh page");
+            box.trigger("box:switch", box.url);
+        } else {
+            //seems no need to do
+        }
+    },
+    get_data: function(){
+        data = {
+            '__pk_list':['{{ OBJECT.pk_str()|escape_url }}']
+        };
+        return data;
+    },
+};
+{% if field_group %}
+init_action('group_actions', action_functions);
+{% else %}
+    {% set group_num=MODEL._meta.field_groups|length %}
+    {% for group_name, each_field_group in MODEL._meta.field_groups.iteritems() if each_field_group.visible_in_edit(OBJECT) and not (SESSION.is_segment_user and each_field_group.seg_hidden) %}
+init_action('group_actions_{{ group_name }}' , action_functions);
+    {% endfor %}
+{% endif %}
+{% if 0 %}
+</script>
+{% endif %}
+{% endblock %}
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/Server/box_model_add_wizard.html
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/Server/box_model_add_wizard.html	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/admintools/snmp/Server/box_model_add_wizard.html	(working copy)
@@ -0,0 +1,225 @@
+{# Required Context Variables: MODEL, MANAGER, [CONCRETE_MODEL, CONCRETE_MANAGER]
+   This implements a wizard for adding an instance for a model
+#}
+{% extends "box.html" %}
+
+{% block custom_box_class %}box-model-add modal-content{% endblock %}
+
+{% block box_content %}
+{% import "widgets/form.html" as form %}
+
+{% if CONCRETE_MODEL %}
+    {% set CURRENT_MODEL = CONCRETE_MODEL %}
+{% else %}
+    {% set CURRENT_MODEL = MODEL %}
+{% endif %}
+
+<div class="box-header">
+    <div class="box-icon-title">
+        <i class="fa fa-plus-circle"></i>
+    </div>
+    <h2>{{ gettext('New %s')%CURRENT_MODEL._meta.verbose_name }}</h2>
+</div>
+<div class="box-content">
+    <script type="text/javascript">
+    var js_hook_{{ id|jsvar }} = new Object();
+    js_hook_{{ id|jsvar }}.id = "{{ id|jsvar}}";
+    js_hook_{{ id|jsvar }}.form_fields = {};
+    js_hook_{{ id|jsvar }}.ready_total = 0;
+    js_hook_{{ id|jsvar }}.ready_count = 0;
+    </script>
+
+    <form class="form-horizontal main-form" role="form">
+        <div class="padded">
+    {% for field_group in CURRENT_MODEL._meta.field_groups.values() %}
+        {% if field_group.isbasic %}
+        <div class="row-fluid">
+            <div class="span12 with-min-width field-group-box">
+            <fieldset>
+            {% if CURRENT_MODEL._meta.abstract %}
+                {% for field in field_group.fields %}
+                    {% if field.name in CURRENT_MODEL._meta.all_deriving_fields and field.visible_in_add() and not (SESSION.is_segment_user and field.seg_hidden) %}
+                        {{ field.default_widget().render(form, 'js_hook_'+id|jsvar, {'abstract':True, 'form':form,'csrf_token':csrf_token,'CURRENT_MODEL':CURRENT_MODEL}) }}
+                    {% endif %}
+                {% endfor %}
+            {% else %}
+                {% for field in field_group.fields %}
+                    {% if field.visible_in_add() and not (SESSION.is_segment_user and field.seg_hidden) %}
+                        {% set context_of_field = (PARAMS.get("context", {})|url2obj).get(field.name, None) %}
+                        {% set concrete_initial_value = (PARAMS.get("concrete", {})|url2obj).get(field.name, None) %}
+                        {% if context_of_field != None %}
+                            {{ field.static_widget(manager=MANAGER, context_value=context_of_field[0], context_repr=context_of_field[1]).render(form, 'js_hook_'+id|jsvar, {'form':form,'csrf_token':csrf_token}) }}
+                        {% else %}
+                            {% set editable = True %}
+                            {{ field.default_widget(editable=editable, initial_value=concrete_initial_value).render(form, 'js_hook_'+id|jsvar, {'form':form,'csrf_token':csrf_token}) }}
+                        {% endif %}
+                    {% endif %}
+                {% endfor %}
+            {% endif %}
+            </fieldset>
+            </div>
+        </div><!-- row-fluid -->
+        {% endif %}
+    {% endfor %}
+        </div>
+        <div class="form-actions col-md-offset-3">
+            {% if not CURRENT_MODEL._meta.abstract and CURRENT_MODEL._meta.addable %}
+            <button type="submit" class="btn btn-action create-submit">{{ CURRENT_MODEL._meta.button_submit_text(CURRENT_MODEL._meta) }}</button>
+            {% endif %}
+            <button type="button" data-dismiss="modal" class="btn btn-default btn-cancel">{% trans %}Cancel{% endtrans %}</button>
+        </div><!-- form-actions -->
+    </form>
+</div>
+{% endblock box_content %}
+
+{% block box_script %}
+
+{% if CONCRETE_MODEL %}
+    {% set CURRENT_MODEL = CONCRETE_MODEL %}
+{% else %}
+    {% set CURRENT_MODEL = MODEL %}
+{% endif %}
+{% if 0 %}
+<script type="text/javascript">
+// Just make editor happy to highlight the scripts
+{% endif %}
+
+$HIVE.set_help_link('{{ CURRENT_MODEL._meta.get_help_link() }}');
+
+// the group condition datastructure
+var field_group_dict = {{ CURRENT_MODEL._meta.get_field_group_dict()|json_dumps }};
+var group_condition_dict = {{ CURRENT_MODEL._meta.get_group_condition_dict()|json_dumps }};
+var field_condition_dict = {{ CURRENT_MODEL._meta.get_field_condition_dict()|json_dumps }};
+var field_default_value_confition_dict = {{ CURRENT_MODEL._meta.get_field_default_value_confition_dict()|json_dumps }};
+
+// copy the hook's data into box
+var hook = js_hook_{{ id|jsvar }};
+box.form_fields = hook.form_fields;
+require(['widget-form', 'underscore'], function(form){
+    form.on_ready(js_hook_{{id|jsvar}}, function(){
+        $HIVE.log('all widgets are ready')
+        // The concrete class auto-switch action
+        var switch_list = {{ MODEL._meta.all_deriving_fields }};
+        for (i in switch_list) {
+            var tgt = box.form_fields[switch_list[i]];
+            tgt.change(function(){
+                if (tgt.get_value() == "") {
+                    return;
+                }
+                //var arg_list = "";
+                var concrete_dict = {};
+                for (j in switch_list) {
+                    concrete_dict[switch_list[j]] = box.form_fields[switch_list[j]].get_value();
+                    //arg_list += "&" + switch_list[j] + "=" + box.form_fields[switch_list[i]].get_value();
+                }
+                //arg_list = "?" + arg_list.slice(1)
+                var existing_args = "{{ PARAMSTR }}";
+                console.log("existing_args are: " + existing_args)
+                var arg_list = "?" + $HIVE.dict_to_param({"concrete":concrete_dict}) + "&" + existing_args;
+                var url = "{{ '/'+'/'.join(REQUEST.META.REQUEST_URI.split('/')[1:-1])+'/_model_quantity_check' }}" + arg_list;
+                $(".create-submit").attr("disabled", true);
+                $.post(url, {'csrfmiddlewaretoken':'{{ csrf_token }}'}, function(result){
+                    $(".create-submit").removeAttr("disabled");
+                    response = result;
+                    if (response) {
+                        {% if PARAMS and 'standalone' in PARAMS %}
+                        window.location.href = "{{ REQUEST.META.REQUEST_URI.split('?')[0].split('/')[-1] }}" + arg_list;
+                        {% else %}
+                        box.trigger("box:switch", "{{ '/'+'/'.join(REQUEST.META.REQUEST_URI.split('?')[0].split('/')[1:]) }}" + arg_list);
+                        {% endif %}
+                    } else {
+                        $HIVE.alert('error','Quantity Limit','You have reach the quantity limit for this model, could not add any more.');
+                        tgt.set_value("");
+                    }
+                }, 'json');
+            });
+        }
+
+        // Display or hide fields based on the group condition
+        $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+        $HIVE.set_default_value_based_on_condition(box, field_default_value_confition_dict);
+        $.each(box.form_fields, function(key,value){
+            box.listenTo(value, "form:changed", function(){
+                $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+            });
+        });
+
+        (function(){
+            // Special handling for SNMP Trap Host 'port' field
+            var isEditPage = false;
+            {% include 'snmp_trap_host.html' %}
+        })();
+
+    }); // form.on_ready
+});
+
+// The cancel action
+box.$el.find(".btn-cancel").click(function(){
+    $(".create-submit").removeAttr("disabled");
+    box.trigger("box:cancel"); // if it's in a popup window, it closes
+    false
+});
+
+// The submit action
+box.$el.find('.main-form').submit(function(e){
+    var err = false;
+    var err_msg = '';
+    var post_data = {};
+    $.each(box.form_fields, function(key,value){
+        if (value.is_hidden()) {
+            return; // continue
+        }
+        if (value['validate'] != undefined) {
+            validate_result = value['validate']();
+            if (!validate_result[0]) {
+                err = true;
+                err_msg += '<b>' + value['label'] + '</b> -- ' + validate_result[1] + '<br />';
+            }
+        }
+        if (value['validate_on_blur'] != undefined) {
+            validate_result = value['validate_on_blur']();
+            if (!validate_result[0]) {
+                err = true;
+                err_msg += '<b>' + value['label'] + '</b> -- ' + validate_result[1] + '<br />';
+            }
+        }
+        post_data[value['name']] = value.get_value();
+    });
+
+    if (err) {
+        $HIVE.alert('error',gettext('Please correct these errors'),err_msg,false);
+        return false;
+    }
+
+    progressDlg = $HIVE.progressDlg('{% trans %}Adding...{% endtrans %}');
+    progressDlg.showPleaseWait();
+    // AJAX post the data to submit, returns [true/false, 'info or error message']
+    var submit_url = '{{ CURRENT_MODEL._meta.get_ajax_url('add') }}';
+
+    console.log('post data: ' + JSON.stringify(post_data));
+    $.post(submit_url, {'post_data':JSON.stringify(post_data),'csrfmiddlewaretoken':'{{ csrf_token }}'}, function(data){
+        try {
+            if (data[0] == true) {
+                progressDlg.hidePleaseWait();
+                box.trigger("box:finish", data[1], data[2]);
+            } else {
+                progressDlg.hidePleaseWait();
+                $HIVE.alert('error','{{ CURRENT_MODEL._meta.verbose_name }} {% trans %}Creation Error{% endtrans %}', data[1])
+                return false;
+            }
+        } catch (e) {
+            $HIVE.alert('error', 'Fatal Error', 'Invalid response from server');
+            return false;
+        }
+    }, "json").fail(function(){
+        progressDlg.hidePleaseWait();
+        $HIVE.alert('error','Fatal Error','Fail sending data to server');
+        return false
+    });
+    return false;
+}); // .main-form submit
+
+{% if 0 %}
+</script>
+{% endif %}
+{% endblock box_script %}
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/snmp_trap_host.html
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/snmp_trap_host.html	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/snmp_trap_host.html	(working copy)
@@ -0,0 +1,77 @@
+// isEditPage is true if this is used on an edit page, false otherwise
+// Please include this template within a function scope where isEditPage is defined
+var portWidget = box.form_fields && box.form_fields['port'];
+if (!portWidget) return;
+
+var widgetEle = $("#" + portWidget.widget.id);
+var input = widgetEle.find("input");
+
+var showSaveChanges = function(){
+    try {
+        // Run the same side-effects as the form:changed listener so Save Changes appears
+        $HIVE.check_form_condition(box, field_group_dict, group_condition_dict, field_condition_dict);
+        if (_.indexOf(box.changed_fields, portWidget) == -1) {
+            box.changed_fields.push(portWidget);
+        }
+        box.$el.find(".btn-static").fadeIn("slow");
+        if ($(".btn-static").is(":visible")) {
+            var buttonH = $(".btn-static").offset().top;
+            $(function(){
+                $(window).off('scroll.box_static');
+                $(window).on('scroll.box_static', function(){
+                    var scrollH = $(this).scrollTop();
+                    if (scrollH >= buttonH) {
+                        $(".btn-switch").addClass("btn-fixed");
+                    } else {
+                        $(".btn-switch").removeClass("btn-fixed");
+                    }
+                });
+            });
+        }
+    } catch (e) {
+        try { portWidget.trigger && portWidget.trigger('form:changed'); } catch (e2) {}
+    }
+};
+
+input.on("input", function(){
+    var val = $(this).val();
+    var n = parseInt(val, 10);
+    if (isNaN(n) || (n !== 161 && n !== 162)) {
+        widgetEle.find(".error-info").html(interpolate("{{ gettext('The value should be %s or %s.') }}", [161, 162]));
+        widgetEle.find(".error-info").show();
+        widgetEle.find(".error-sign").show();
+    } else {
+        widgetEle.find(".error-info").html("");
+        widgetEle.find(".error-info").hide();
+        widgetEle.find(".error-sign").hide();
+    }
+    if (isEditPage) {
+        // notify the form that this widget changed so the Save Changes button appears
+        showSaveChanges();
+    }
+});
+if (isEditPage) {
+    // also show Save Changes on focus or click (user requested click to show)
+    input.on('focus click', function(){
+        showSaveChanges();
+    });
+}
+
+// Make inline input handler show immediate feedback, but avoid duplicate
+// messages in the submit alert. Use validate() as the single canonical
+// final check and make validate_on_blur a noop so submit loop won't
+// append the same error twice (submit calls both validate and
+// validate_on_blur).
+portWidget.validate_on_blur = function(){
+    return [true, ""]; // no-op for blur (inline handler already shows message)
+};
+
+// final validation used at submit time
+portWidget.validate = function(){
+    var val = portWidget.get_value();
+    var n = parseInt(val, 10);
+    if (isNaN(n) || (n !== 161 && n !== 162)) {
+        return [false, interpolate("{{ gettext('The value should be %s or %s.') }}", [161, 162])];
+    }
+    return [true, ""];
+};
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/en/LC_MESSAGES/django.po
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/en/LC_MESSAGES/django.po	(revision 39870)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/en/LC_MESSAGES/django.po	(working copy)
@@ -5423,6 +5423,9 @@
 msgid "The value should between %s to %s."
 msgstr ""
 
+msgid "The value should be %s or %s."
+msgstr ""
+
 #: apv/models/loadbalancing/slb/vs/http/global/cache.py:156
 msgid ""
 "The value of the expiration time has exceeded the maximum value "
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/ja/LC_MESSAGES/django.po
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/ja/LC_MESSAGES/django.po	(revision 39870)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/ja/LC_MESSAGES/django.po	(working copy)
@@ -5606,6 +5606,9 @@
 msgid "The value should between %s to %s."
 msgstr "値は%sと%sの間でなければなりません"
 
+msgid "The value should be %s or %s."
+msgstr "値は%sまたは%sである必要があります"
+
 #: apv/models/loadbalancing/slb/vs/http/global/cache.py:156
 msgid ""
 "The value of the expiration time has exceeded the maximum value "
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/zh_CN/LC_MESSAGES/django.po
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/zh_CN/LC_MESSAGES/django.po	(revision 39870)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/zh_CN/LC_MESSAGES/django.po	(working copy)
@@ -5588,6 +5588,9 @@
 msgid "The value should between %s to %s."
 msgstr "该值应介于%s和%s之间"
 
+msgid "The value should be %s or %s."
+msgstr "该值应为%s或%s"
+
 #: apv/models/loadbalancing/slb/vs/http/global/cache.py:156
 msgid ""
 "The value of the expiration time has exceeded the maximum value "
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/zh_TW/LC_MESSAGES/django.po
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/zh_TW/LC_MESSAGES/django.po	(revision 39870)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/locale/zh_TW/LC_MESSAGES/django.po	(working copy)
@@ -5588,6 +5588,9 @@
 msgid "The value should between %s to %s."
 msgstr "該值應介於%s和%s之間"
 
+msgid "The value should be %s or %s."
+msgstr "該值應為%s或%s"
+
 #: apv/models/loadbalancing/slb/vs/http/global/cache.py:156
 msgid ""
 "The value of the expiration time has exceeded the maximum value "
