the detail page of testcase in frontend of testing-scheduler 13/60013/5
authorLeoQi <QibinZheng2014@tongji.edu.cn>
Thu, 19 Jul 2018 18:55:29 +0000 (02:55 +0800)
committerLeoQi <QibinZheng2014@tongji.edu.cn>
Thu, 30 Aug 2018 11:04:09 +0000 (19:04 +0800)
JIRA: BOTTLENECK-237

the pages provide the testcase content and operations on it.

Change-Id: I0c0dd39c9a285179f2192211487c2f9d9808c523
Signed-off-by: Zheng Qibin <QibinZheng2014@tongji.edu.cn>
testing-scheduler/ui/src/components/editor/editor.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/editor/flow.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/editor/step.vue [new file with mode: 0644]
testing-scheduler/ui/src/components/testcase_content.vue [new file with mode: 0644]

diff --git a/testing-scheduler/ui/src/components/editor/editor.vue b/testing-scheduler/ui/src/components/editor/editor.vue
new file mode 100644 (file)
index 0000000..eec9d5c
--- /dev/null
@@ -0,0 +1,141 @@
+<template>\r
+<div class="col-md-offset-1 col-md-10" style="margin-top: 20px;">\r
+    <ul class="nav nav-tabs">\r
+        <li class="active"><a data-toggle="tab" data-target="#step-pane">Step</a></li>\r
+        <li><a data-toggle="tab" data-target="#flow-pane">Flow</a></li>\r
+    </ul>\r
+    <div class="tab-content">\r
+        <div id="step-pane" class="tab-pane active fade in">\r
+            <br>\r
+            <div class="row">\r
+                <div class='col-md-12'>\r
+                    <step v-bind:stepList="stepList" v-on:stepList="getStepList"></step>\r
+                </div>\r
+            </div>\r
+        </div>\r
+        <div id="flow-pane" class="tab-pane fade">\r
+            <br>\r
+            <div class="row">\r
+                <div class='col-md-12'>\r
+                    <div class="row">\r
+                        <button style='margin-left:20px; margin-bottom: 30px;' class="btn btn-success" type="button" id="new-flow" v-on:click='addSubflow'>&nbsp;&nbsp;<span class="bold">ADD FLOW</span></button>\r
+                    </div>\r
+                    <div class='row'>\r
+                        <div class='col-md-2'>\r
+                            <ul id="flow-tabs">\r
+                                <li class="active"><a data-toggle="tab" data-target="#flow-main">main</a></li>\r
+                                <li v-for="subflow in subflowList"><a data-toggle="tab" v-bind:data-target="'#' + subflow.tabId">{{ subflow.name }}</a></li>\r
+                            </ul>\r
+                        </div>\r
+                        <div class="col-md-10">\r
+                            <div class="tab-content">\r
+                                <div id="flow-main" class="tab-pane active fade in">\r
+                                    <flow v-model='mainflowName' v-bind:orderList='mainOrdersList' v-bind:stepsRefs='stepNameList' v-bind:flowsRefs='flowNameList' v-on:orderList='updateOrderList($event, mainflowName)'>\r
+                                    </flow>\r
+                                </div>\r
+                                <div v-for="subflow in subflowList" v-bind:id="subflow.tabId" class="tab-pane fade">\r
+                                    <flow v-model='subflow.name' v-bind:orderList='subflow.orderList' v-bind:stepsRefs='stepNameList' v-bind:flowsRefs='flowNameList' v-on:orderList='updateOrderList($event, subflow.name)'></flow>\r
+                                </div>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+</div>\r
+</template>\r
+<script>\r
+import '../../assets/css/editor.css'\r
+import step from './step.vue'\r
+import flow from './flow.vue'\r
+import showMessage from '../message/showMessage.js'\r
+export default {\r
+    name: 'editor',\r
+    props: ['saveSignal', 'stepList', 'mainOrdersList', 'subflowList'],\r
+    model: {\r
+        prop: 'saveSignal',\r
+        event: 'saveResponse'\r
+    },\r
+    data: function(){\r
+        return {\r
+            mainflowName: 'main'\r
+        }\r
+    },\r
+    components: {\r
+        step,\r
+        flow\r
+    },\r
+    methods: {\r
+        getStepList: function(stepList) {\r
+            this.stepList = stepList;\r
+        },\r
+        addSubflow: function() {\r
+            var tabid = "flow-" + Math.floor(Math.random()*(1000000));\r
+            this.subflowList.push({'tabId': tabid, 'name': 'fake', 'orderList': []});\r
+        },\r
+        updateOrderList: function(orderList, flowName) {\r
+            if(flowName == 'main') {\r
+                this.mainOrdersList = orderList;\r
+            } else {\r
+                for(var i = 0; i < this.subflowList.length; ++i) {\r
+                    if(this.subflowList[i].name == flowName) {\r
+                        this.subflowList[i].orderList = orderList;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    },\r
+    computed: {\r
+        flowNameList: function() {\r
+            var stepNameArr = [];\r
+            for(var i = 0; i < this.subflowList.length; i++) {\r
+                stepNameArr.push(this.subflowList[i].name);\r
+            }\r
+            console.log(stepNameArr);\r
+            return stepNameArr;\r
+        },\r
+        stepNameList: function() {\r
+            var stepNameArr = [];\r
+            for(var i = 0; i < this.stepList.length; i++) {\r
+                stepNameArr.push(this.stepList[i].name);\r
+            }\r
+            return stepNameArr;\r
+        }\r
+    },\r
+    watch: {\r
+        saveSignal: function(newVal) {\r
+            if(newVal == true) {\r
+                console.log("editor newVal true");\r
+                var self = this;\r
+                var msgTitle = "SAVE -- TESTCASE";\r
+                $.ajax({\r
+                    url: this.global.SERVER_ADDR + "testcase/save",\r
+                    method: "POST",\r
+                    data: {\r
+                        suiteName:  this.$route.query.suiteName,\r
+                        caseName: this.$route.query.caseName,\r
+                        stepList: JSON.stringify(this.stepList),\r
+                        subflowList: JSON.stringify(this.subflowList),\r
+                        mainOrdersList: JSON.stringify(this.mainOrdersList)\r
+                    },\r
+                    success: function(data) {\r
+                        console.log("ajax save content!");\r
+                        if(data['code'] == 200) {\r
+                            showMessage("success", msgTitle, "Save content successfully!");\r
+                            self.$emit('saveResponse', true);\r
+                        } else {\r
+                            showMessage(data['code'], msgTitle, "Failed to save content!", data['error']);\r
+                            self.$emit('saveResponse', false);\r
+                        }\r
+                    },\r
+                    error: function(obj, status, msg) {\r
+                        showMessage(status, msgTitle, "Failed to save content!", msg);\r
+                        self.$emit('saveResponse', false);\r
+                    }\r
+                });\r
+            }\r
+        }\r
+    }\r
+}\r
+</script>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/editor/flow.vue b/testing-scheduler/ui/src/components/editor/flow.vue
new file mode 100644 (file)
index 0000000..b79943a
--- /dev/null
@@ -0,0 +1,340 @@
+<template>\r
+<div class="row" style="border: 1px solid #cec8c8">\r
+    <div class="col-md-12" style="padding: 10px 0 5px;">\r
+        <div class="form-group">\r
+            <label class="col-md-2 control-label" style="font-size: 22px;">flowName</label>\r
+            <div class="col-md-6">\r
+                <input v-if="flowName != 'main'" type="text" class="form-control" v-model="flowName" v-on:input='$emit("editFlowName", $event.target.value)' placeholder="please input flow name." />\r
+                <p style="font-size: 22px;" v-else>{{flowName}}</p>\r
+            </div>\r
+        </div>\r
+    </div>\r
+    <div class="col-md-12">\r
+        <div class="ibox">\r
+            <div class="ibox-title">\r
+                <h5 class="text-success">Order</h5>\r
+                <div class="ibox-tools">\r
+                    <a class="collapse-link">\r
+                        <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                    </a>\r
+                </div>\r
+            </div>\r
+            <div class="ibox-content">\r
+                <div class="row">\r
+                    <button class="btn btn-success" type="button" id="new-order" v-on:click='addOrder'>&nbsp;&nbsp;<span class="bold">ADD ORDER</span></button>\r
+                    <div class="col-md-3">\r
+                       <span class="select-box" >\r
+                        <select id="orderSelect" class="select form-control" v-model='orderSelected' >\r
+                            <option value="1">Normal</option>\r
+                            <option value="2">Switch</option>\r
+                            <option value="3">Parallel</option>\r
+                        </select>\r
+                        </span>\r
+                    </div>\r
+                    <br>\r
+                    <!-- Normal -->\r
+                    <div id="normal-panel" v-show='orderSelected == 1'>\r
+                        <div class="col-lg-11" id="normalform">\r
+                            <br>\r
+                            <div>\r
+                                <div class="ibox border-ibox">\r
+                                    <div class="ibox-title">\r
+                                        <h5>Normal</h5>\r
+                                        <div class="ibox-tools">\r
+                                            <a class="collapse-link" >\r
+                                                <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                                            </a>\r
+                                        </div>\r
+                                    </div>\r
+                                    <div class="ibox-content">\r
+                                       <!-- <div class="form-group">\r
+                                          <div class="col-lg-6 row"><label>name</label><input id="NName" type="name" placeholder="name" class="form-control"></div>\r
+                                       </div> -->\r
+                                       <div class="form-group">\r
+                                            <label class='headmsg control-label'>Step</label>\r
+                                            <div class='col-md-4'>\r
+                                                <select class="chooseStep form-control" id="NStep" v-model='normalStep'>\r
+                                                        <option></option>\r
+                                                        <option v-for='stepRef in stepsRefs' v-bind:value='stepRef'>{{ stepRef }}</option>\r
+                                                </select>\r
+                                            </div>\r
+                                       </div>\r
+                                    </div>\r
+                                </div>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                    <!-- Switch -->\r
+                    <div id="switch-panel" v-show='orderSelected == 2'>\r
+                        <br>\r
+                        <div class="row">\r
+                            <div class="col-lg-11">\r
+                                <div class="ibox border-ibox float-e-margins">\r
+                                    <div class="ibox-title">\r
+                                        <h5>Switch</h5>\r
+                                        <div class="ibox-tools">\r
+                                            <button class="btn btn-success " type="button" id="new-case" v-on:click='addNewCase'>&nbsp;&nbsp;<span class="bold">New Case</span></button>\r
+                                            <a class="collapse-link" >\r
+                                                <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                                            </a>\r
+                                        </div>\r
+                                    </div>\r
+                                    <div class="ibox-content">\r
+                                        <div class="row">\r
+                                            <div class="row">\r
+                                                <div class="form-group">\r
+                                                    <label class="headmsg control-label">Value:</label>\r
+                                                    <div class="col-md-5"><input type="text" class="case form-control" v-model='switchValue'></div>\r
+                                                </div>\r
+                                            </div>\r
+                                            <div class="row">\r
+                                                <label class="headmsg control-label">Cases:</label>\r
+                                                <div class='col-md-12 row'>\r
+                                                    <div class='col-md-offset-1' v-for='switchCase in switchCases' style='border-left-style: solid; border-left-color: gray; margin-bottom: 30px;'>\r
+                                                        <div class="row">\r
+                                                            <div class="form-group">\r
+                                                                <label class="headmsg control-label">CaseValue:</label>\r
+                                                                <div class="col-md-5"><input type="text" class="case form-control" v-model='switchCase.value'></div>\r
+                                                            </div>\r
+                                                        </div>\r
+                                                        <div class="row">\r
+                                                            <label class="headmsg control-label">Case:</label>\r
+                                                            <div class="col-md-3">\r
+                                                                <select class="myselect chooseStep form-control" v-model='switchCase.orderType'>\r
+                                                                    <option></option>\r
+                                                                    <option v-for='orderType in ["step", "flow"]' v-bind:value='orderType'>{{ orderType }}</option>\r
+                                                                </select>\r
+                                                            </div>\r
+                                                            <div class="col-md-4">\r
+                                                                <select class="myselect chooseStep form-control" v-model='switchCase.orderValue'>\r
+                                                                    <option></option>\r
+                                                                    <option v-if='switchCase.orderType == "step"' v-for='stepRef in stepsRefs' v-bind:value='stepRef'>{{ stepRef }}</option>\r
+                                                                    <option v-if='switchCase.orderType == "flow"' v-for='flowRef in filtedFlowsRefs' v-bind:value='flowRef'>{{ flowRef }}</option>\r
+                                                                </select>\r
+                                                            </div>\r
+                                                        </div>\r
+                                                    </div>\r
+                                                </div>\r
+                                            </div>\r
+                                        </div>\r
+                                    </div>\r
+                                </div>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                    <!-- Parallel -->\r
+                    <div id="parallel-panel" v-show='orderSelected == 3'>\r
+                        <br>\r
+                        <div class="row">\r
+                            <div class="col-lg-11">\r
+                                <div class="ibox border-ibox float-e-margins">\r
+                                    <div class="ibox-title">\r
+                                        <h5>Parallel</h5>\r
+                                        <div class="ibox-tools">\r
+                                            <button class="btn btn-success " type="button" id="para-step" v-on:click='addNewBranch'>&nbsp;&nbsp;<span class="bold"><i class='fa fa-plus-square-o'></i> Branch</span></button>\r
+                                            <a class="collapse-link" >\r
+                                                <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                                            </a>\r
+                                        </div>\r
+                                    </div>\r
+                                    <div id="parallel">\r
+                                        <div class="ibox-content">\r
+                                            <div class='row'>\r
+                                                <div class='row'><label class="headmsg control-label">Branches:</label></div>\r
+                                                <div class='row'>\r
+                                                    <div class='col-md-offset-1'>\r
+                                                        <div v-for='branch in parallelBranches' class="row" style='border-left-style: solid; border-left-color: gray; margin-bottom: 20px; padding-top: 7px; padding-bottom: 7px;'>\r
+                                                            <label class="headmsg control-label">Branch:</label>\r
+                                                            <div class="col-md-3">\r
+                                                                <select class="myselect chooseStep form-control" v-model='branch.orderType'>\r
+                                                                    <option></option>\r
+                                                                    <option v-for='orderType in ["step", "flow"]' v-bind:value='orderType'>{{ orderType }}</option>\r
+                                                                </select>\r
+                                                            </div>\r
+                                                            <div class="col-md-4">\r
+                                                                <select class="myselect chooseStep form-control" v-model='branch.orderValue'>\r
+                                                                    <option></option>\r
+                                                                    <option v-if='branch.orderType == "step"' v-for='stepRef in stepsRefs' v-bind:value='stepRef'>{{ stepRef }}</option>\r
+                                                                    <option v-if='branch.orderType == "flow"' v-for='flowRef in filtedFlowsRefs' v-bind:value='flowRef'>{{ flowRef }}</option>\r
+                                                                </select>\r
+                                                            </div>\r
+                                                        </div>\r
+                                                    </div>\r
+                                                </div>\r
+                                            </div>\r
+                                        </div>\r
+                                    </div>\r
+                                </div>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+        <div class="ibox">\r
+            <div class="ibox-title">\r
+                <h5 class="text-success">OrderList</h5>\r
+                <div class="ibox-tools">\r
+                        <a class="collapse-link" >\r
+                            <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                        </a>\r
+                </div>\r
+            </div>\r
+            <div class="ibox-content" id="order-list">\r
+                <div v-for='(order, index) in orderList' class='ibox float-e-margins' style='margin-bottom: 0;'>\r
+                    <div class="ibox-title step">\r
+                        <h5>Order #{{index+1}}   <strong style='margin-left: 20px;'>{{['normal', 'switch', 'parallel'][order.type - 1]}}</strong> </h5>\r
+                        <div class="ibox-tools">\r
+                            <a class="collapse-link" >\r
+                                <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                            </a>\r
+                            <a class="close-link" v-on:click='removeOrder'>\r
+                                <i class="fa fa-times"></i>\r
+                            </a>\r
+                        </div>\r
+                    </div>\r
+                    <div class="ibox-content">\r
+                        <div v-if='order.type == 1' class="row">\r
+                            <label class="control-label" style='padding-right: 20px;'> step: </label>\r
+                            <label class="control-label"> {{ order.step }}</label>\r
+                        </div>\r
+                        <div v-if='order.type == 2' class="row">\r
+                            <div>\r
+                                <label class="control-label" style='padding-right: 20px;'> value: </label>\r
+                                <label class="control-label"> {{order.value}} </label>\r
+                            </div>\r
+                            <div><label class="control-label"> cases: </label></div>\r
+                            <div v-for='sCase in order.cases' class="row">\r
+                                <label class="control-label col-md-offset-1"> -- <b>{{ sCase.value }}</b> : </label>\r
+                                <label class='coltrol-label' style='margin-left: 20px;'>{{ sCase.orderValue }} [{{ sCase.orderType }}]</label>\r
+                            </div>\r
+                        </div>\r
+                        <div v-if='order.type == 3' class="row">\r
+                            <div><label class="control-label"> </label></div>\r
+                            <div v-for='branch in order.branches' class="row">\r
+                                <label class="control-label col-md-offset-1" style='padding-right: 20px;'> -- branch: </label>\r
+                                <label class="control-label"> {{ branch.orderValue }} [{{ branch.orderType }}]</label>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+</div>\r
+</template>\r
+<script>\r
+export default {\r
+    name: 'flow',\r
+    props: ['stepsRefs', 'flowsRefs', 'flowName', 'orderList'],\r
+    model: {\r
+        prop: 'flowName',\r
+        event: 'editFlowName'\r
+    },\r
+    data: function() {\r
+        return {\r
+            normalStep: '',\r
+            switchValue: '',\r
+            switchCases: [{'value': '', 'orderType': '', 'orderValue': ''}],\r
+            parallelBranches: [{'orderType': '', 'orderValue': ''}],\r
+            orderSelected: 1\r
+        }\r
+    },\r
+    mounted: function(){\r
+        // this.selectPluginUpdate();\r
+    },\r
+    updated: function(){\r
+        // this.selectPluginUpdate();\r
+    },\r
+    methods: {\r
+        addOrder: function(){\r
+            var select = this.orderSelected;\r
+            if(select == 1){\r
+                if(this.normalStep == ""){\r
+                    alert("Not completed!!!");\r
+                    return;\r
+                }\r
+                var temp = {type:1,step:this.normalStep};\r
+                this.orderList.push(temp);\r
+                this.normalStep = '';\r
+            }\r
+            if(select == 2){\r
+                var caseList = [];\r
+                for(var i=0; i<this.switchCases.length; ++i){\r
+                    var caseValue = this.switchCases[i].value;\r
+                    if(caseValue == ""){\r
+                        alert("Not completed!!!");\r
+                        return;\r
+                    }\r
+                    var caseOrderType = this.switchCases[i].orderType;\r
+                    if(caseOrderType == ""){\r
+                        alert("Not completed!!!");\r
+                        return;\r
+                    }\r
+                    var caseOrderValue = this.switchCases[i].orderValue;\r
+                    if(caseOrderValue == ""){\r
+                        alert("Not completed!!!");\r
+                        return;\r
+                    }\r
+                    caseList.push({value: caseValue, orderType: caseOrderType, orderValue: caseOrderValue});\r
+                }\r
+                temp = {type:2, value: this.switchValue, cases:caseList};\r
+                this.orderList.push(temp);\r
+                this.switchValue = '';\r
+                   this.switchCases = [{value: '', orderType: '', orderValue: ''}];\r
+            }\r
+            if(select == 3){\r
+                var branchList = [];\r
+                var allStep = $('#parallel .chooseStep');\r
+                for(var i=0; i<this.parallelBranches.length; ++i){\r
+                    var branchOrderType = this.parallelBranches[i].orderType;\r
+                    if(branchOrderType == ""){\r
+                        alert("Not completed!!!");\r
+                        return;\r
+                    }\r
+                    var branchOrderValue = this.parallelBranches[i].orderValue;\r
+                    if(branchOrderValue == ""){\r
+                        alert("Not completed!!!");\r
+                        return;\r
+                    }\r
+                    branchList.push({orderType: branchOrderType, orderValue: branchOrderValue});\r
+                }\r
+                temp = {type:3,branches:branchList};\r
+                this.orderList.push(temp);\r
+                this.parallelBranches = [{orderType: '', orderValue: ''}];\r
+            }\r
+            this.$emit("orderList", this.orderList);\r
+        },\r
+        removeOrder: function(index){\r
+            this.orderList.splice(index, 1);\r
+        },\r
+        addNewCase: function() {\r
+            this.switchCases.push({value: '', orderType: '', orderValue: ''});\r
+        },\r
+        addNewBranch: function() {\r
+            this.parallelBranches.push({step: ''});\r
+        },\r
+        collapseBox: function(event) {\r
+            console.log("collapse");\r
+            var ele = event.target;\r
+            console.log(event);\r
+            console.log(ele);\r
+            var ibox = $(ele).closest('div.ibox');\r
+            var content = ibox.children('.ibox-content');\r
+            content.slideToggle(200);\r
+            $(ele).toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');\r
+        }\r
+    },\r
+    computed: {\r
+        filtedFlowsRefs: function() {\r
+            var subflowNameArr = [];\r
+            for(var i = 0; i < this.flowsRefs.length; i++) {\r
+                if(this.flowsRefs[i] != this.flowName) {\r
+                    subflowNameArr.push(this.flowsRefs[i]);\r
+                }\r
+            }\r
+            return subflowNameArr;\r
+        }\r
+    }\r
+}\r
+</script>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/editor/step.vue b/testing-scheduler/ui/src/components/editor/step.vue
new file mode 100644 (file)
index 0000000..8c03513
--- /dev/null
@@ -0,0 +1,222 @@
+<template>\r
+<!-- step -->\r
+<div class="row">\r
+    <div class="col-md-6 col-sm-12">\r
+        <div class="ibox float-e-margins">\r
+            <div class="ibox-title">\r
+                <h5 class="text-success">Step</h5>\r
+                <div class="ibox-tools" style="height: 25px;">\r
+                    <button class="btn btn-success " type="button" id="new-step">&nbsp;&nbsp;<span class="bold">New Step</span></button>\r
+                        <a class="collapse-link" >\r
+                            <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                        </a>\r
+                </div>\r
+            </div>\r
+            <div class="ibox-content" style="border: 1px solid #cec8c8">\r
+                <form class="form-horizontal">\r
+                    <div class="row">\r
+                        <div class="form-group">\r
+                            <label class="col-md-2 control-label">Name:</label>\r
+                            <div class="col-md-5"><input type="text" class="form-control" id="name"></div>\r
+                        </div>\r
+                        <div class="form-group">\r
+                            <label class="col-md-2 control-label">Service:</label>\r
+                            <div class="col-md-4">\r
+                                <select class="form-control" id="service">\r
+                                    <option></option>\r
+                                    <option v-for='service in dataService' v-bind:value='service'>{{service}}</option>\r
+                                </select>\r
+                            </div>\r
+                        </div>\r
+                        <div class="form-group">\r
+                            <label class="col-md-2 control-label">Action:</label>\r
+                            <div class="col-md-4">\r
+                                <select class="form-control" id="action">\r
+                                    <option></option>\r
+                                    <option v-for='action in dataAction' v-bind:value='action.name'>{{action.name}}</option>\r
+                                </select>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                    <div class="row" id="parameter">\r
+                        <div class="form-group" v-for='(param, index) in dataParam'>\r
+                            <label class="col-md-2 control-label" v-bind:title="param.description">{{ param.name }}\r
+                            </label>\r
+                            <div class="col-md-5">\r
+                                <input type="text" class="form-control"  v-bind:placeholder="param.description" v-bind:id="'par'+index">\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                </form>\r
+            </div>\r
+        </div>\r
+    </div>\r
+    <div class="col-md-6 col-sm-12">\r
+        <div class="ibox float-e-margins">\r
+            <div class="ibox-title">\r
+                <h5 class="text-success">StepList</h5>\r
+                <div class="ibox-tools">\r
+                        <a class="collapse-link">\r
+                            <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                        </a>\r
+                </div>\r
+            </div>\r
+            <div class="ibox-content" id="step-list" style="border: 1px solid #cec8c8">\r
+                <div v-for='(step, index) in stepList' class='ibox'>\r
+                    <div class="ibox-title step">\r
+                        <h5>Step{{index + 1}} &nbsp;&nbsp; {{step.name}} </h5>\r
+                        <div class="ibox-tools">\r
+                            <a class="collapse-link">\r
+                                <i class="fa fa-chevron-up" v-on:click.stop='collapseBox'></i>\r
+                            </a>\r
+                            <a class="close-link" v-on:click='removeStep(index)'>\r
+                                <i class="fa fa-times"></i>\r
+                            </a>\r
+                        </div>\r
+                    </div>\r
+                    <div class="ibox-content">\r
+                        <div class="row">\r
+                            <label class="control-label"><span style='padding-right: 20px;'>Service:</span> {{ step.service }}</label>\r
+                        </div>\r
+                        <div class="row">\r
+                          <label class="control-label"><span style='padding-right: 20px;'>Action:</span> {{ step.action }}</label>\r
+                        </div>\r
+                           <div class="param row">\r
+                          <label class="control-label">\r
+                              <span style='padding-right: 20px;'>Parameter:</span>\r
+                              <span v-for='param in step.params'>{{param.key}} = {{param.value}} ;&nbsp;&nbsp;&nbsp;</span>\r
+                          </label>\r
+                        </div>\r
+                       </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+</div>\r
+</template>\r
+<script>\r
+export default {\r
+    name: 'step',\r
+    props: ['stepList'],\r
+    data: function() {\r
+        return {\r
+            dataService: [],\r
+            dataAction: [],\r
+            dataParam: []\r
+        }\r
+    },\r
+    mounted: function() {\r
+        this.getServiceList();\r
+        var self = this;\r
+        $("#service").change(function(){\r
+            self.selectService();\r
+        });\r
+        $("#action").change(function(){\r
+            self.selectAction();\r
+        });\r
+        $('#new-step').click(function(){\r
+            self.newStep();\r
+        });\r
+    },\r
+    methods: {\r
+        getServiceList: function(){\r
+            console.log("get serviceList!");\r
+            var self = this;\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "service/list",\r
+                method: "GET",\r
+                async:false,\r
+                success: function(data){\r
+                    console.log("ajax success!");\r
+                    if(data['code'] == 200){\r
+                        self.dataService = [];\r
+                        self.dataService = data['result'];\r
+                    }\r
+                }\r
+            });\r
+        },\r
+        getServiceContent: function(name){\r
+            var self = this;\r
+            $.ajax({\r
+                url: this.global.SERVER_ADDR + "service/content",\r
+                method: "GET",\r
+                async:false,\r
+                data: {\r
+                    "serviceName": name\r
+                },\r
+                success: function(data){\r
+                    if(data['code'] == 200){\r
+                        self.dataAction = [];\r
+                        self.dataAction = data['result']['actions'];\r
+                    }\r
+                }\r
+            });\r
+        },\r
+        getParams: function(name){\r
+            for(var i in this.dataAction){\r
+                if(this.dataAction[i].name == name){\r
+                    this.dataParam = [];\r
+                    this.dataParam = this.dataAction[i].params;\r
+                    break;\r
+                }\r
+            }\r
+        },\r
+        selectService: function(event){\r
+            var selectedName = $("#service").val();\r
+            this.getServiceContent(selectedName);\r
+        },\r
+        selectAction: function(event){\r
+            var selectedName = $("#action").val();\r
+            if(selectedName=="") {\r
+                this.dataParam = [];\r
+                return;\r
+            }\r
+            this.getParams(selectedName);\r
+            if(this.dataParam==undefined) this.dataParam = [];\r
+        },\r
+        newStep: function(){\r
+            var ser = $("#service").val();\r
+            var act = $("#action").val();\r
+            var na = $("#name").val();\r
+            if(ser==""||act==""||na==""){\r
+                alert('Not completed!');\r
+                return;\r
+            }\r
+            var parCount = this.dataParam.length;\r
+            var par = [];\r
+            for(var i=0; i<parCount; ++i){\r
+                var temp = $('#par'+i).val();\r
+                if(temp==""){\r
+                    alert('Not completed!');\r
+                    return;\r
+                }\r
+                var name = this.dataParam[i].name;\r
+                par.push({key: name, value: temp});\r
+            }\r
+            this.stepList.push({name: na, service: ser, action: act, params: par});\r
+            $("#name").val("");\r
+            $("#service").val("");\r
+            this.dataAction = [];\r
+            this.dataParam = [];\r
+        },\r
+        removeStep: function(index) {\r
+            this.stepList.splice(index, 1);\r
+        },\r
+        collapseBox: function(event) {\r
+            console.log("collapse");\r
+            var ele = event.target;\r
+            console.log(event);\r
+            console.log(ele);\r
+            var ibox = $(ele).closest('div.ibox');\r
+            var content = ibox.children('.ibox-content');\r
+            content.slideToggle(200);\r
+            $(ele).toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');\r
+        }\r
+    },\r
+    watch: {\r
+        stepList: function() {\r
+            this.$emit('stepList', this.stepList);\r
+        }\r
+    }\r
+}\r
+</script>
\ No newline at end of file
diff --git a/testing-scheduler/ui/src/components/testcase_content.vue b/testing-scheduler/ui/src/components/testcase_content.vue
new file mode 100644 (file)
index 0000000..c986b6a
--- /dev/null
@@ -0,0 +1,215 @@
+<template>\r
+  <div class="wrapper wrapper-content animated fadeIn">\r
+    <div class="row" style="margin-bottom: 20px;">\r
+      <div class="col-md-8">\r
+        <ol class="breadcrumb" style="padding-left: 20px; font-size: 17px;">\r
+          <li>\r
+            <router-link to="/" >root</router-link>\r
+          </li>\r
+          <li>\r
+            <router-link :to="{ path: '/testcase', query: { name: suitename }}" >{{this.$route.query.suiteName}}</router-link>\r
+          </li>\r
+          <li>\r
+            <router-link :to="{ path: '/content', query: { suiteName: suitename, caseName: casename } }"><b>{{this.$route.query.caseName}}</b></router-link>\r
+          </li>\r
+        </ol>\r
+      </div>\r
+    </div>\r
+    <div id="page-content" class="row">\r
+      <div class="col-lg-12">\r
+        <div class="ibox">\r
+            <div class="ibox-title">\r
+                <h5 style="font-size:26px;margin-top: -3px;">Test Case Content</h5>\r
+                <div v-show="contentLoading || contentSaving" class="sk-spinner sk-spinner-circle" style="float: left;margin-left: 10px;">\r
+                    <div class="sk-circle1 sk-circle"></div>\r
+                    <div class="sk-circle2 sk-circle"></div>\r
+                    <div class="sk-circle3 sk-circle"></div>\r
+                    <div class="sk-circle4 sk-circle"></div>\r
+                    <div class="sk-circle5 sk-circle"></div>\r
+                    <div class="sk-circle6 sk-circle"></div>\r
+                    <div class="sk-circle7 sk-circle"></div>\r
+                    <div class="sk-circle8 sk-circle"></div>\r
+                    <div class="sk-circle9 sk-circle"></div>\r
+                    <div class="sk-circle10 sk-circle"></div>\r
+                    <div class="sk-circle11 sk-circle"></div>\r
+                    <div class="sk-circle12 sk-circle"></div>\r
+                </div>\r
+                <div class="ibox-tools">\r
+                    <button class="btn btn-info btn-sm my-button-sm" type="button" v-on:click="runTestcase()">Run</button>\r
+                    <button class="btn btn-success btn-sm my-button-sm" type="button" v-on:click="setEditable()">Edit</button>\r
+                    <button v-show="isEditable" class="btn btn-warning btn-sm my-button-sm" v-on:click="saveTestcase()" type="button">Save</button>\r
+                    <button v-show="isEditable" class="btn btn-danger btn-sm my-button-sm" v-on:click="cancelEdit()" type="button">Cancel</button>\r
+                    <a class="collapse-link">\r
+                        <i class="fa fa-chevron-up"></i>\r
+                    </a>\r
+                    <a class="fullscreen-link">\r
+                        <i class="fa fa-expand"></i>\r
+                    </a>\r
+                </div>\r
+            </div>\r
+            <div class="ibox-content" style="max-height: 600px; overflow-y: auto; padding: 0; border: 1px solid #e7e7e7;">\r
+                <div style='text-align:center;'>\r
+                  <textarea v-show='!isEditable' v-model="content" id="tc_content" style="white-space:nowrap; overflow:scroll;max-width:2400px; width: 100%;height: 100%;min-height: 500px;font-size:16px;border:none; vertical-align: middle; padding: 30px 0 20px 40px;">\r
+                  </textarea>\r
+                </div><editor v-show='isEditable' v-bind:saveSignal='saveSignal' v-bind = 'editorContent' v-on:saveResponse='processSaveResponse'></editor>\r
+            </div>\r
+        </div>\r
+      </div>\r
+    </div>\r
+    <hr />\r
+    <div class="row">\r
+      <div class="col-lg-12">\r
+          <div class="ibox">\r
+              <div class="ibox-title">\r
+                  <h5 style="font-size:26px;margin-top: -3px;">Workflow</h5>\r
+                  <div class="ibox-tools">\r
+                      <a class="collapse-link">\r
+                          <i class="fa fa-chevron-up"></i>\r
+                      </a>\r
+                      <a class="fullscreen-link">\r
+                          <i class="fa fa-expand"></i>\r
+                      </a>\r
+                  </div>\r
+              </div>\r
+              <div class="ibox-content" style="padding-top: 60px;">\r
+                  <wfresult v-bind:workflowId="workflowId" v-bind:wfloading='wfloading' v-bind:wfJson='wfJson'></wfresult>\r
+              </div>\r
+          </div>\r
+      </div>\r
+    </div>\r
+  </div>\r
+</template>\r
+<script>\r
+import editor from './editor/editor.vue'\r
+import wfresult from './workflow_graph/wfresult.vue'\r
+import showMessage from './message/showMessage.js'\r
+export default {\r
+    name: 'testcase_content',\r
+    data () {\r
+      return {\r
+          content: '',\r
+          editorContent: {'stepList': [], 'mainOrdersList': [], 'subflowList': []},\r
+          bakContent: '',\r
+          isEditable: false,\r
+          contentLoading: false,\r
+          contentSaving: false,\r
+          suitename:this.$route.query.suiteName,\r
+          casename:this.$route.query.caseName,\r
+          workflowId: '',\r
+          wfloading: false,\r
+          wfJson: '',\r
+          saveSignal: false\r
+      }\r
+    },\r
+    created: function() {\r
+        this.getTestcase();\r
+    },\r
+    methods: {\r
+      setEditable: function(){\r
+          this.isEditable = true;\r
+          this.bakContent = this.content;\r
+      },\r
+      cancelEdit: function(){\r
+          this.content = this.bakContent;\r
+          this.isEditable = false;\r
+      },\r
+      saveTestcase: function(){\r
+          console.log("save");\r
+          this.saveSignal = true;\r
+          this.contentSaving = true;\r
+      },\r
+      runTestcase: function(){\r
+        var self = this;\r
+        var msgTitle = "RUN -- TESTCASE";\r
+        $.ajax({\r
+            url: this.global.SERVER_ADDR + "execute/testcase",\r
+            method: "POST",\r
+            data: {\r
+                "suiteName": this.$route.query.suiteName,\r
+                "caseName": this.$route.query.caseName\r
+            },\r
+            beforeSend: function(XHR) {\r
+                self.wfloading = true;\r
+                showMessage("info", msgTitle, "start to run <strong>" + self.$route.query.caseName + "</strong>");\r
+            },\r
+            success: function(data) {\r
+                if(data['code'] == 200) {\r
+                    self.workflowId = data['result']['workflowId'];\r
+                    showMessage(data['code'], msgTitle, "<strong>" + self.$route.query.caseName + "</strong> finished!");\r
+                    $.ajax({\r
+                        url: self.global.SERVER_ADDR + "story-content",\r
+                        method: "GET",\r
+                        data: {\r
+                            "service":  self.$route.query.suiteName,\r
+                            "story": self.$route.query.caseName\r
+                        },\r
+                        success: function(data) {\r
+                            if(data['code'] == 200) {\r
+                                self.wfJson = data['result']['content'];\r
+                            } else {\r
+                              showMessage(data['code'], msgTitle, "workflow.json get failed!");\r
+                            }\r
+                        },\r
+                        error: function(obj, status, msg) {\r
+                          showMessage(status, msgTitle, msg);\r
+                        }\r
+                    });\r
+                } else {\r
+                  self.wfloading = false;\r
+                  showMessage(data['code'], msgTitle, "Failed to run <strong>" + self.$route.query.caseName + "</strong>", data['error']);\r
+                }\r
+            },\r
+            error: function(obj, status, msg) {\r
+                self.wfloading = false;\r
+                showMessage(status, msgTitle, "Failed to run <strong>" + self.$route.query.caseName + "</strong>", msg);\r
+            }\r
+        });\r
+      },\r
+      getTestcase: function(){\r
+          var self = this;\r
+          var msgTitle = "GET -- TESTCASE";\r
+          $.ajax({\r
+            url: this.global.SERVER_ADDR + "testcase/content",\r
+            method:"GET",\r
+            data:{\r
+              suiteName:  this.$route.query.suiteName,\r
+              caseName: this.$route.query.caseName\r
+            },\r
+            beforeSend: function(XHR) {\r
+                self.contentLoading = true;\r
+            },\r
+            success:function (data) {\r
+              if(data['code'] == 200) {\r
+                self.content = data['result']['content'];\r
+                self.contentLoading = false;\r
+                self.editorContent = data['result']['editorContent'];\r
+              }\r
+              else {\r
+                showMessage("error", msgTitle, "fail to load testcase content!", data['error']);\r
+                self.contentLoading = false;\r
+              }\r
+            },\r
+            error: function (obj, status, msg) {\r
+              showMessage(status, msgTitle, "fail to load testcase content!", msg);\r
+              self.contentLoading = false;\r
+            }\r
+          });\r
+      },\r
+      async processSaveResponse(result) {\r
+          if(result == true) {\r
+            this.saveSignal = false;\r
+            this.isEditable = false;\r
+            this.contentSaving = false;\r
+            this.getTestcase();\r
+          } else {\r
+            this.saveSignal = false;\r
+            this.contentSaving = false;\r
+          }\r
+      }\r
+    },\r
+    components: {\r
+      editor,\r
+      wfresult\r
+    }\r
+}\r
+</script>
\ No newline at end of file