the environment page in frontend of testing-scheduler 15/60015/5
authorLeoQi <QibinZheng2014@tongji.edu.cn>
Thu, 19 Jul 2018 18:58:47 +0000 (02:58 +0800)
committerLeoQi <QibinZheng2014@tongji.edu.cn>
Thu, 30 Aug 2018 11:06:15 +0000 (19:06 +0800)
JIRA: BOTTLENECK-238

the environment page provides configuration setting operations.

Change-Id: I79f93bfc0c66c37a3f58d042669cbb61d3bad848
Signed-off-by: Zheng Qibin <QibinZheng2014@tongji.edu.cn>
testing-scheduler/ui/src/components/env_component/api_param.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/env_component/base_input.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/env_component/service_api.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/env_component/service_modal.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/environment.vue [new file with mode: 0644]

diff --git a/testing-scheduler/ui/src/components/env_component/api_param.vue b/testing-scheduler/ui/src/components/env_component/api_param.vue
new file mode 100644 (file)
index 0000000..300b6a4
--- /dev/null
@@ -0,0 +1,63 @@
+<template>\r
+    <div class="row">\r
+         <div class="form-group">\r
+            <label class="col-lg-3 control-label">Params</label>\r
+            <div class="col-lg-2">\r
+                <button type="button" class="btn btn-primary btn-sm" v-on:click="addNewParam()">New</button>\r
+            </div>\r
+         </div>\r
+         <div class="form-group">\r
+            <div class="col-lg-offset-2 col-lg-8">\r
+                <div class="table-responsive">\r
+                 <table class="table table-bordered text-center">\r
+                    <thead>\r
+                        <tr>\r
+                            <th>name</th>\r
+                            <th class="text-center">description</th>\r
+                            <th class="text-center">operation</th>\r
+                        </tr>\r
+                    </thead>\r
+                    <tbody>\r
+                        <tr v-for="param in params">\r
+                            <td><input type="text" class="form-control text-center" style="border: 0px" v-model="param['name']"></td>\r
+                            <td><input type="text" class="form-control text-center" style="border: 0px" v-bind:title="param['description']" v-model="param['description']"></td>\r
+                            <td>\r
+                                <button type="button" class="btn btn-white" v-on:click="deleteParam(param['name'])">\r
+                                    <i class="fa fa-trash"></i>\r
+                                </button>\r
+                            </td>\r
+                        </tr>\r
+                    </tbody>\r
+                 </table>\r
+                </div>\r
+             </div>\r
+          </div>\r
+     </div>\r
+</template>\r
+<script>\r
+export default {\r
+    props: ["params"],\r
+    data: function() {\r
+        return {\r
+            paramArr: this.params\r
+        }\r
+    },\r
+    watch: {\r
+        paramArr: function(){\r
+            this.$emit("params", this.paramArr);\r
+        }\r
+    },\r
+    methods: {\r
+        addNewParam: function() {\r
+            this.params.push({'name': '', 'description': ''});\r
+        },\r
+        deleteParam: function(paramName) {\r
+            for(var i = 0;i < this.params.length; i++) {\r
+                if(paramName == this.params[i]['name']) {\r
+                    this.params.splice(i, 1);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+</script>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/env_component/base_input.vue b/testing-scheduler/ui/src/components/env_component/base_input.vue
new file mode 100644 (file)
index 0000000..d96921a
--- /dev/null
@@ -0,0 +1,20 @@
+<template>\r
+    <div class="form-group">\r
+        <label class="col-lg-3 control-label">{{ name }}</label>\r
+        <div class="col-lg-7">\r
+            <input type="text" class="form-control" v-bind:value="value" v-on:input="$emit('input', $event.target.value)">\r
+        </div>\r
+    </div>\r
+</template>\r
+<script>\r
+export default {\r
+    props: ['name', 'value'],\r
+    data: function() {\r
+        return {\r
+            inputName: this.name,\r
+            inputValue: this.value,\r
+            fake: "abc"\r
+        }\r
+    }\r
+}\r
+</script>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/env_component/service_api.vue b/testing-scheduler/ui/src/components/env_component/service_api.vue
new file mode 100644 (file)
index 0000000..2acd499
--- /dev/null
@@ -0,0 +1,112 @@
+<template>\r
+    <div class="panel panel-success">\r
+            <div class="panel-heading">\r
+                <button type="button" class="btn btn-xs btn-danger pull-right" v-on:click="deleteApi(name)">Delete</button>\r
+                <h5 class="panel-title">\r
+                    <a data-toggle="collapse" data-parent="panelParent" v-bind:href="'#' + name + '-collapse'" style="display:block;">{{ name }}</a>\r
+                </h5>\r
+            </div>\r
+            <div  v-bind:id="name + '-collapse'" class="panel-collapse collapse fade">\r
+                <div class="panel-body">\r
+                    <base-input name="name" v-model="name"></base-input>\r
+                    <base-input name="method" v-model="method"></base-input>\r
+                    <base-input name="baseuri" v-model="baseuri"></base-input>\r
+                    <api-param v-bind:params="params"></api-param>\r
+                    <div class="form-group" v-bind:class="{  'has-error': jsonSyntaxError}">\r
+                        <label class="col-lg-3 control-label" id="templateLabel">\r
+                            Template <i class="fa fa-question-circle"></i>\r
+                        </label>\r
+                        <div class="col-lg-7">\r
+                            <!-- help text -->\r
+                            <span id="tempHelp">Json格式文本,用于定义发送http请求的报文内容。示例如下:<br>( 其中 ((&lt;variable&gt;)) 为占位符,用于替换实际值 )<br>GET方式:<br>{<br> &nbsp;"uri" : "((baseuri))?name=((name))"<br>}<br>POST方式:<br>{<br> &nbsp;"uri" : "((baseuri))",<br> &nbsp;"body" : {<br>&nbsp;&nbsp;&nbsp;"name" : "((name))",<br>&nbsp;&nbsp;&nbsp;"account" : {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"id" : "((user_name))",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"addr" : "SH"<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;}<br>}</span>\r
+                            <textarea class="form-control" style="min-height: 200px;" v-model="templateStr"></textarea>\r
+                            <span class="help-block" v-show="jsonSyntaxError">Json语法错误,请检查!</span>\r
+                        </div>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+</template>\r
+<script>\r
+import base_input from "./base_input.vue"\r
+import api_param from "./api_param.vue"\r
+import Vue from "vue"\r
+export default {\r
+    props: ['panelParent', 'name', 'method', 'baseuri', 'params', 'template'],\r
+    watch: {\r
+        name: function(val) {\r
+            this.$emit("name", val);\r
+        },\r
+        method: function(val) {\r
+            this.$emit("method", val);\r
+        },\r
+        baseuri: function(val) {\r
+            this.$emit("baseuri", val);\r
+        },\r
+        params: function(val) {\r
+            this.$emit("params", val);\r
+        },\r
+        templateStr: function(val) {\r
+            try {\r
+                console.log(JSON.parse(val));\r
+                this.jsonSyntaxError = false;\r
+                this.$emit("template", JSON.parse(val));\r
+            } catch(err) {\r
+                console.log("catch the exception templateStr");\r
+                this.jsonSyntaxError = true;\r
+            }\r
+        }\r
+    },\r
+    components: {\r
+        'base-input': base_input,\r
+        'api-param': api_param\r
+    },\r
+    data: function() {\r
+        return {\r
+            jsonSyntaxError: false,\r
+            templateStr: JSON.stringify(this.template, null, 2)\r
+        };\r
+    },\r
+    methods: {\r
+        deleteApi: function(apiName) {\r
+            this.$emit("delete", apiName);\r
+        }\r
+    }\r
+}\r
+</script>\r
+<style scoped>\r
+#templateLabel:hover+div #tempHelp{\r
+    display: block;\r
+}\r
+#tempHelp {\r
+    display: none;\r
+    position: absolute;\r
+    width: 90%;\r
+    min-height: 150px;\r
+    background-color: #ab2d2d;\r
+    color: white;\r
+    transition: display 1s;\r
+    text-align: left;\r
+    padding: 10px 16px;\r
+    z-index: 2;\r
+    font-size: 10px;\r
+    opacity: 0.9;\r
+}\r
+#tempHelp::after {\r
+    content: '';\r
+    position: absolute;\r
+    bottom: 92%;\r
+    right: 100%;\r
+    margin-left: -5px;\r
+    border-width: 5px;\r
+    border-style: solid;\r
+    border-color: transparent #ab2d2d transparent transparent;\r
+}\r
+@media(max-width:1200px) {\r
+    #tempHelp::after {\r
+        bottom: 100%;\r
+        left: 5%;\r
+        border-color: transparent transparent #ab2d2d transparent;\r
+    }\r
+}\r
+</style>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/env_component/service_modal.vue b/testing-scheduler/ui/src/components/env_component/service_modal.vue
new file mode 100644 (file)
index 0000000..015c91c
--- /dev/null
@@ -0,0 +1,193 @@
+<template>\r
+    <div class="modal inmodal fade" id="myModal">\r
+        <div class="modal-dialog modal-lg">\r
+            <div class="modal-content animated">\r
+                <div class="modal-header">\r
+                    <button type="button" class="close" data-dismiss="modal">\r
+                        <span aria-hidden="true">&times;</span><span class="sr-only">Close</span>\r
+                    </button>\r
+                    <h3 class="modal-title">{{type.service}}</h3>\r
+                </div>\r
+                <div class="modal-body">\r
+                    <div class="row">\r
+                        <form method="get" class="form-horizontal">\r
+                            <div id="service-address">\r
+                                <button class="btn btn-default">Basic</button>\r
+                                <div class="form-group">\r
+                                    <label class="col-sm-3 control-label">name</label>\r
+                                    <div class="col-sm-7">\r
+                                        <input  type="text" class="form-control service-title" v-model="type.service" placeholder="please input service name.">\r
+                                    </div>\r
+                                </div>\r
+                                <div class="form-group">\r
+                                    <label class="col-sm-3 control-label">ip</label>\r
+                                    <div class="col-sm-7"><input type="text" class="form-control" v-model="ip"></div>\r
+                                </div>\r
+                                <div class="form-group">\r
+                                    <label class="col-sm-3 control-label">port</label>\r
+                                    <div class="col-sm-7"><input type="text" class="form-control" v-model="port"></div>\r
+                                </div>\r
+                            </div>\r
+                            <div class="hr-line-dashed"></div>\r
+                            <div id="service-apis">\r
+                                <div id="apis-nav">\r
+                                    <button class="btn btn-default">Apis</button>\r
+                                </div>\r
+                                <br />\r
+                                <div id="api-panels" class="api col-sm-offset-1 col-sm-10">\r
+                                    <div class="panel-group" id="accordion">\r
+                                        <service-api v-for="api in apis" panel-parent="#accordion" v-bind="api" v-on:name="api.name = $event" v-on:method="api.method = $event" v-on:baseuri="api.baseuri = $event" v-on:params="api.params = $event" v-on:template="api.template = $event" v-on:delete="removeApi"></service-api>\r
+                                    </div>\r
+                                    <button type="button" class="btn btn-primary pull-right" v-on:click="addNewApi()">New</button>\r
+                                </div>\r
+                            </div>\r
+                        </form>\r
+                    </div>\r
+                </div>\r
+                <div class="modal-footer">\r
+                    <button type="button" class="btn btn-white" data-dismiss="modal">Close</button>\r
+                    <button type="button" class="btn btn-primary" v-on:click="save()">Save changes</button>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+</template>\r
+<script>\r
+import service_api from "./service_api.vue";\r
+import showMessage from '../message/showMessage.js'\r
+export default {\r
+    props: ['type'],\r
+    data: function() {\r
+        return {\r
+            typeTag: this.type.tag,\r
+            ip: "",\r
+            port: "",\r
+            apis: []\r
+        }\r
+    },\r
+    created: function() {\r
+    },\r
+    watch: {\r
+        type: {\r
+            handler: function(newVal, oldVal) {\r
+                console.log("###########type is changed!");\r
+                if(newVal.content) {\r
+                   var content = newVal.content;\r
+                   this.ip =  content.ip;\r
+                   this.port = content.port;\r
+                   this.apis = content.apis;\r
+                   console.log(this.apis);\r
+                } else {\r
+                    this.resetModalData();\r
+                }\r
+                console.log("end!");\r
+            },\r
+            deep: true\r
+        }\r
+    },\r
+    methods: {\r
+        addNewApi: function() {\r
+            var newApi = {'name': 'new', 'method': 'GET', 'baseuri': '', 'params': [], 'template': {"uri": "((baseuri))"}};\r
+            this.apis.push(newApi);\r
+        },\r
+        removeApi: function(name) {\r
+            for(var i = 0; i < this.apis.length; i++) {\r
+                if(name == this.apis[i]['name']) {\r
+                    this.apis.splice(i, 1);\r
+                }\r
+            }\r
+        },\r
+        save: function() {\r
+            if(this.ip == "") {\r
+                showMessage("warning", "SERVICE", "ip is not filled!");\r
+                return;\r
+            } else if (this.port == "") {\r
+                showMessage("warning", "SERVICE", "port is not filled!");\r
+                return;\r
+            } else if (this.type.service == "") {\r
+                showMessage("warning", "SERVICE", "service name is not filled!");\r
+                return;\r
+            }\r
+            if(this.type.edit == true) {\r
+                this.saveEdition();\r
+            } else {\r
+                this.saveCreation();\r
+            }\r
+            this.resetModalData();\r
+            $("#myModal").modal("hide");\r
+        },\r
+        saveEdition: function() {\r
+            var self = this;\r
+            var msgTitle = "SAVE -- SERVICE";\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "env/editService",\r
+                method: "post",\r
+                data: {\r
+                    "oldName":     self.type.originName,\r
+                    "newName":     self.type.service,\r
+                    "ip":         self.ip,\r
+                    "port":     self.port,\r
+                    "apis":     JSON.stringify(self.apis),\r
+                },\r
+                success: function(data) {\r
+                    if(data['code'] == 200) {\r
+                        showMessage("success", msgTitle, "Save service <strong>" + self.type.service + "</strong> successfully!");\r
+                    } else {\r
+                        showMessage(data['code'], msgTitle, "Failed to save service <strong>" + self.type.service + "</strong>!", data['error']);\r
+                    }\r
+                },\r
+                error: function() {\r
+                    showMessage("error", msgTitle, "Failed to save service <strong>" + self.type.service + "</strong>!", msg);\r
+                }\r
+            });\r
+            var edition = {\r
+                'oldName': this.type.originName,\r
+                'newName': this.type.service\r
+            };\r
+            this.$emit("service-edition", edition);\r
+        },\r
+        saveCreation: function() {\r
+            console.log("save creation!!!");\r
+            var self = this;\r
+            var msgTitle = "CREATE -- SERVICE";\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "env/createService",\r
+                method: "post",\r
+                data: {\r
+                    "name": self.type.service,\r
+                    "ip":     self.ip,\r
+                    "port": self.port,\r
+                    "apis": JSON.stringify(self.apis)\r
+                },\r
+                success: function(data) {\r
+                    if(data['code'] == 200) {\r
+                        showMessage("success", msgTitle, "Create <strong>"+ self.type.service + "</strong> successfully!");\r
+                    } else {\r
+                        showMessage(data['code'], msgTitle, "Failed to create service <strong>" + self.type.service + "</strong>!", data['error']);\r
+                        self.$emit("creation-fail", self.type.service);\r
+                    }\r
+                },\r
+                error: function() {\r
+                    showMessage("error", msgTitle, "Failed to create service <strong>" + self.type.service + "</strong>!", msg);\r
+                    self.$emit("creation-fail", self.type.service);\r
+                }\r
+            });\r
+            this.$emit("service-creation", this.type.service);\r
+        },\r
+        resetModalData: function() {\r
+            this.ip = "";\r
+            this.port = "";\r
+            this.apis = [];\r
+        },\r
+        getData: function() {\r
+            console.log("apis:");\r
+            for(i in this.apis) {\r
+                console.log(this.apis[i]);\r
+            }\r
+        }\r
+    },\r
+    components: {\r
+        'service-api': service_api\r
+    }\r
+}\r
+</script>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/environment.vue b/testing-scheduler/ui/src/components/environment.vue
new file mode 100644 (file)
index 0000000..1b9a89f
--- /dev/null
@@ -0,0 +1,239 @@
+<template>\r
+<div class="wrapper wrapper-content">\r
+    <div class="row">\r
+        <div class="col-lg-offset-2 col-lg-8">\r
+            <div class="ibox">\r
+                <div class="ibox-content">\r
+                    <h1>CONTEXT <i class="fa fa-question-circle"></i></h1>\r
+                    <div class="row">\r
+                        <div class="col-md-offset-1 col-md-10">\r
+                            <textarea v-model="context" id="context-content" style="white-space:nowrap; overflow:scroll; font-size: 16px; padding: 4px; width: 100%; min-height: 300px; max-height: 300px;">\r
+                            </textarea>\r
+                            <button type="button" class="btn btn-primary pull-right" v-on:click="saveContext()">Save</button>\r
+                        </div>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+    <div class="row">\r
+        <div class="col-lg-offset-2 col-lg-8">\r
+            <div class="ibox">\r
+                <div class="ibox-content">\r
+                    <h1>Service</h1>\r
+                    <div class="service-table">\r
+                        <table id="serviceList" class="table table-bordered table-hover text-center">\r
+                            <thead>\r
+                                <tr>\r
+                                    <th class="text-center">No</th>\r
+                                    <th class="text-center">Service</th>\r
+                                    <th class="text-center">Time</th>\r
+                                    <th class="text-center">Operation</th>\r
+                                </tr>\r
+                            </thead>\r
+                            <tbody>\r
+                                <tr v-for="service in serviceList" v-on:click="editService(service.name)" style="cursor: pointer;">\r
+                                    <td style="vertical-align: middle;">{{ service.id }}</td>\r
+                                    <td style="vertical-align: middle;">{{ service.name }}</td>\r
+                                    <td style="vertical-align: middle;">{{ service.time }}</td>\r
+                                    <td style="vertical-align: middle;"><button type="button" class="btn btn-white" v-on:click.stop="deleteService(service.name)"><i class="fa fa-trash"></i></button>\r
+                                    </td>\r
+                                </tr>\r
+                            </tbody>\r
+                        </table>\r
+                        <div>\r
+                            <button class="btn btn-lg btn-success" style="float:right;" v-on:click="addNewService()">  Add  </button>\r
+                        </div>\r
+                    </div>\r
+                    <!-- modal of one service -->\r
+                    <div class="row">\r
+                        <service-modal v-bind:type="type" v-on:service-creation="plusAService" v-on:service-edition="editAServiceName" v-on:creation-fail="creationFailHandler"></service-modal>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+</div>\r
+</template>\r
+<script>\r
+import Vue from 'vue'\r
+import service_modal from "./env_component/service_modal.vue"\r
+import showMessage from './message/showMessage.js'\r
+export default {\r
+    name: 'environment',\r
+    data: function() {\r
+        return {\r
+            serviceList: [],\r
+            type: {\r
+                edit: true,\r
+                service: "ansible",\r
+                tag: "default"\r
+            },\r
+            context: ''\r
+        }\r
+    },\r
+    components: {\r
+        'service-modal': service_modal\r
+    },\r
+    created: function() {\r
+        var self = this;\r
+        var msgTitle = "GET -- SERVICE LIST";\r
+        var errorInfo = 'Unable to get the service list';\r
+        $.ajax({\r
+            url: this.global.SERVER_ADDR + "env/getAllServices",\r
+            method: "GET",\r
+            success: function(data) {\r
+                if(data['code'] == 200) {\r
+                    self.serviceList = data['result'];\r
+                } else {\r
+                    showMessage(data['code'], msgTitle, errorInfo, data['error']);\r
+                }\r
+            },\r
+            error: function(obj, status, msg) {\r
+                showMessage("error", msgTitle, errorInfo, msg);\r
+            }\r
+        });\r
+        $.ajax({\r
+            url: this.global.SERVER_ADDR + "env/getContext",\r
+            method: "GET",\r
+            success: function(data) {\r
+                if(data['code'] == 200) {\r
+                    self.context = data['result']['context'];\r
+                } else {\r
+                    showMessage(data['code'], msgTitle, errorInfo, data['error']);\r
+                }\r
+            },\r
+            error: function(obj, status, msg) {\r
+                showMessage("error", msgTitle, errorInfo, msg);\r
+            }\r
+        });\r
+    },\r
+    methods: {\r
+        addNewService: function(){\r
+            this.type.edit = false;\r
+            this.type.tag = "abc";\r
+            this.type.service = null;\r
+            this.type.originName = null;\r
+            if(this.type.content){\r
+                this.type.content = null;\r
+            }\r
+            $("#myModal").modal("show");\r
+        },\r
+        plusAService: function(serviceName){\r
+            var item = {'id': '', 'name': '', 'time': ''};\r
+            item['id'] = this.serviceList[this.serviceList.length - 1]['id'] + 1;\r
+            item['name'] = serviceName;\r
+            item['time'] = this.getFormatDate(new Date());\r
+            this.serviceList.push(item);\r
+        },\r
+        editAServiceName: function(edition) {\r
+            for(var i = 0;i < this.serviceList.length; i++) {\r
+                if(edition['oldName'] == this.serviceList[i]['name']) {\r
+                    this.serviceList[i]['name'] = edition['newName'];\r
+                }\r
+            }\r
+        },\r
+        editService: function(serviceName){\r
+            this.type.edit = true;\r
+            this.type.tag = "abc";\r
+            this.type.service = serviceName;\r
+            this.type.originName = serviceName;\r
+            if(this.type.content){\r
+                this.type.content = null;\r
+            }\r
+            console.log(this.type);\r
+            var self = this;\r
+            var msgTitle = "GET -- SERVICE";\r
+            var errorInfo = "Unable to get the service: <strong>" + self.type.service + "</strong>";\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "env/getService",\r
+                method: "GET",\r
+                data: {\r
+                    "serviceName": serviceName\r
+                },\r
+                success: function(data) {\r
+                    if(data['code'] == 200) {\r
+                        self.type.tag = "hhh";\r
+                        self.type.content = data['result'];\r
+                        self.type.originName = self.type.service;\r
+                    } else {\r
+                        showMessage(data['code'], msgTitle, errorInfo, data['error']);\r
+                    }\r
+                },\r
+                error: function(obj, status, msg) {\r
+                    showMessage("error", msgTitle, errorInfo, msg);\r
+                }\r
+            });\r
+            $("#myModal").modal("show");\r
+        },\r
+        deleteService: function(serviceName){\r
+            var msgTitle = "DELETE -- SERVICE";\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "env/deleteService",\r
+                method: "POST",\r
+                data: {\r
+                    "serviceName": serviceName\r
+                },\r
+                success: function(data) {\r
+                    if(data['code'] == 200) {\r
+                        showMessage(data['code'], msgTitle, "Delete <strong>" + serviceName + "</strong> successfully.");\r
+                    } else {\r
+                        showMessage(data['code'], msgTitle,  "Failed to delete <strong>" + serviceName + "</strong>", data['error']);\r
+                    }\r
+                },\r
+                error: function(obj, status, msg) {\r
+                    showMessage("error", msgTitle, "Failed to delete <strong>" + serviceName + "</strong>", msg);\r
+                }\r
+            });\r
+            for(var i = 0;i < this.serviceList.length; i++) {\r
+                if(serviceName == this.serviceList[i]['name']) {\r
+                    this.serviceList.splice(i, 1);\r
+                }\r
+            }\r
+        },\r
+        creationFailHandler: function(serviceName) {\r
+            for(var i = 0; i < this.serviceList.length; i++) {\r
+                if(serviceName == this.serviceList[i].name) {\r
+                    this.serviceList.splice(i, 1);\r
+                }\r
+            }\r
+        },\r
+        getFormatDate: function(date) {\r
+            var year = date.getFullYear();\r
+            var month = date.getMonth() + 1;\r
+            var strDate = date.getDate();\r
+            var seperator = "-";\r
+            if(month >= 1 && month <= 9) {\r
+                month = "0" + month;\r
+            }\r
+            if(strDate >= 1 && strDate <= 9) {\r
+                strDate = "0" + strDate;\r
+            }\r
+            var formatDate = year + seperator + month + seperator + strDate;\r
+            return formatDate;\r
+        },\r
+        saveContext: function() {\r
+            var self = this;\r
+            var msgTitle = "SAVE -- CONTEXT";\r
+            var errorInfo = "Failed to save context!";\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "env/editContext",\r
+                method: "POST",\r
+                data: {\r
+                    context: self.context\r
+                },\r
+                success: function(data) {\r
+                    if(data['code'] == 200) {\r
+                        showMessage(data['code'], msgTitle, "Save context successfully!");\r
+                    } else {\r
+                        showMessage(data['code'], msgTitle, errorInfo, data['error']);\r
+                    }\r
+                },\r
+                error: function(obj, status, msg) {\r
+                    showMessage("error", msgTitle, errorInfo, msg);\r
+                }\r
+            });\r
+        }\r
+    }\r
+}\r
+</script>
\ No newline at end of file