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