summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeoQi <QibinZheng2014@tongji.edu.cn>2018-07-20 02:58:47 +0800
committerLeoQi <QibinZheng2014@tongji.edu.cn>2018-08-30 19:06:15 +0800
commitdae60f00ff56acd4a57c750ad342a85a7a5d835c (patch)
tree71f952c077505e0307ca6d8fccf54f0fd1eafd03
parentad12a6561be8c67f6da09c38c4e1c0e88eb9a6de (diff)
the environment page in frontend of testing-scheduler
JIRA: BOTTLENECK-238 the environment page provides configuration setting operations. Change-Id: I79f93bfc0c66c37a3f58d042669cbb61d3bad848 Signed-off-by: Zheng Qibin <QibinZheng2014@tongji.edu.cn>
-rw-r--r--testing-scheduler/ui/src/components/env_component/api_param.vue63
-rw-r--r--testing-scheduler/ui/src/components/env_component/base_input.vue20
-rw-r--r--testing-scheduler/ui/src/components/env_component/service_api.vue112
-rw-r--r--testing-scheduler/ui/src/components/env_component/service_modal.vue193
-rw-r--r--testing-scheduler/ui/src/components/environment.vue239
5 files changed, 627 insertions, 0 deletions
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
index 00000000..300b6a48
--- /dev/null
+++ b/testing-scheduler/ui/src/components/env_component/api_param.vue
@@ -0,0 +1,63 @@
+<template>
+ <div class="row">
+ <div class="form-group">
+ <label class="col-lg-3 control-label">Params</label>
+ <div class="col-lg-2">
+ <button type="button" class="btn btn-primary btn-sm" v-on:click="addNewParam()">New</button>
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="col-lg-offset-2 col-lg-8">
+ <div class="table-responsive">
+ <table class="table table-bordered text-center">
+ <thead>
+ <tr>
+ <th>name</th>
+ <th class="text-center">description</th>
+ <th class="text-center">operation</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="param in params">
+ <td><input type="text" class="form-control text-center" style="border: 0px" v-model="param['name']"></td>
+ <td><input type="text" class="form-control text-center" style="border: 0px" v-bind:title="param['description']" v-model="param['description']"></td>
+ <td>
+ <button type="button" class="btn btn-white" v-on:click="deleteParam(param['name'])">
+ <i class="fa fa-trash"></i>
+ </button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: ["params"],
+ data: function() {
+ return {
+ paramArr: this.params
+ }
+ },
+ watch: {
+ paramArr: function(){
+ this.$emit("params", this.paramArr);
+ }
+ },
+ methods: {
+ addNewParam: function() {
+ this.params.push({'name': '', 'description': ''});
+ },
+ deleteParam: function(paramName) {
+ for(var i = 0;i < this.params.length; i++) {
+ if(paramName == this.params[i]['name']) {
+ this.params.splice(i, 1);
+ }
+ }
+ }
+ }
+}
+</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
index 00000000..d96921a5
--- /dev/null
+++ b/testing-scheduler/ui/src/components/env_component/base_input.vue
@@ -0,0 +1,20 @@
+<template>
+ <div class="form-group">
+ <label class="col-lg-3 control-label">{{ name }}</label>
+ <div class="col-lg-7">
+ <input type="text" class="form-control" v-bind:value="value" v-on:input="$emit('input', $event.target.value)">
+ </div>
+ </div>
+</template>
+<script>
+export default {
+ props: ['name', 'value'],
+ data: function() {
+ return {
+ inputName: this.name,
+ inputValue: this.value,
+ fake: "abc"
+ }
+ }
+}
+</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
index 00000000..2acd4994
--- /dev/null
+++ b/testing-scheduler/ui/src/components/env_component/service_api.vue
@@ -0,0 +1,112 @@
+<template>
+ <div class="panel panel-success">
+ <div class="panel-heading">
+ <button type="button" class="btn btn-xs btn-danger pull-right" v-on:click="deleteApi(name)">Delete</button>
+ <h5 class="panel-title">
+ <a data-toggle="collapse" data-parent="panelParent" v-bind:href="'#' + name + '-collapse'" style="display:block;">{{ name }}</a>
+ </h5>
+ </div>
+ <div v-bind:id="name + '-collapse'" class="panel-collapse collapse fade">
+ <div class="panel-body">
+ <base-input name="name" v-model="name"></base-input>
+ <base-input name="method" v-model="method"></base-input>
+ <base-input name="baseuri" v-model="baseuri"></base-input>
+ <api-param v-bind:params="params"></api-param>
+ <div class="form-group" v-bind:class="{ 'has-error': jsonSyntaxError}">
+ <label class="col-lg-3 control-label" id="templateLabel">
+ Template <i class="fa fa-question-circle"></i>
+ </label>
+ <div class="col-lg-7">
+ <!-- help text -->
+ <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>
+ <textarea class="form-control" style="min-height: 200px;" v-model="templateStr"></textarea>
+ <span class="help-block" v-show="jsonSyntaxError">Json语法错误,请检查!</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+import base_input from "./base_input.vue"
+import api_param from "./api_param.vue"
+import Vue from "vue"
+export default {
+ props: ['panelParent', 'name', 'method', 'baseuri', 'params', 'template'],
+ watch: {
+ name: function(val) {
+ this.$emit("name", val);
+ },
+ method: function(val) {
+ this.$emit("method", val);
+ },
+ baseuri: function(val) {
+ this.$emit("baseuri", val);
+ },
+ params: function(val) {
+ this.$emit("params", val);
+ },
+ templateStr: function(val) {
+ try {
+ console.log(JSON.parse(val));
+ this.jsonSyntaxError = false;
+ this.$emit("template", JSON.parse(val));
+ } catch(err) {
+ console.log("catch the exception templateStr");
+ this.jsonSyntaxError = true;
+ }
+ }
+ },
+ components: {
+ 'base-input': base_input,
+ 'api-param': api_param
+ },
+ data: function() {
+ return {
+ jsonSyntaxError: false,
+ templateStr: JSON.stringify(this.template, null, 2)
+ };
+ },
+ methods: {
+ deleteApi: function(apiName) {
+ this.$emit("delete", apiName);
+ }
+ }
+}
+</script>
+<style scoped>
+#templateLabel:hover+div #tempHelp{
+ display: block;
+}
+#tempHelp {
+ display: none;
+ position: absolute;
+ width: 90%;
+ min-height: 150px;
+ background-color: #ab2d2d;
+ color: white;
+ transition: display 1s;
+ text-align: left;
+ padding: 10px 16px;
+ z-index: 2;
+ font-size: 10px;
+ opacity: 0.9;
+}
+#tempHelp::after {
+ content: '';
+ position: absolute;
+ bottom: 92%;
+ right: 100%;
+ margin-left: -5px;
+ border-width: 5px;
+ border-style: solid;
+ border-color: transparent #ab2d2d transparent transparent;
+}
+@media(max-width:1200px) {
+ #tempHelp::after {
+ bottom: 100%;
+ left: 5%;
+ border-color: transparent transparent #ab2d2d transparent;
+ }
+}
+</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
index 00000000..015c91cd
--- /dev/null
+++ b/testing-scheduler/ui/src/components/env_component/service_modal.vue
@@ -0,0 +1,193 @@
+<template>
+ <div class="modal inmodal fade" id="myModal">
+ <div class="modal-dialog modal-lg">
+ <div class="modal-content animated">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">
+ <span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
+ </button>
+ <h3 class="modal-title">{{type.service}}</h3>
+ </div>
+ <div class="modal-body">
+ <div class="row">
+ <form method="get" class="form-horizontal">
+ <div id="service-address">
+ <button class="btn btn-default">Basic</button>
+ <div class="form-group">
+ <label class="col-sm-3 control-label">name</label>
+ <div class="col-sm-7">
+ <input type="text" class="form-control service-title" v-model="type.service" placeholder="please input service name.">
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-3 control-label">ip</label>
+ <div class="col-sm-7"><input type="text" class="form-control" v-model="ip"></div>
+ </div>
+ <div class="form-group">
+ <label class="col-sm-3 control-label">port</label>
+ <div class="col-sm-7"><input type="text" class="form-control" v-model="port"></div>
+ </div>
+ </div>
+ <div class="hr-line-dashed"></div>
+ <div id="service-apis">
+ <div id="apis-nav">
+ <button class="btn btn-default">Apis</button>
+ </div>
+ <br />
+ <div id="api-panels" class="api col-sm-offset-1 col-sm-10">
+ <div class="panel-group" id="accordion">
+ <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>
+ </div>
+ <button type="button" class="btn btn-primary pull-right" v-on:click="addNewApi()">New</button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-white" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary" v-on:click="save()">Save changes</button>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+import service_api from "./service_api.vue";
+import showMessage from '../message/showMessage.js'
+export default {
+ props: ['type'],
+ data: function() {
+ return {
+ typeTag: this.type.tag,
+ ip: "",
+ port: "",
+ apis: []
+ }
+ },
+ created: function() {
+ },
+ watch: {
+ type: {
+ handler: function(newVal, oldVal) {
+ console.log("###########type is changed!");
+ if(newVal.content) {
+ var content = newVal.content;
+ this.ip = content.ip;
+ this.port = content.port;
+ this.apis = content.apis;
+ console.log(this.apis);
+ } else {
+ this.resetModalData();
+ }
+ console.log("end!");
+ },
+ deep: true
+ }
+ },
+ methods: {
+ addNewApi: function() {
+ var newApi = {'name': 'new', 'method': 'GET', 'baseuri': '', 'params': [], 'template': {"uri": "((baseuri))"}};
+ this.apis.push(newApi);
+ },
+ removeApi: function(name) {
+ for(var i = 0; i < this.apis.length; i++) {
+ if(name == this.apis[i]['name']) {
+ this.apis.splice(i, 1);
+ }
+ }
+ },
+ save: function() {
+ if(this.ip == "") {
+ showMessage("warning", "SERVICE", "ip is not filled!");
+ return;
+ } else if (this.port == "") {
+ showMessage("warning", "SERVICE", "port is not filled!");
+ return;
+ } else if (this.type.service == "") {
+ showMessage("warning", "SERVICE", "service name is not filled!");
+ return;
+ }
+ if(this.type.edit == true) {
+ this.saveEdition();
+ } else {
+ this.saveCreation();
+ }
+ this.resetModalData();
+ $("#myModal").modal("hide");
+ },
+ saveEdition: function() {
+ var self = this;
+ var msgTitle = "SAVE -- SERVICE";
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/editService",
+ method: "post",
+ data: {
+ "oldName": self.type.originName,
+ "newName": self.type.service,
+ "ip": self.ip,
+ "port": self.port,
+ "apis": JSON.stringify(self.apis),
+ },
+ success: function(data) {
+ if(data['code'] == 200) {
+ showMessage("success", msgTitle, "Save service <strong>" + self.type.service + "</strong> successfully!");
+ } else {
+ showMessage(data['code'], msgTitle, "Failed to save service <strong>" + self.type.service + "</strong>!", data['error']);
+ }
+ },
+ error: function() {
+ showMessage("error", msgTitle, "Failed to save service <strong>" + self.type.service + "</strong>!", msg);
+ }
+ });
+ var edition = {
+ 'oldName': this.type.originName,
+ 'newName': this.type.service
+ };
+ this.$emit("service-edition", edition);
+ },
+ saveCreation: function() {
+ console.log("save creation!!!");
+ var self = this;
+ var msgTitle = "CREATE -- SERVICE";
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/createService",
+ method: "post",
+ data: {
+ "name": self.type.service,
+ "ip": self.ip,
+ "port": self.port,
+ "apis": JSON.stringify(self.apis)
+ },
+ success: function(data) {
+ if(data['code'] == 200) {
+ showMessage("success", msgTitle, "Create <strong>"+ self.type.service + "</strong> successfully!");
+ } else {
+ showMessage(data['code'], msgTitle, "Failed to create service <strong>" + self.type.service + "</strong>!", data['error']);
+ self.$emit("creation-fail", self.type.service);
+ }
+ },
+ error: function() {
+ showMessage("error", msgTitle, "Failed to create service <strong>" + self.type.service + "</strong>!", msg);
+ self.$emit("creation-fail", self.type.service);
+ }
+ });
+ this.$emit("service-creation", this.type.service);
+ },
+ resetModalData: function() {
+ this.ip = "";
+ this.port = "";
+ this.apis = [];
+ },
+ getData: function() {
+ console.log("apis:");
+ for(i in this.apis) {
+ console.log(this.apis[i]);
+ }
+ }
+ },
+ components: {
+ 'service-api': service_api
+ }
+}
+</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
index 00000000..1b9a89f1
--- /dev/null
+++ b/testing-scheduler/ui/src/components/environment.vue
@@ -0,0 +1,239 @@
+<template>
+<div class="wrapper wrapper-content">
+ <div class="row">
+ <div class="col-lg-offset-2 col-lg-8">
+ <div class="ibox">
+ <div class="ibox-content">
+ <h1>CONTEXT <i class="fa fa-question-circle"></i></h1>
+ <div class="row">
+ <div class="col-md-offset-1 col-md-10">
+ <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;">
+ </textarea>
+ <button type="button" class="btn btn-primary pull-right" v-on:click="saveContext()">Save</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-offset-2 col-lg-8">
+ <div class="ibox">
+ <div class="ibox-content">
+ <h1>Service</h1>
+ <div class="service-table">
+ <table id="serviceList" class="table table-bordered table-hover text-center">
+ <thead>
+ <tr>
+ <th class="text-center">No</th>
+ <th class="text-center">Service</th>
+ <th class="text-center">Time</th>
+ <th class="text-center">Operation</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="service in serviceList" v-on:click="editService(service.name)" style="cursor: pointer;">
+ <td style="vertical-align: middle;">{{ service.id }}</td>
+ <td style="vertical-align: middle;">{{ service.name }}</td>
+ <td style="vertical-align: middle;">{{ service.time }}</td>
+ <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>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div>
+ <button class="btn btn-lg btn-success" style="float:right;" v-on:click="addNewService()"> Add </button>
+ </div>
+ </div>
+ <!-- modal of one service -->
+ <div class="row">
+ <service-modal v-bind:type="type" v-on:service-creation="plusAService" v-on:service-edition="editAServiceName" v-on:creation-fail="creationFailHandler"></service-modal>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+</template>
+<script>
+import Vue from 'vue'
+import service_modal from "./env_component/service_modal.vue"
+import showMessage from './message/showMessage.js'
+export default {
+ name: 'environment',
+ data: function() {
+ return {
+ serviceList: [],
+ type: {
+ edit: true,
+ service: "ansible",
+ tag: "default"
+ },
+ context: ''
+ }
+ },
+ components: {
+ 'service-modal': service_modal
+ },
+ created: function() {
+ var self = this;
+ var msgTitle = "GET -- SERVICE LIST";
+ var errorInfo = 'Unable to get the service list';
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/getAllServices",
+ method: "GET",
+ success: function(data) {
+ if(data['code'] == 200) {
+ self.serviceList = data['result'];
+ } else {
+ showMessage(data['code'], msgTitle, errorInfo, data['error']);
+ }
+ },
+ error: function(obj, status, msg) {
+ showMessage("error", msgTitle, errorInfo, msg);
+ }
+ });
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/getContext",
+ method: "GET",
+ success: function(data) {
+ if(data['code'] == 200) {
+ self.context = data['result']['context'];
+ } else {
+ showMessage(data['code'], msgTitle, errorInfo, data['error']);
+ }
+ },
+ error: function(obj, status, msg) {
+ showMessage("error", msgTitle, errorInfo, msg);
+ }
+ });
+ },
+ methods: {
+ addNewService: function(){
+ this.type.edit = false;
+ this.type.tag = "abc";
+ this.type.service = null;
+ this.type.originName = null;
+ if(this.type.content){
+ this.type.content = null;
+ }
+ $("#myModal").modal("show");
+ },
+ plusAService: function(serviceName){
+ var item = {'id': '', 'name': '', 'time': ''};
+ item['id'] = this.serviceList[this.serviceList.length - 1]['id'] + 1;
+ item['name'] = serviceName;
+ item['time'] = this.getFormatDate(new Date());
+ this.serviceList.push(item);
+ },
+ editAServiceName: function(edition) {
+ for(var i = 0;i < this.serviceList.length; i++) {
+ if(edition['oldName'] == this.serviceList[i]['name']) {
+ this.serviceList[i]['name'] = edition['newName'];
+ }
+ }
+ },
+ editService: function(serviceName){
+ this.type.edit = true;
+ this.type.tag = "abc";
+ this.type.service = serviceName;
+ this.type.originName = serviceName;
+ if(this.type.content){
+ this.type.content = null;
+ }
+ console.log(this.type);
+ var self = this;
+ var msgTitle = "GET -- SERVICE";
+ var errorInfo = "Unable to get the service: <strong>" + self.type.service + "</strong>";
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/getService",
+ method: "GET",
+ data: {
+ "serviceName": serviceName
+ },
+ success: function(data) {
+ if(data['code'] == 200) {
+ self.type.tag = "hhh";
+ self.type.content = data['result'];
+ self.type.originName = self.type.service;
+ } else {
+ showMessage(data['code'], msgTitle, errorInfo, data['error']);
+ }
+ },
+ error: function(obj, status, msg) {
+ showMessage("error", msgTitle, errorInfo, msg);
+ }
+ });
+ $("#myModal").modal("show");
+ },
+ deleteService: function(serviceName){
+ var msgTitle = "DELETE -- SERVICE";
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/deleteService",
+ method: "POST",
+ data: {
+ "serviceName": serviceName
+ },
+ success: function(data) {
+ if(data['code'] == 200) {
+ showMessage(data['code'], msgTitle, "Delete <strong>" + serviceName + "</strong> successfully.");
+ } else {
+ showMessage(data['code'], msgTitle, "Failed to delete <strong>" + serviceName + "</strong>", data['error']);
+ }
+ },
+ error: function(obj, status, msg) {
+ showMessage("error", msgTitle, "Failed to delete <strong>" + serviceName + "</strong>", msg);
+ }
+ });
+ for(var i = 0;i < this.serviceList.length; i++) {
+ if(serviceName == this.serviceList[i]['name']) {
+ this.serviceList.splice(i, 1);
+ }
+ }
+ },
+ creationFailHandler: function(serviceName) {
+ for(var i = 0; i < this.serviceList.length; i++) {
+ if(serviceName == this.serviceList[i].name) {
+ this.serviceList.splice(i, 1);
+ }
+ }
+ },
+ getFormatDate: function(date) {
+ var year = date.getFullYear();
+ var month = date.getMonth() + 1;
+ var strDate = date.getDate();
+ var seperator = "-";
+ if(month >= 1 && month <= 9) {
+ month = "0" + month;
+ }
+ if(strDate >= 1 && strDate <= 9) {
+ strDate = "0" + strDate;
+ }
+ var formatDate = year + seperator + month + seperator + strDate;
+ return formatDate;
+ },
+ saveContext: function() {
+ var self = this;
+ var msgTitle = "SAVE -- CONTEXT";
+ var errorInfo = "Failed to save context!";
+ $.ajax({
+ url: this.global.SERVER_ADDR + "env/editContext",
+ method: "POST",
+ data: {
+ context: self.context
+ },
+ success: function(data) {
+ if(data['code'] == 200) {
+ showMessage(data['code'], msgTitle, "Save context successfully!");
+ } else {
+ showMessage(data['code'], msgTitle, errorInfo, data['error']);
+ }
+ },
+ error: function(obj, status, msg) {
+ showMessage("error", msgTitle, errorInfo, msg);
+ }
+ });
+ }
+ }
+}
+</script> \ No newline at end of file